omnimancer-cli 0.2.22__tar.gz → 0.2.24__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 (167) hide show
  1. {omnimancer_cli-0.2.22/omnimancer_cli.egg-info → omnimancer_cli-0.2.24}/PKG-INFO +53 -5
  2. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/README.md +50 -3
  3. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/__init__.py +12 -4
  4. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/cli/approval_integration.py +54 -0
  5. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/cli/command_dispatch.py +326 -12
  6. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/cli/commands.py +13 -10
  7. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/cli/completion.py +83 -67
  8. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/cli/display.py +52 -12
  9. omnimancer_cli-0.2.24/omnimancer/cli/file_mentions.py +170 -0
  10. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/cli/headless.py +2 -24
  11. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/cli/interface.py +138 -50
  12. omnimancer_cli-0.2.24/omnimancer/cli/prompt_input.py +186 -0
  13. omnimancer_cli-0.2.24/omnimancer/cli/pt_completion.py +172 -0
  14. omnimancer_cli-0.2.24/omnimancer/cli/usage.py +27 -0
  15. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/config_manager.py +16 -2
  16. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/config_migration.py +27 -2
  17. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/config_validator.py +4 -1
  18. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/models.py +46 -4
  19. omnimancer_cli-0.2.24/omnimancer/core/prompt_enhancer.py +326 -0
  20. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/provider_capabilities.py +24 -8
  21. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/provider_initializer.py +26 -7
  22. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/providers/__init__.py +2 -0
  23. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/providers/factory.py +26 -4
  24. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/providers/openai.py +257 -17
  25. omnimancer_cli-0.2.24/omnimancer/providers/openai_compatible.py +143 -0
  26. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/providers/openrouter.py +2 -1
  27. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/ui/streaming_display.py +12 -2
  28. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24/omnimancer_cli.egg-info}/PKG-INFO +53 -5
  29. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer_cli.egg-info/SOURCES.txt +10 -0
  30. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer_cli.egg-info/requires.txt +2 -1
  31. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/pyproject.toml +5 -2
  32. omnimancer_cli-0.2.24/tests/test_config_migration_passthrough.py +81 -0
  33. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_import_validation.py +23 -0
  34. omnimancer_cli-0.2.24/tests/test_openai_compatible_provider.py +209 -0
  35. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_openai_provider_tools.py +39 -0
  36. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_openai_request_timeout.py +24 -0
  37. omnimancer_cli-0.2.24/tests/test_openai_streaming.py +252 -0
  38. omnimancer_cli-0.2.24/tests/test_provider_aliases.py +117 -0
  39. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_provider_discovery.py +1 -0
  40. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/LICENSE +0 -0
  41. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/__main__.py +0 -0
  42. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/cli/__init__.py +0 -0
  43. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/cli/agent_loop.py +0 -0
  44. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/cli/approval_formatter.py +0 -0
  45. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/cli/approval_prompt.py +0 -0
  46. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/cli/dynamic_commands.py +0 -0
  47. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/cli/handlers/__init__.py +0 -0
  48. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/cli/subagent.py +0 -0
  49. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/cli/system_prompts.py +0 -0
  50. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/cli/tool_handler.py +0 -0
  51. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/__init__.py +0 -0
  52. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/agent/__init__.py +0 -0
  53. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/agent/approval_context.py +0 -0
  54. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/agent/approval_interface.py +0 -0
  55. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/agent/approval_manager.py +0 -0
  56. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/agent/config.py +0 -0
  57. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/agent/file_system_manager.py +0 -0
  58. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/agent/program_executor.py +0 -0
  59. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/agent/read_before_write_errors.py +0 -0
  60. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/agent/status_core.py +0 -0
  61. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/agent/status_manager.py +0 -0
  62. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/agent/tool_definitions.py +0 -0
  63. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/agent/types.py +0 -0
  64. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/agent/web_client.py +0 -0
  65. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/agent/workflow_orchestrator.py +0 -0
  66. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/agent_engine.py +0 -0
  67. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/agent_managers.py +0 -0
  68. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/agent_mode_manager.py +0 -0
  69. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/chat_manager.py +0 -0
  70. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/conversation_manager.py +0 -0
  71. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/engine.py +0 -0
  72. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/env_loader.py +0 -0
  73. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/fallback_manager.py +0 -0
  74. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/health_monitor.py +0 -0
  75. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/history_manager.py +0 -0
  76. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/hooks.py +0 -0
  77. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/mcp_integration_layer.py +0 -0
  78. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/provider_registry.py +0 -0
  79. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/rate_limit_fallback.py +0 -0
  80. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/security/__init__.py +0 -0
  81. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/security/approval_workflow.py +0 -0
  82. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/security/audit_logger.py +0 -0
  83. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/security/permission_controller.py +0 -0
  84. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/security/permission_rules.py +0 -0
  85. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/security/sandbox_manager.py +0 -0
  86. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/security/security_manager.py +0 -0
  87. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/core/signal_handler.py +0 -0
  88. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/mcp/__init__.py +0 -0
  89. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/mcp/client.py +0 -0
  90. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/mcp/manager.py +0 -0
  91. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/providers/azure.py +0 -0
  92. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/providers/base.py +0 -0
  93. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/providers/bedrock.py +0 -0
  94. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/providers/claude.py +0 -0
  95. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/providers/claude_code.py +0 -0
  96. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/providers/claude_credentials.py +0 -0
  97. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/providers/cohere.py +0 -0
  98. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/providers/digitalocean.py +0 -0
  99. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/providers/gemini.py +0 -0
  100. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/providers/mistral.py +0 -0
  101. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/providers/ollama.py +0 -0
  102. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/providers/perplexity.py +0 -0
  103. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/providers/vertex.py +0 -0
  104. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/providers/xai.py +0 -0
  105. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/ui/__init__.py +0 -0
  106. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/ui/cancellation_handler.py +0 -0
  107. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/ui/progress_indicator.py +0 -0
  108. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/utils/__init__.py +0 -0
  109. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/utils/error_handler.py +0 -0
  110. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/utils/errors.py +0 -0
  111. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer/utils/retry.py +0 -0
  112. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer_cli.egg-info/dependency_links.txt +0 -0
  113. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer_cli.egg-info/entry_points.txt +0 -0
  114. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/omnimancer_cli.egg-info/top_level.txt +0 -0
  115. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/setup.cfg +0 -0
  116. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_approval_integration_compatibility.py +0 -0
  117. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_approval_preview_format.py +0 -0
  118. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_approval_remember.py +0 -0
  119. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_approval_system.py +0 -0
  120. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_azure_provider.py +0 -0
  121. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_bedrock_provider.py +0 -0
  122. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_claude_code_provider.py +0 -0
  123. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_claude_credentials.py +0 -0
  124. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_claude_provider.py +0 -0
  125. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_cohere_provider.py +0 -0
  126. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_command_approval_security.py +0 -0
  127. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_config_comprehensive.py +0 -0
  128. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_conversation_history.py +0 -0
  129. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_conversation_manager.py +0 -0
  130. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_core_engine.py +0 -0
  131. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_digitalocean_provider.py +0 -0
  132. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_enhanced_model_info.py +0 -0
  133. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_env_loader.py +0 -0
  134. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_error_handling_robustness.py +0 -0
  135. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_execution_timeout_errors.py +0 -0
  136. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_fallback_manager.py +0 -0
  137. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_fixtures.py +0 -0
  138. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_gemini_provider.py +0 -0
  139. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_hooks.py +0 -0
  140. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_httpx_compatibility.py +0 -0
  141. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_interface_smoke_tests.py +0 -0
  142. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_mcp_integration.py +0 -0
  143. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_mcp_integration_layer.py +0 -0
  144. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_mcp_management_commands.py +0 -0
  145. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_mistral_provider.py +0 -0
  146. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_models.py +0 -0
  147. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_ollama_provider.py +0 -0
  148. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_openai_context_fit.py +0 -0
  149. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_openrouter_provider.py +0 -0
  150. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_permission_rules.py +0 -0
  151. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_perplexity_provider.py +0 -0
  152. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_program_executor.py +0 -0
  153. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_provider_base.py +0 -0
  154. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_provider_capability_consistency.py +0 -0
  155. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_provider_integration.py +0 -0
  156. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_provider_registry.py +0 -0
  157. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_rate_limit_fallback.py +0 -0
  158. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_retry.py +0 -0
  159. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_security_validation.py +0 -0
  160. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_system_integration.py +0 -0
  161. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_system_prompts.py +0 -0
  162. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_tool_calling_integration.py +0 -0
  163. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_tool_handler.py +0 -0
  164. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_vertex_provider.py +0 -0
  165. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_web_request_markers.py +0 -0
  166. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/tests/test_workflows_comprehensive.py +0 -0
  167. {omnimancer_cli-0.2.22 → omnimancer_cli-0.2.24}/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.2.22
3
+ Version: 0.2.24
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
@@ -37,7 +37,8 @@ Requires-Dist: jsonschema>=4.17.0
37
37
  Requires-Dist: readability-lxml>=0.8.1
38
38
  Requires-Dist: PyYAML>=6.0.0
39
39
  Requires-Dist: toml>=0.10.2
40
- Requires-Dist: mcp>=1.0.0
40
+ Requires-Dist: mcp<2,>=1.0.0
41
+ Requires-Dist: prompt-toolkit<4.0,>=3.0.43
41
42
  Provides-Extra: dev
42
43
  Requires-Dist: pytest>=7.0.0; extra == "dev"
43
44
  Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
@@ -49,9 +50,11 @@ Requires-Dist: flake8>=6.0.0; extra == "dev"
49
50
  Requires-Dist: mypy>=1.0.0; extra == "dev"
50
51
  Dynamic: license-file
51
52
 
52
- # Omnimancer
53
+ <p align="center">
54
+ <img src="assets/omnimancer.png" alt="Omnimancer" width="600">
55
+ </p>
53
56
 
54
- A multi-model coding agent for the terminal. One tool, any LLM.
57
+ <p align="center"><strong>A multi-model coding agent for the terminal. One tool, any LLM.</strong></p>
55
58
 
56
59
  Omnimancer works like `claude -p` but isn't locked to a single provider. Point it at Claude, OpenAI, Gemini, Bedrock, Ollama, or any of 13+ supported backends and get a coding agent that reads files, writes code, runs commands, and iterates autonomously — with streaming responses, token/cost tracking, and structured JSON output for pipeline integration.
57
60
 
@@ -62,6 +65,10 @@ Beyond the basics, it ships with:
62
65
  - **Permission rules** — declarative allow/deny/ask rules per tool with regex matchers
63
66
  - **Subagents** — scoped child agents with their own prompt, tool whitelist, and model
64
67
  - **Layered security** — approval workflow, sensitive-path protection, and project-boundary enforcement
68
+ - **Named endpoint aliases** — run several OpenAI-compatible endpoints (vLLM, llama.cpp, LM Studio) side by side as first-class providers, keyless if the endpoint is
69
+ - **Modern input layer** — prompt_toolkit prompt with multiline editing, fuzzy `@file` mentions with content injection, live completion for providers/models, Ctrl-R history search
70
+ - **Prompt enhancement** — `e:` prefix or `/enhance` rewrites your draft with a configurable small model before sending (PromptFoundry meta-prompts)
71
+ - **Session approval modes** — `/accept edits|all` (or Shift+Tab) for claude-code-style auto-accept, always below your permission rules
65
72
 
66
73
  ## Install
67
74
 
@@ -166,6 +173,7 @@ Streaming is automatic for providers that support it. Other providers fall back
166
173
  | Provider | Streaming |
167
174
  |----------|:---------:|
168
175
  | Claude (Anthropic) | Yes |
176
+ | OpenAI / openai-compatible / DigitalOcean | Yes (SSE, incl. tool-call deltas) |
169
177
  | All others | Fallback (full response) |
170
178
 
171
179
  Streaming works in both regular chat and agent mode (tool calling flow). The display uses a live-updating terminal panel that refreshes at 15fps.
@@ -244,7 +252,8 @@ Tool names match the agent's toolset (`Read`, `Write`, `Edit`, `Bash`, `Glob`, `
244
252
  | `/quit` | Exit (also: `/exit`, Ctrl+D) |
245
253
  | `/clear` | Clear terminal screen |
246
254
  | `/switch <provider> [model]` | Switch provider or model (uncataloged models are registered on the fly) |
247
- | `/models [filter]` | List available models (alias: `/model`) |
255
+ | `/models [filter]` | List available models; `/models refresh [provider]` pulls live catalogs |
256
+ | `/model` | Interactive model picker for the current provider |
248
257
  | `/providers` | List all providers with status |
249
258
  | `/agent on\|off\|status` | Toggle agent mode |
250
259
  | `/subagents [run <name> <task>]` | List or run scoped child agents |
@@ -253,6 +262,8 @@ Tool names match the agent's toolset (`Read`, `Write`, `Edit`, `Bash`, `Glob`, `
253
262
  | `/config remove-provider <name>` | Remove a provider |
254
263
  | `/hooks [list\|on\|off\|add\|remove]` | Manage lifecycle hooks |
255
264
  | `/permissions [list\|on\|off\|allow\|deny\|ask\|remove]` | Manage permission rules |
265
+ | `/accept [edits\|all\|off]` | Session approval mode (Shift+Tab cycles it at the prompt) |
266
+ | `/enhance [chat\|code\|image\|research] <draft>` | Rewrite a draft prompt with the enhancement model, confirm, send (the `e:` message prefix does it inline) |
256
267
  | `/save [name]` | Save conversation |
257
268
  | `/load [name]` | Load conversation |
258
269
  | `/list` | List saved conversations |
@@ -426,6 +437,39 @@ several endpoints side by side and switch between them with `/switch <provider>`
426
437
  Any OpenAI-compatible service (local proxy, gateway, self-hosted model) works by
427
438
  overriding `base_url` on the `openai` provider.
428
439
 
440
+
441
+ ### Self-hosted endpoints as named providers
442
+
443
+ Any number of OpenAI-compatible endpoints (vLLM, llama.cpp server, LM Studio, proxies) can be configured side by side under names you choose. `provider_type` picks the implementation; the entry name is yours:
444
+
445
+ ```bash
446
+ >>> /config set-provider gateway --type openai-compatible \
447
+ --base-url http://vllm-gateway.internal:8888/v1 --model qwen3-coder-30b
448
+ >>> /config set-provider local --type openai-compatible \
449
+ --base-url http://localhost:8000/v1 --model qwen3-coder-30b
450
+ >>> /switch local
451
+ ```
452
+
453
+ The `openai-compatible` type is keyless by default (`auth_type: "none"`), takes its model catalog from the endpoint's `/v1/models` (including each model's served context size — see `/models refresh`), and raises timeout errors with a cold-start hint since self-hosted gateways may load a model on first request. Set `providers.<name>.timeout` generously for such endpoints (e.g. `360`).
454
+
455
+ ### Prompt enhancement (optional)
456
+
457
+ `/enhance` and the `e:` message prefix rewrite a draft prompt with a dedicated model before sending, using the [PromptFoundry](https://github.com/gitshipdone/promptfoundry) meta-prompts (same author; that repo is the canonical source for the prompt texts and is being prepared for public release).
458
+
459
+ The feature is **opt-in**: it activates only when your config carries an `enhancement` block. Without one, `e:` is not intercepted and `/enhance` points you here.
460
+
461
+ ```json
462
+ "enhancement": {
463
+ "provider": "gateway",
464
+ "model": "qwen3-8b",
465
+ "temperature": 0.4,
466
+ "default_profile": "code",
467
+ "enabled": true
468
+ }
469
+ ```
470
+
471
+ `provider` must name an entry in `providers`; `default_profile` is one of `chat`, `code`, `image`, `research`. Failsafe chain: the configured model is tried first; if it is unreachable, the model you are currently chatting with rewrites the draft instead; if everything fails, the original draft is sent unchanged — enhancement never blocks a message.
472
+
429
473
  ### Environment variable overrides
430
474
 
431
475
  Environment variables take precedence over the saved config and are applied at
@@ -571,3 +615,7 @@ Tests follow TDD. 1,460 tests across providers, CLI, streaming, agent operations
571
615
  ## License
572
616
 
573
617
  MIT
618
+
619
+ ---
620
+
621
+ *This documentation was reviewed by a local Qwen model as part of OMN testing harness.*
@@ -1,6 +1,8 @@
1
- # Omnimancer
1
+ <p align="center">
2
+ <img src="assets/omnimancer.png" alt="Omnimancer" width="600">
3
+ </p>
2
4
 
3
- A multi-model coding agent for the terminal. One tool, any LLM.
5
+ <p align="center"><strong>A multi-model coding agent for the terminal. One tool, any LLM.</strong></p>
4
6
 
5
7
  Omnimancer works like `claude -p` but isn't locked to a single provider. Point it at Claude, OpenAI, Gemini, Bedrock, Ollama, or any of 13+ supported backends and get a coding agent that reads files, writes code, runs commands, and iterates autonomously — with streaming responses, token/cost tracking, and structured JSON output for pipeline integration.
6
8
 
@@ -11,6 +13,10 @@ Beyond the basics, it ships with:
11
13
  - **Permission rules** — declarative allow/deny/ask rules per tool with regex matchers
12
14
  - **Subagents** — scoped child agents with their own prompt, tool whitelist, and model
13
15
  - **Layered security** — approval workflow, sensitive-path protection, and project-boundary enforcement
16
+ - **Named endpoint aliases** — run several OpenAI-compatible endpoints (vLLM, llama.cpp, LM Studio) side by side as first-class providers, keyless if the endpoint is
17
+ - **Modern input layer** — prompt_toolkit prompt with multiline editing, fuzzy `@file` mentions with content injection, live completion for providers/models, Ctrl-R history search
18
+ - **Prompt enhancement** — `e:` prefix or `/enhance` rewrites your draft with a configurable small model before sending (PromptFoundry meta-prompts)
19
+ - **Session approval modes** — `/accept edits|all` (or Shift+Tab) for claude-code-style auto-accept, always below your permission rules
14
20
 
15
21
  ## Install
16
22
 
@@ -115,6 +121,7 @@ Streaming is automatic for providers that support it. Other providers fall back
115
121
  | Provider | Streaming |
116
122
  |----------|:---------:|
117
123
  | Claude (Anthropic) | Yes |
124
+ | OpenAI / openai-compatible / DigitalOcean | Yes (SSE, incl. tool-call deltas) |
118
125
  | All others | Fallback (full response) |
119
126
 
120
127
  Streaming works in both regular chat and agent mode (tool calling flow). The display uses a live-updating terminal panel that refreshes at 15fps.
@@ -193,7 +200,8 @@ Tool names match the agent's toolset (`Read`, `Write`, `Edit`, `Bash`, `Glob`, `
193
200
  | `/quit` | Exit (also: `/exit`, Ctrl+D) |
194
201
  | `/clear` | Clear terminal screen |
195
202
  | `/switch <provider> [model]` | Switch provider or model (uncataloged models are registered on the fly) |
196
- | `/models [filter]` | List available models (alias: `/model`) |
203
+ | `/models [filter]` | List available models; `/models refresh [provider]` pulls live catalogs |
204
+ | `/model` | Interactive model picker for the current provider |
197
205
  | `/providers` | List all providers with status |
198
206
  | `/agent on\|off\|status` | Toggle agent mode |
199
207
  | `/subagents [run <name> <task>]` | List or run scoped child agents |
@@ -202,6 +210,8 @@ Tool names match the agent's toolset (`Read`, `Write`, `Edit`, `Bash`, `Glob`, `
202
210
  | `/config remove-provider <name>` | Remove a provider |
203
211
  | `/hooks [list\|on\|off\|add\|remove]` | Manage lifecycle hooks |
204
212
  | `/permissions [list\|on\|off\|allow\|deny\|ask\|remove]` | Manage permission rules |
213
+ | `/accept [edits\|all\|off]` | Session approval mode (Shift+Tab cycles it at the prompt) |
214
+ | `/enhance [chat\|code\|image\|research] <draft>` | Rewrite a draft prompt with the enhancement model, confirm, send (the `e:` message prefix does it inline) |
205
215
  | `/save [name]` | Save conversation |
206
216
  | `/load [name]` | Load conversation |
207
217
  | `/list` | List saved conversations |
@@ -375,6 +385,39 @@ several endpoints side by side and switch between them with `/switch <provider>`
375
385
  Any OpenAI-compatible service (local proxy, gateway, self-hosted model) works by
376
386
  overriding `base_url` on the `openai` provider.
377
387
 
388
+
389
+ ### Self-hosted endpoints as named providers
390
+
391
+ Any number of OpenAI-compatible endpoints (vLLM, llama.cpp server, LM Studio, proxies) can be configured side by side under names you choose. `provider_type` picks the implementation; the entry name is yours:
392
+
393
+ ```bash
394
+ >>> /config set-provider gateway --type openai-compatible \
395
+ --base-url http://vllm-gateway.internal:8888/v1 --model qwen3-coder-30b
396
+ >>> /config set-provider local --type openai-compatible \
397
+ --base-url http://localhost:8000/v1 --model qwen3-coder-30b
398
+ >>> /switch local
399
+ ```
400
+
401
+ The `openai-compatible` type is keyless by default (`auth_type: "none"`), takes its model catalog from the endpoint's `/v1/models` (including each model's served context size — see `/models refresh`), and raises timeout errors with a cold-start hint since self-hosted gateways may load a model on first request. Set `providers.<name>.timeout` generously for such endpoints (e.g. `360`).
402
+
403
+ ### Prompt enhancement (optional)
404
+
405
+ `/enhance` and the `e:` message prefix rewrite a draft prompt with a dedicated model before sending, using the [PromptFoundry](https://github.com/gitshipdone/promptfoundry) meta-prompts (same author; that repo is the canonical source for the prompt texts and is being prepared for public release).
406
+
407
+ The feature is **opt-in**: it activates only when your config carries an `enhancement` block. Without one, `e:` is not intercepted and `/enhance` points you here.
408
+
409
+ ```json
410
+ "enhancement": {
411
+ "provider": "gateway",
412
+ "model": "qwen3-8b",
413
+ "temperature": 0.4,
414
+ "default_profile": "code",
415
+ "enabled": true
416
+ }
417
+ ```
418
+
419
+ `provider` must name an entry in `providers`; `default_profile` is one of `chat`, `code`, `image`, `research`. Failsafe chain: the configured model is tried first; if it is unreachable, the model you are currently chatting with rewrites the draft instead; if everything fails, the original draft is sent unchanged — enhancement never blocks a message.
420
+
378
421
  ### Environment variable overrides
379
422
 
380
423
  Environment variables take precedence over the saved config and are applied at
@@ -520,3 +563,7 @@ Tests follow TDD. 1,460 tests across providers, CLI, streaming, agent operations
520
563
  ## License
521
564
 
522
565
  MIT
566
+
567
+ ---
568
+
569
+ *This documentation was reviewed by a local Qwen model as part of OMN testing harness.*
@@ -10,10 +10,18 @@ try:
10
10
 
11
11
  __version__ = _get_version("omnimancer-cli")
12
12
  except Exception:
13
- with open("pyproject.toml", "r") as f:
14
- project = f.readlines()
15
- version = [i for i in project if "version" in i].pop(0).strip()
16
- __version__ = version.split().pop().strip("\"'")
13
+ # Uninstalled checkout (PYTHONPATH usage): read pyproject.toml next to
14
+ # the package, never relative to cwd — the CLI can be invoked from any
15
+ # working directory.
16
+ try:
17
+ from pathlib import Path
18
+
19
+ _pyproject = Path(__file__).resolve().parent.parent / "pyproject.toml"
20
+ project = _pyproject.read_text().splitlines()
21
+ version = [i for i in project if "version" in i].pop(0).strip()
22
+ __version__ = version.split().pop().strip("\"'")
23
+ except Exception:
24
+ __version__ = "unknown"
17
25
  __author__ = "Omnimancer Team"
18
26
  __description__ = "Unified CLI for multiple AI language models"
19
27
 
@@ -8,6 +8,7 @@ in terminal with clear formatting and captures approval decisions.
8
8
 
9
9
  import logging
10
10
  from datetime import datetime
11
+ from enum import Enum
11
12
  from pathlib import Path
12
13
  from typing import Any, Dict, List, Optional
13
14
 
@@ -27,6 +28,32 @@ from .approval_prompt import ApprovalDecision, CLIApprovalPrompt
27
28
  logger = logging.getLogger(__name__)
28
29
 
29
30
 
31
+ class ApprovalMode(Enum):
32
+ """Session-wide approval mode (claude-code-style accept toggles).
33
+
34
+ Sits BELOW permission rules: DENY rules refuse before the approval
35
+ workflow is reached, and ASK rules set ``_force_prompt``, which is
36
+ checked before the mode. The low-level security gate re-validates
37
+ paths/commands at execute time regardless.
38
+ """
39
+
40
+ NORMAL = "normal"
41
+ ACCEPT_EDITS = "accept-edits"
42
+ ACCEPT_ALL = "accept-all"
43
+
44
+
45
+ #: /accept cycle order.
46
+ _MODE_CYCLE = [
47
+ ApprovalMode.NORMAL,
48
+ ApprovalMode.ACCEPT_EDITS,
49
+ ApprovalMode.ACCEPT_ALL,
50
+ ]
51
+
52
+ #: Operation types auto-approved by ACCEPT_EDITS. Deliberately excludes
53
+ #: deletes and command execution — those stay interactive.
54
+ _EDIT_OPERATION_TYPES = frozenset({OperationType.FILE_WRITE})
55
+
56
+
30
57
  class CLIApprovalIntegration:
31
58
  """
32
59
  Integration layer that connects EnhancedApprovalManager with CLI approval dialogs.
@@ -60,6 +87,7 @@ class CLIApprovalIntegration:
60
87
  self.console = console or Console()
61
88
  self.enable_auto_approval = enable_auto_approval
62
89
  self.approval_timeout_seconds = approval_timeout_seconds
90
+ self.session_approval_mode = ApprovalMode.NORMAL
63
91
 
64
92
  # Initialize UI components
65
93
  self.formatter = CLIApprovalFormatter(self.console)
@@ -337,6 +365,18 @@ class CLIApprovalIntegration:
337
365
  if operation.data.get("_force_prompt"):
338
366
  return None
339
367
 
368
+ # Session approval mode (/accept): accept-edits auto-approves file
369
+ # writes only; accept-all approves everything that reaches the
370
+ # approval workflow (deny rules and hard security limits never do).
371
+ if self._mode_auto_approves(operation):
372
+ self.console.print(
373
+ "[dim]✅ Auto-approved:"
374
+ f" {operation.description}"
375
+ f" (session mode: {self.session_approval_mode.value})"
376
+ "[/dim]"
377
+ )
378
+ return True
379
+
340
380
  try:
341
381
  # Generate operation signature for matching
342
382
  operation_signature = self._generate_operation_signature(operation)
@@ -366,6 +406,20 @@ class CLIApprovalIntegration:
366
406
  logger.error(f"Error checking auto-approval: {e}")
367
407
  return None
368
408
 
409
+ def _mode_auto_approves(self, operation: Operation) -> bool:
410
+ """Whether the session approval mode auto-approves this operation."""
411
+ if self.session_approval_mode is ApprovalMode.ACCEPT_ALL:
412
+ return True
413
+ if self.session_approval_mode is ApprovalMode.ACCEPT_EDITS:
414
+ return operation.type in _EDIT_OPERATION_TYPES
415
+ return False
416
+
417
+ def cycle_approval_mode(self) -> ApprovalMode:
418
+ """Advance normal → accept-edits → accept-all → normal."""
419
+ index = _MODE_CYCLE.index(self.session_approval_mode)
420
+ self.session_approval_mode = _MODE_CYCLE[(index + 1) % len(_MODE_CYCLE)]
421
+ return self.session_approval_mode
422
+
369
423
  async def _store_approval_pattern(
370
424
  self,
371
425
  operation: Operation,