omnimancer-cli 0.1.15__tar.gz → 0.2.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.
Files changed (205) hide show
  1. omnimancer_cli-0.2.6/PKG-INFO +570 -0
  2. omnimancer_cli-0.2.6/README.md +519 -0
  3. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/__init__.py +12 -17
  4. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/cli/__init__.py +1 -1
  5. omnimancer_cli-0.2.6/omnimancer/cli/agent_loop.py +629 -0
  6. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/cli/approval_formatter.py +723 -734
  7. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/cli/approval_integration.py +809 -734
  8. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/cli/approval_prompt.py +1320 -1307
  9. omnimancer_cli-0.2.6/omnimancer/cli/command_dispatch.py +1844 -0
  10. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/cli/commands.py +51 -193
  11. omnimancer_cli-0.2.6/omnimancer/cli/completion.py +244 -0
  12. omnimancer_cli-0.2.6/omnimancer/cli/display.py +390 -0
  13. omnimancer_cli-0.2.6/omnimancer/cli/handlers/__init__.py +1 -0
  14. omnimancer_cli-0.2.6/omnimancer/cli/headless.py +374 -0
  15. omnimancer_cli-0.2.6/omnimancer/cli/interface.py +1107 -0
  16. omnimancer_cli-0.2.6/omnimancer/cli/subagent.py +125 -0
  17. omnimancer_cli-0.2.6/omnimancer/cli/system_prompts.py +435 -0
  18. omnimancer_cli-0.2.6/omnimancer/cli/tool_handler.py +456 -0
  19. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/__init__.py +1 -4
  20. omnimancer_cli-0.2.6/omnimancer/core/agent/__init__.py +63 -0
  21. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/agent/approval_context.py +468 -460
  22. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/agent/approval_interface.py +632 -628
  23. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/agent/approval_manager.py +764 -760
  24. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/agent/config.py +853 -845
  25. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/agent/file_system_manager.py +1846 -1790
  26. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/agent/program_executor.py +790 -748
  27. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/agent/read_before_write_errors.py +513 -492
  28. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/agent/status_core.py +447 -446
  29. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/agent/status_manager.py +873 -878
  30. omnimancer_cli-0.2.6/omnimancer/core/agent/tool_definitions.py +222 -0
  31. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/agent/types.py +61 -60
  32. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/agent/web_client.py +750 -745
  33. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/agent/workflow_orchestrator.py +850 -826
  34. omnimancer_cli-0.2.6/omnimancer/core/agent_engine.py +1003 -0
  35. omnimancer_cli-0.2.6/omnimancer/core/agent_managers.py +725 -0
  36. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/agent_mode_manager.py +741 -706
  37. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/chat_manager.py +141 -141
  38. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/config_manager.py +1776 -2199
  39. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/config_migration.py +777 -772
  40. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/config_validator.py +793 -768
  41. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/conversation_manager.py +352 -352
  42. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/engine.py +1040 -787
  43. omnimancer_cli-0.2.6/omnimancer/core/env_loader.py +213 -0
  44. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/fallback_manager.py +576 -568
  45. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/health_monitor.py +470 -462
  46. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/history_manager.py +5 -2
  47. omnimancer_cli-0.2.6/omnimancer/core/hooks.py +218 -0
  48. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/mcp_integration_layer.py +883 -878
  49. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/models.py +2036 -1889
  50. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/provider_capabilities.py +434 -403
  51. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/provider_initializer.py +466 -450
  52. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/provider_registry.py +442 -432
  53. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/security/approval_workflow.py +406 -406
  54. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/security/audit_logger.py +511 -511
  55. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/security/permission_controller.py +557 -511
  56. omnimancer_cli-0.2.6/omnimancer/core/security/permission_rules.py +85 -0
  57. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/security/sandbox_manager.py +381 -379
  58. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/security/security_manager.py +552 -530
  59. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/signal_handler.py +190 -174
  60. omnimancer_cli-0.2.6/omnimancer/mcp/client.py +379 -0
  61. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/mcp/manager.py +718 -649
  62. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/providers/azure.py +611 -608
  63. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/providers/base.py +305 -262
  64. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/providers/bedrock.py +755 -711
  65. omnimancer_cli-0.2.6/omnimancer/providers/claude.py +743 -0
  66. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/providers/claude_code.py +412 -406
  67. omnimancer_cli-0.2.6/omnimancer/providers/claude_credentials.py +128 -0
  68. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/providers/cohere.py +419 -412
  69. omnimancer_cli-0.2.6/omnimancer/providers/digitalocean.py +82 -0
  70. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/providers/factory.py +1004 -988
  71. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/providers/gemini.py +712 -708
  72. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/providers/mistral.py +563 -554
  73. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/providers/ollama.py +533 -510
  74. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/providers/openai.py +595 -362
  75. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/providers/openrouter.py +742 -710
  76. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/providers/perplexity.py +483 -476
  77. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/providers/vertex.py +628 -617
  78. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/providers/xai.py +495 -484
  79. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/ui/cancellation_handler.py +272 -235
  80. omnimancer_cli-0.2.6/omnimancer/ui/streaming_display.py +75 -0
  81. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/utils/error_handler.py +53 -35
  82. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/utils/errors.py +54 -37
  83. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/utils/retry.py +240 -238
  84. omnimancer_cli-0.2.6/omnimancer_cli.egg-info/PKG-INFO +570 -0
  85. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer_cli.egg-info/SOURCES.txt +31 -48
  86. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer_cli.egg-info/requires.txt +1 -0
  87. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/pyproject.toml +9 -7
  88. omnimancer_cli-0.2.6/tests/test_approval_integration_compatibility.py +94 -0
  89. omnimancer_cli-0.2.6/tests/test_approval_preview_format.py +148 -0
  90. omnimancer_cli-0.2.6/tests/test_approval_remember.py +71 -0
  91. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_approval_system.py +3 -10
  92. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_azure_provider.py +26 -13
  93. omnimancer_cli-0.2.6/tests/test_claude_credentials.py +405 -0
  94. omnimancer_cli-0.2.6/tests/test_claude_provider.py +629 -0
  95. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_cohere_provider.py +2 -6
  96. omnimancer_cli-0.2.6/tests/test_command_approval_security.py +146 -0
  97. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_config_comprehensive.py +39 -64
  98. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_conversation_history.py +2 -2
  99. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_core_engine.py +30 -0
  100. omnimancer_cli-0.2.6/tests/test_digitalocean_provider.py +92 -0
  101. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_enhanced_model_info.py +131 -131
  102. omnimancer_cli-0.2.6/tests/test_env_loader.py +108 -0
  103. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_error_handling_robustness.py +6 -19
  104. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_execution_timeout_errors.py +1 -1
  105. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_gemini_provider.py +7 -8
  106. omnimancer_cli-0.2.6/tests/test_hooks.py +300 -0
  107. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_httpx_compatibility.py +2 -1
  108. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_import_validation.py +12 -21
  109. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_interface_smoke_tests.py +1 -3
  110. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_mcp_integration.py +152 -282
  111. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_mistral_provider.py +39 -19
  112. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_models.py +93 -0
  113. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_ollama_provider.py +2 -10
  114. omnimancer_cli-0.2.6/tests/test_openai_context_fit.py +161 -0
  115. omnimancer_cli-0.2.6/tests/test_openai_provider_tools.py +194 -0
  116. omnimancer_cli-0.2.6/tests/test_permission_rules.py +215 -0
  117. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_perplexity_provider.py +22 -10
  118. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_program_executor.py +27 -16
  119. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_provider_base.py +118 -7
  120. omnimancer_cli-0.2.6/tests/test_provider_capability_consistency.py +95 -0
  121. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_provider_integration.py +2 -7
  122. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_provider_registry.py +207 -207
  123. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_security_validation.py +46 -26
  124. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_system_integration.py +30 -20
  125. omnimancer_cli-0.2.6/tests/test_system_prompts.py +43 -0
  126. omnimancer_cli-0.2.6/tests/test_tool_calling_integration.py +425 -0
  127. omnimancer_cli-0.2.6/tests/test_tool_handler.py +579 -0
  128. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_workflows_comprehensive.py +8 -163
  129. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_xai_provider.py +29 -17
  130. omnimancer_cli-0.1.15/PKG-INFO +0 -414
  131. omnimancer_cli-0.1.15/README.md +0 -364
  132. omnimancer_cli-0.1.15/omnimancer/cli/agent_manager.py +0 -826
  133. omnimancer_cli-0.1.15/omnimancer/cli/agent_wizard.py +0 -944
  134. omnimancer_cli-0.1.15/omnimancer/cli/batch_approval_display.py +0 -617
  135. omnimancer_cli-0.1.15/omnimancer/cli/batch_approval_filters.py +0 -729
  136. omnimancer_cli-0.1.15/omnimancer/cli/batch_operation_monitor.py +0 -775
  137. omnimancer_cli-0.1.15/omnimancer/cli/commands/performance_cmd.py +0 -624
  138. omnimancer_cli-0.1.15/omnimancer/cli/completion_handler.py +0 -281
  139. omnimancer_cli-0.1.15/omnimancer/cli/config_setup_wizard.py +0 -783
  140. omnimancer_cli-0.1.15/omnimancer/cli/handlers/__init__.py +0 -18
  141. omnimancer_cli-0.1.15/omnimancer/cli/handlers/agent_handler.py +0 -865
  142. omnimancer_cli-0.1.15/omnimancer/cli/handlers/agent_persona_handler.py +0 -1048
  143. omnimancer_cli-0.1.15/omnimancer/cli/handlers/custom_agent_handler.py +0 -352
  144. omnimancer_cli-0.1.15/omnimancer/cli/handlers/permissions_handler.py +0 -1609
  145. omnimancer_cli-0.1.15/omnimancer/cli/interface.py +0 -6695
  146. omnimancer_cli-0.1.15/omnimancer/cli/performance_dashboard.py +0 -612
  147. omnimancer_cli-0.1.15/omnimancer/core/agent/__init__.py +0 -256
  148. omnimancer_cli-0.1.15/omnimancer/core/agent/agent_config.py +0 -715
  149. omnimancer_cli-0.1.15/omnimancer/core/agent/agent_switcher.py +0 -668
  150. omnimancer_cli-0.1.15/omnimancer/core/agent/approval_dialog.py +0 -902
  151. omnimancer_cli-0.1.15/omnimancer/core/agent/cli_integration.py +0 -470
  152. omnimancer_cli-0.1.15/omnimancer/core/agent/custom_agent_integration.py +0 -654
  153. omnimancer_cli-0.1.15/omnimancer/core/agent/diff_renderer.py +0 -706
  154. omnimancer_cli-0.1.15/omnimancer/core/agent/file_content_display.py +0 -503
  155. omnimancer_cli-0.1.15/omnimancer/core/agent/file_modification_workflow.py +0 -658
  156. omnimancer_cli-0.1.15/omnimancer/core/agent/input_handler.py +0 -614
  157. omnimancer_cli-0.1.15/omnimancer/core/agent/metrics_collector.py +0 -771
  158. omnimancer_cli-0.1.15/omnimancer/core/agent/optimization_engine.py +0 -729
  159. omnimancer_cli-0.1.15/omnimancer/core/agent/performance_monitor.py +0 -717
  160. omnimancer_cli-0.1.15/omnimancer/core/agent/persona.py +0 -870
  161. omnimancer_cli-0.1.15/omnimancer/core/agent/persona_validator.py +0 -672
  162. omnimancer_cli-0.1.15/omnimancer/core/agent/proposed_changes_integration.py +0 -663
  163. omnimancer_cli-0.1.15/omnimancer/core/agent/read_before_write_ui.py +0 -647
  164. omnimancer_cli-0.1.15/omnimancer/core/agent/rich_renderer.py +0 -763
  165. omnimancer_cli-0.1.15/omnimancer/core/agent/status_config.py +0 -238
  166. omnimancer_cli-0.1.15/omnimancer/core/agent/status_integrated_engine.py +0 -540
  167. omnimancer_cli-0.1.15/omnimancer/core/agent/status_ui_components.py +0 -535
  168. omnimancer_cli-0.1.15/omnimancer/core/agent/template_applicator.py +0 -548
  169. omnimancer_cli-0.1.15/omnimancer/core/agent/terminal_status_listener.py +0 -394
  170. omnimancer_cli-0.1.15/omnimancer/core/agent/token_tracker.py +0 -679
  171. omnimancer_cli-0.1.15/omnimancer/core/agent_engine.py +0 -1625
  172. omnimancer_cli-0.1.15/omnimancer/core/agent_progress_ui.py +0 -545
  173. omnimancer_cli-0.1.15/omnimancer/core/config_provider.py +0 -1974
  174. omnimancer_cli-0.1.15/omnimancer/core/config_security_validator.py +0 -393
  175. omnimancer_cli-0.1.15/omnimancer/core/enhanced_input.py +0 -523
  176. omnimancer_cli-0.1.15/omnimancer/core/env_loader.py +0 -83
  177. omnimancer_cli-0.1.15/omnimancer/core/setup_wizard.py +0 -345
  178. omnimancer_cli-0.1.15/omnimancer/core/setup_wizard_core.py +0 -449
  179. omnimancer_cli-0.1.15/omnimancer/core/setup_wizard_guide_generator.py +0 -376
  180. omnimancer_cli-0.1.15/omnimancer/core/setup_wizard_provider_setup.py +0 -454
  181. omnimancer_cli-0.1.15/omnimancer/core/setup_wizard_ui.py +0 -363
  182. omnimancer_cli-0.1.15/omnimancer/core/setup_wizard_validation.py +0 -411
  183. omnimancer_cli-0.1.15/omnimancer/mcp/client.py +0 -725
  184. omnimancer_cli-0.1.15/omnimancer/providers/claude.py +0 -426
  185. omnimancer_cli-0.1.15/omnimancer_cli.egg-info/PKG-INFO +0 -414
  186. omnimancer_cli-0.1.15/tests/test_performance_security.py +0 -440
  187. omnimancer_cli-0.1.15/tests/test_setup_wizard.py +0 -662
  188. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/LICENSE +0 -0
  189. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/__main__.py +0 -0
  190. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/cli/dynamic_commands.py +0 -0
  191. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/core/security/__init__.py +0 -0
  192. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/mcp/__init__.py +0 -0
  193. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/providers/__init__.py +0 -0
  194. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/ui/__init__.py +0 -0
  195. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/ui/progress_indicator.py +0 -0
  196. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer/utils/__init__.py +0 -0
  197. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer_cli.egg-info/dependency_links.txt +0 -0
  198. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer_cli.egg-info/entry_points.txt +0 -0
  199. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/omnimancer_cli.egg-info/top_level.txt +0 -0
  200. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/setup.cfg +0 -0
  201. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_conversation_manager.py +0 -0
  202. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_fallback_manager.py +0 -0
  203. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_fixtures.py +0 -0
  204. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_mcp_integration_layer.py +0 -0
  205. {omnimancer_cli-0.1.15 → omnimancer_cli-0.2.6}/tests/test_retry.py +0 -0
@@ -0,0 +1,570 @@
1
+ Metadata-Version: 2.4
2
+ Name: omnimancer-cli
3
+ Version: 0.2.6
4
+ Summary: A unified command-line interface for multiple AI language models
5
+ Author-email: Kellan Strong <kellan@jite.ai>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/nvasion/omnimancer
8
+ Project-URL: Repository, https://github.com/nvasion/omnimancer
9
+ Project-URL: Issues, https://github.com/nvasion/omnimancer/issues
10
+ Keywords: ai,cli,chat,openai,claude,language-model
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Classifier: Topic :: Communications :: Chat
21
+ Requires-Python: >=3.10
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: click>=8.0.0
25
+ Requires-Dist: rich>=13.0.0
26
+ Requires-Dist: httpx>=0.24.0
27
+ Requires-Dist: pydantic>=2.0.0
28
+ Requires-Dist: cryptography>=41.0.0
29
+ Requires-Dist: python-dotenv>=1.0.0
30
+ Requires-Dist: certifi>=2023.0.0
31
+ Requires-Dist: aiofiles>=23.0.0
32
+ Requires-Dist: aiohttp>=3.8.0
33
+ Requires-Dist: psutil>=5.9.0
34
+ Requires-Dist: beautifulsoup4>=4.12.0
35
+ Requires-Dist: html2text>=2020.1.16
36
+ Requires-Dist: jsonschema>=4.17.0
37
+ Requires-Dist: readability-lxml>=0.8.1
38
+ Requires-Dist: PyYAML>=6.0.0
39
+ Requires-Dist: toml>=0.10.2
40
+ Requires-Dist: mcp>=1.0.0
41
+ Provides-Extra: dev
42
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
43
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
44
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
45
+ Requires-Dist: pytest-mock>=3.10.0; extra == "dev"
46
+ Requires-Dist: black>=23.0.0; extra == "dev"
47
+ Requires-Dist: isort>=5.12.0; extra == "dev"
48
+ Requires-Dist: flake8>=6.0.0; extra == "dev"
49
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
50
+ Dynamic: license-file
51
+
52
+ # Omnimancer
53
+
54
+ A multi-model coding agent for the terminal. One tool, any LLM.
55
+
56
+ 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
+
58
+ Beyond the basics, it ships with:
59
+
60
+ - **MCP support** (stdio, SSE, and HTTP transports) for tools, resources, and prompts
61
+ - **Lifecycle hooks** — run shell commands on message/tool events, with blocking veto power
62
+ - **Permission rules** — declarative allow/deny/ask rules per tool with regex matchers
63
+ - **Subagents** — scoped child agents with their own prompt, tool whitelist, and model
64
+ - **Layered security** — approval workflow, sensitive-path protection, and project-boundary enforcement
65
+
66
+ ## Install
67
+
68
+ ```bash
69
+ pip install omnimancer-cli
70
+ ```
71
+
72
+ ## Usage
73
+
74
+ ### Headless (pipeline mode)
75
+
76
+ ```bash
77
+ # Single prompt, JSON output — like claude -p
78
+ omn -p "refactor auth.py to use dependency injection"
79
+
80
+ # Pipe context in
81
+ cat error.log | omn -p "diagnose this crash and suggest a fix"
82
+
83
+ # Use a specific provider and model.
84
+ # Note: the prompt must come right after -p; put other flags after it.
85
+ omn -p "write tests for src/api/routes.py" --provider claude --model claude-sonnet-4
86
+ omn -p "explain this codebase" --provider openai --model gpt-4o
87
+ omn -p "review this diff" --provider ollama < changes.patch
88
+
89
+ # Output formats
90
+ omn -p "summarize this repo" # plain text (default)
91
+ omn -p "summarize this repo" --output-format json # structured JSON
92
+ omn -p "summarize this" --output-format stream-json # streaming JSON
93
+
94
+ # Auto-approve all tool operations (CI/scripts)
95
+ omn -p "fix the failing tests" --dangerously-skip-permissions
96
+
97
+ # Verbose output / explicit config file
98
+ omn -p "audit the security module" --verbose --config ~/.omnimancer/config.json
99
+ ```
100
+
101
+ The `--provider`, `--model`, and `--base-url` flags are **session overrides**: they
102
+ modify the in-memory config for this run only and are never written back to disk.
103
+
104
+ Headless mode with `--output-format json` emits a single structured result
105
+ object — including the tool calls the agent made along the way:
106
+
107
+ ```json
108
+ {
109
+ "type": "result",
110
+ "subtype": "success",
111
+ "is_error": false,
112
+ "result": "Here's the refactored code...",
113
+ "session_id": "…",
114
+ "model": "claude-sonnet-4-20250514",
115
+ "num_turns": 3,
116
+ "tool_calls": [
117
+ {"name": "file_read", "arguments": {"path": "src/auth.py"}, "error": null},
118
+ {"name": "file_write", "arguments": {"path": "src/auth.py"}, "error": null}
119
+ ],
120
+ "usage": {"input_tokens": 1523, "output_tokens": 892, "total_cost_usd": 0.04},
121
+ "total_cost_usd": 0.04,
122
+ "stop_reason": "end_turn"
123
+ }
124
+ ```
125
+
126
+ On failure it stays valid JSON (stdout), with the error and any tool calls made:
127
+
128
+ ```json
129
+ {"type": "result", "subtype": "error", "is_error": true, "error": "…", "tool_calls": [...]}
130
+ ```
131
+
132
+ For a live, line-by-line stream of what the agent is doing (assistant text,
133
+ each `tool_use`, each `tool_result`, then the final `result`), use
134
+ `--output-format stream-json`.
135
+
136
+ ### Interactive mode
137
+
138
+ ```bash
139
+ omn # start interactive REPL
140
+ omn --provider openai # start with a specific provider (session-only)
141
+ omn --no-approval # skip approval prompts
142
+ omn --dangerously-skip-permissions # auto-approve all tool operations
143
+ ```
144
+
145
+ Interactive mode gives you a REPL with streaming responses, token/cost display, and agent capabilities:
146
+
147
+ ```
148
+ >>> read src/main.py and add error handling
149
+ [text streams in real-time as the model generates]
150
+ tokens: 1523 in / 892 out | ~$0.0134
151
+
152
+ >>> /switch openai gpt-4o
153
+ >>> now review what we just changed
154
+ [switches to OpenAI, continues conversation]
155
+ ```
156
+
157
+ ### Streaming responses
158
+
159
+ Responses stream token-by-token as the model generates, so you see output immediately instead of waiting for the full response. After each response, a token/cost summary is displayed.
160
+
161
+ Streaming is automatic for providers that support it. Other providers fall back to displaying the full response once complete — no configuration needed.
162
+
163
+ | Provider | Streaming |
164
+ |----------|:---------:|
165
+ | Claude (Anthropic) | Yes |
166
+ | All others | Fallback (full response) |
167
+
168
+ Streaming works in both regular chat and agent mode (tool calling flow). The display uses a live-updating terminal panel that refreshes at 15fps.
169
+
170
+ ### Agent mode
171
+
172
+ When agent mode is enabled (`/agent on`), the AI can autonomously:
173
+
174
+ - **Read and write files** with approval workflow
175
+ - **Execute shell commands** with security validation
176
+ - **Search codebases** with fuzzy file matching (70% similarity threshold)
177
+ - **Make HTTP requests** for API testing
178
+ - **Call MCP tools** from connected MCP servers
179
+
180
+ All destructive operations require explicit approval (or are governed by your [permission rules](#permission-rules)). Reads and searches are auto-approved.
181
+
182
+ Providers that support native tool calling (Claude, OpenAI, Gemini) use structured function calls. Others fall back to operation markers parsed from the response text.
183
+
184
+ ```
185
+ >>> /agent on
186
+ >>> fix the failing test in tests/test_auth.py
187
+ [agent reads test file, reads source, edits code, runs pytest, iterates]
188
+ tokens: 4210 in / 1893 out | ~$0.0412
189
+ ```
190
+
191
+ ### Subagents
192
+
193
+ Subagents are scoped child agents with their own system prompt, tool whitelist, model override, and iteration cap. Each run uses an isolated conversation context, so a subagent never pollutes your main session — and its errors are caught and reported instead of crashing the REPL.
194
+
195
+ Define them in `config.json`:
196
+
197
+ ```json
198
+ "subagents": {
199
+ "reviewer": {
200
+ "description": "Reviews code for bugs and style issues",
201
+ "prompt": "You are a meticulous code reviewer...",
202
+ "tools": ["Read", "Grep", "Bash"],
203
+ "model": null,
204
+ "max_iterations": 10
205
+ }
206
+ }
207
+ ```
208
+
209
+ Tool names match the agent's toolset (`Read`, `Write`, `Edit`, `Bash`, `Glob`, `Grep`, `WebFetch`). `tools: null` inherits all tools; `model: null` inherits the session model.
210
+
211
+ ```
212
+ >>> /subagents # list configured subagents
213
+ >>> /subagents run reviewer check src/auth.py for security issues
214
+ ```
215
+
216
+ ## Supported Providers
217
+
218
+ | Provider | Tool Calling | Streaming | Notes |
219
+ |----------|:---:|:---:|-------|
220
+ | **Claude** (Anthropic) | Yes | Yes | Primary target. Best coding performance. |
221
+ | **OpenAI** | Yes | Fallback | GPT-4o, o1, etc. |
222
+ | **Gemini** (Google) | Yes | Fallback | Large context window. |
223
+ | **AWS Bedrock** | Yes | Fallback | Claude/Titan via AWS. |
224
+ | **Ollama** | No | Fallback | Local models. No API key needed. |
225
+ | **xAI** (Grok) | Yes | Fallback | |
226
+ | **Mistral** | No | Fallback | |
227
+ | **Perplexity** | No | Fallback | Web search built-in. |
228
+ | **Azure OpenAI** | Yes | Fallback | Enterprise Azure deployment. |
229
+ | **Vertex AI** | Yes | Fallback | Google Cloud deployment. |
230
+ | **OpenRouter** | No | Fallback | Access to 100+ models. |
231
+ | **DigitalOcean** | No | Fallback | OpenAI-compatible GenAI inference. Custom endpoint supported. |
232
+ | **Cohere** | No | Fallback | |
233
+
234
+ "Fallback" means the provider works but sends the full response at once instead of streaming token-by-token. The UI handles both modes transparently.
235
+
236
+ ## Commands
237
+
238
+ | Command | Description |
239
+ |---------|-------------|
240
+ | `/help [command]` | Show help (optionally for a specific command) |
241
+ | `/quit` | Exit (also: `/exit`, Ctrl+D) |
242
+ | `/clear` | Clear terminal screen |
243
+ | `/switch <provider> [model]` | Switch provider or model |
244
+ | `/models [filter]` | List available models (alias: `/model`) |
245
+ | `/providers` | List all providers with status |
246
+ | `/agent on\|off\|status` | Toggle agent mode |
247
+ | `/subagents [run <name> <task>]` | List or run scoped child agents |
248
+ | `/config show\|get\|set` | View or modify configuration |
249
+ | `/config set-provider <name> [--api-key …] [--base-url …] [--model …]` | Create/update a provider |
250
+ | `/config remove-provider <name>` | Remove a provider |
251
+ | `/hooks [list\|on\|off\|add\|remove]` | Manage lifecycle hooks |
252
+ | `/permissions [list\|on\|off\|allow\|deny\|ask\|remove]` | Manage permission rules |
253
+ | `/save [name]` | Save conversation |
254
+ | `/load [name]` | Load conversation |
255
+ | `/list` | List saved conversations |
256
+ | `/history [recent\|search\|clear\|export\|stats]` | Manage conversation history |
257
+ | `/tools` | Show available MCP tools |
258
+ | `/prompts [list\|<name> [key=value …]]` | List and render MCP prompts |
259
+ | `/mcp [status\|reload\|connect\|disconnect\|health] [server]` | MCP server management |
260
+ | `/add-model <name> <provider> [description]` | Register a custom model |
261
+ | `/remove-model <name> <provider>` | Unregister a custom model |
262
+ | `/list-custom-models` | List registered custom models |
263
+ | `/status` | System status |
264
+
265
+ You can also define your own slash commands: drop `.json` or `.py` command
266
+ definitions into `~/.omnimancer/commands/` and they're loaded at startup.
267
+
268
+ ## MCP servers
269
+
270
+ Omnimancer's MCP layer is built on the official [`mcp` SDK](https://pypi.org/project/mcp/) and supports three transports — **stdio** (local subprocess), **SSE**, and **streamable HTTP** (remote) — and three MCP features: **tools** (exposed to the agent and listed via `/tools`), **resources**, and **prompts** (listed and rendered via `/prompts`).
271
+
272
+ Configure servers in `config.json`:
273
+
274
+ ```json
275
+ "mcp": {
276
+ "enabled": true,
277
+ "servers": {
278
+ "filesystem": {
279
+ "transport": "stdio",
280
+ "command": "npx",
281
+ "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/project"],
282
+ "env": {},
283
+ "enabled": true,
284
+ "auto_approve": ["read_file"],
285
+ "timeout": 30
286
+ },
287
+ "remote-api": {
288
+ "transport": "http",
289
+ "url": "https://mcp.example.com/mcp",
290
+ "headers": {"Authorization": "Bearer ..."},
291
+ "enabled": true
292
+ }
293
+ }
294
+ }
295
+ ```
296
+
297
+ Stdio servers need `command` (plus optional `args`/`env`); SSE and HTTP servers need `url` (plus optional `headers` — e.g. a bearer token for authenticated servers). `auto_approve` lists tool names that skip the approval prompt for that server.
298
+
299
+ Manage servers at runtime with `/mcp status`, `/mcp connect [server]`, `/mcp disconnect [server]`, `/mcp reload [server]`, and `/mcp health [server]`.
300
+
301
+ MCP is optional: if the `mcp` package isn't installed, everything else still works — connecting to a server just tells you to `pip install mcp`.
302
+
303
+ ## Hooks
304
+
305
+ Hooks run shell commands at lifecycle events — for logging, notifications, linting, or policy enforcement. Four events are available:
306
+
307
+ | Event | Fires | Can block? |
308
+ |-------|-------|:---:|
309
+ | `pre_send_message` | Before a message is sent to the provider | Yes |
310
+ | `post_send_message` | After a successful provider response | No |
311
+ | `tool_use_request` | Before an agent tool/operation runs | Yes |
312
+ | `post_tool` | After a tool/operation completes | No |
313
+
314
+ A **blocking** hook vetoes the action if it exits non-zero (or times out). Hooks receive the event payload as JSON on stdin, plus `OMNIMANCER_HOOK_*` environment variables (`OMNIMANCER_HOOK_EVENT`, `OMNIMANCER_HOOK_MESSAGE`, …) for shell one-liners. Hook errors never crash the app.
315
+
316
+ Manage from the CLI:
317
+
318
+ ```
319
+ >>> /hooks # list configured hooks
320
+ >>> /hooks add post_tool notify --timeout 10 notify-send "tool ran"
321
+ >>> /hooks add tool_use_request guard --matcher "rm -rf" --blocking exit 1
322
+ >>> /hooks remove post_tool notify
323
+ >>> /hooks off # disable all hooks globally
324
+ ```
325
+
326
+ `--matcher` is a regex tested against the event's target (message text, file path, command) — the hook only fires on a match. Hooks are stored in `config.json` under `hooks`:
327
+
328
+ ```json
329
+ "hooks": {
330
+ "enabled": true,
331
+ "tool_use_request": [
332
+ {"name": "guard", "command": "exit 1", "matcher": "rm -rf", "blocking": true, "timeout": 30}
333
+ ]
334
+ }
335
+ ```
336
+
337
+ ## Permission rules
338
+
339
+ Permission rules decide what the agent may do before the approval prompt is ever shown. Each rule matches a tool (an operation type like `file_write`, `command_execute`, `web_request` — or `*` for any) plus an optional regex on the target (file path, command, URL).
340
+
341
+ Precedence: **deny > ask > allow > default** (normal approval workflow).
342
+
343
+ ```
344
+ >>> /permissions # list rules
345
+ >>> /permissions deny command_execute "rm -rf"
346
+ >>> /permissions ask file_write ".*prod.*"
347
+ >>> /permissions allow file_write "\.env$" # authorize project-local .env writes
348
+ >>> /permissions remove deny 1 # remove rule by index
349
+ >>> /permissions off # disable rules globally
350
+ ```
351
+
352
+ - `deny` rules refuse without prompting.
353
+ - `ask` rules force a prompt even if the operation was previously "remembered" as approved.
354
+ - `allow` rules auto-approve — and also authorize writes to sensitive-named files (like `.env`) inside the project.
355
+
356
+ Rules live in `config.json` under `permissions` (`always_deny` / `always_ask` / `always_allow` lists).
357
+
358
+ ## Security model
359
+
360
+ Three layers govern every agent operation, in order:
361
+
362
+ 1. **Permission rules** — your declarative deny/ask/allow rules (above).
363
+ 2. **Approval workflow** — interactive y/n with diff preview; approvals can be "remembered" per session.
364
+ 3. **Low-level security gate** — path and command validation that runs regardless of approval.
365
+
366
+ The security gate distinguishes:
367
+
368
+ - **Hard-restricted paths** — never writable, even with approval: system directories (`/etc`, `/sys`, `/proc`, `/boot`, `/usr/bin`, …), `~/.ssh`, `~/.aws/credentials`, `~/.config/gcloud`.
369
+ - **Sensitive name patterns** — denied by default but overridable by explicit approval or an `always_allow` rule: `.env*`, `*secret*`, `*key*`, `*token*`, `*password*`, `*credentials*`, `*.db`/`*.sqlite*`.
370
+ - **Project boundary** — writes must stay inside the directory `omn` was launched from (or a temp dir).
371
+
372
+ Plus: command whitelist/blacklist, sandboxed execution, read-before-write logic, and automatic backups of existing files before modification.
373
+
374
+ ## Configuration
375
+
376
+ ### API keys
377
+
378
+ The simplest setup is environment variables:
379
+
380
+ ```bash
381
+ export ANTHROPIC_API_KEY="sk-ant-..."
382
+ export OPENAI_API_KEY="sk-..."
383
+ export GOOGLE_API_KEY="..."
384
+ export XAI_API_KEY="..."
385
+ omn
386
+ ```
387
+
388
+ ### Config file
389
+
390
+ Config is stored in `~/.omnimancer/config.json` (API keys are encrypted at rest).
391
+ You can edit it directly or, more conveniently, configure everything from the CLI:
392
+
393
+ ```bash
394
+ omn
395
+ # Configure a provider in one step (api key is encrypted before storage)
396
+ >>> /config set-provider claude --api-key sk-ant-...
397
+ >>> /config set-provider openai --api-key sk-... --model gpt-4o
398
+ >>> /config set-provider openrouter --api-key sk-or-... --model anthropic/claude-3.5-sonnet
399
+
400
+ # Set or change individual fields
401
+ >>> /config set providers.openai.base_url https://my-proxy.example.com/v1
402
+ >>> /config set providers.openai.max_tokens 8192
403
+ >>> /config set default_provider claude
404
+
405
+ # Inspect / clean up
406
+ >>> /config show
407
+ >>> /config get default_provider
408
+ >>> /config remove-provider openai
409
+ ```
410
+
411
+ ### Multiple endpoints
412
+
413
+ Each of these is just a provider you can point anywhere via `base_url`, so you can run
414
+ several endpoints side by side and switch between them with `/switch <provider>`:
415
+
416
+ | Endpoint | Provider name | Default base URL |
417
+ |----------|---------------|------------------|
418
+ | Claude (direct) | `claude` | `https://api.anthropic.com/v1` |
419
+ | OpenAI | `openai` | `https://api.openai.com/v1` |
420
+ | OpenRouter | `openrouter` | `https://openrouter.ai/api/v1` |
421
+ | DigitalOcean inference | `digitalocean` | `https://inference.do-ai.run/v1` |
422
+
423
+ Any OpenAI-compatible service (local proxy, gateway, self-hosted model) works by
424
+ overriding `base_url` on the `openai` provider.
425
+
426
+ ### Environment variable overrides
427
+
428
+ Environment variables take precedence over the saved config and are applied at
429
+ runtime only (never written back to disk). This makes them ideal for CI and for
430
+ testing endpoints without touching `config.json`.
431
+
432
+ ```bash
433
+ # Conventional API keys
434
+ export ANTHROPIC_API_KEY="sk-ant-..."
435
+ export OPENAI_API_KEY="sk-..."
436
+ export OPENROUTER_API_KEY="sk-or-..."
437
+ export DIGITALOCEAN_INFERENCE_KEY="..."
438
+
439
+ # Per-provider overrides: OMNIMANCER_<PROVIDER>_{API_KEY,BASE_URL,MODEL}
440
+ export OMNIMANCER_OPENAI_BASE_URL="http://localhost:1234/v1"
441
+ export OMNIMANCER_DIGITALOCEAN_MODEL="llama3.3-70b-instruct"
442
+
443
+ # Pick the default provider for this run
444
+ export OMNIMANCER_DEFAULT_PROVIDER="digitalocean"
445
+ omn
446
+ ```
447
+
448
+ You can also override the endpoint for a single headless run with `--base-url`:
449
+
450
+ ```bash
451
+ omn -p "summarize README.md" --provider openai --base-url http://localhost:1234/v1
452
+ omn -p "explain this repo" --provider digitalocean --model llama3.3-70b-instruct
453
+ ```
454
+
455
+ ### Provider-specific setup
456
+
457
+ **Claude (Anthropic):**
458
+ ```bash
459
+ export ANTHROPIC_API_KEY="sk-ant-..."
460
+ # Models: claude-sonnet-4, claude-opus-4, claude-3-5-sonnet
461
+ ```
462
+
463
+ **OpenAI:**
464
+ ```bash
465
+ export OPENAI_API_KEY="sk-..."
466
+ # Models: gpt-4o, gpt-4-turbo, gpt-3.5-turbo
467
+ ```
468
+
469
+ **Google Gemini:**
470
+ ```bash
471
+ export GOOGLE_API_KEY="..."
472
+ # Models: gemini-1.5-pro, gemini-1.5-flash
473
+ ```
474
+
475
+ **AWS Bedrock:**
476
+ ```bash
477
+ # Uses AWS credentials (env vars, ~/.aws/credentials, or IAM role)
478
+ export AWS_DEFAULT_REGION="us-east-1"
479
+ # Models: anthropic.claude-3-5-sonnet, amazon.titan
480
+ ```
481
+
482
+ **OpenRouter:**
483
+ ```bash
484
+ export OPENROUTER_API_KEY="sk-or-..."
485
+ # Models: anthropic/claude-3.5-sonnet, openai/gpt-4o, and 100+ more
486
+ ```
487
+
488
+ **DigitalOcean inference (OpenAI-compatible):**
489
+ ```bash
490
+ export DIGITALOCEAN_INFERENCE_KEY="..."
491
+ # Default endpoint: https://inference.do-ai.run/v1
492
+ # Models: llama3.3-70b-instruct, llama3-8b-instruct, openai-gpt-4o
493
+ # Override the endpoint if needed:
494
+ export OMNIMANCER_DIGITALOCEAN_BASE_URL="https://inference.do-ai.run/v1"
495
+ ```
496
+
497
+ **Ollama (local, no API key):**
498
+ ```bash
499
+ ollama serve
500
+ ollama pull llama3.1
501
+ omn
502
+ >>> /switch ollama llama3.1
503
+ ```
504
+
505
+ **Azure OpenAI:**
506
+ ```bash
507
+ export AZURE_OPENAI_API_KEY="..."
508
+ export AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/"
509
+ ```
510
+
511
+ ## Architecture
512
+
513
+ ```
514
+ omnimancer/
515
+ ├── cli/ # CLI interface (modular)
516
+ │ ├── interface.py # Core REPL loop, streaming integration
517
+ │ ├── headless.py # -p pipeline mode (text/json/stream-json)
518
+ │ ├── command_dispatch.py # Slash command handlers
519
+ │ ├── agent_loop.py # Marker-based agent workflow
520
+ │ ├── tool_handler.py # Native tool call execution
521
+ │ ├── subagent.py # Scoped child agent runner
522
+ │ ├── system_prompts.py # Prompt building
523
+ │ ├── display.py # Terminal output & token status
524
+ │ └── completion.py # Tab completion
525
+ ├── core/ # Engine & business logic
526
+ │ ├── engine.py # Provider abstraction & streaming delegation
527
+ │ ├── agent_engine.py # Autonomous agent capabilities
528
+ │ ├── agent_managers.py # Executor/web/MCP/approval manager facades
529
+ │ ├── hooks.py # Lifecycle hooks manager
530
+ │ ├── models.py # Data models (ChatResponse, StreamEvent, etc.)
531
+ │ ├── agent/ # File ops, approval, tool definitions
532
+ │ └── security/ # Permission rules, path validation, sandboxing
533
+ ├── providers/ # 13+ AI provider implementations
534
+ │ ├── base.py # Provider interface (streaming fallback)
535
+ │ ├── claude.py # Anthropic (native streaming & tool calling)
536
+ │ ├── openai.py # OpenAI (native tool calling)
537
+ │ └── ...
538
+ ├── ui/ # Terminal UI components
539
+ │ └── streaming_display.py # Rich Live streaming display
540
+ └── mcp/ # Model Context Protocol (official mcp SDK)
541
+ ├── client.py # Per-server lifecycle (stdio/SSE/HTTP)
542
+ └── manager.py # Multi-server orchestration
543
+ ```
544
+
545
+ ### Streaming architecture
546
+
547
+ Streaming uses async generators that flow through the full stack:
548
+
549
+ ```
550
+ Provider (SSE parsing) → Engine (delegation) → Interface (display routing)
551
+ ↓
552
+ StreamingDisplay (Rich Live panel)
553
+ ```
554
+
555
+ Each layer yields `StreamEvent` objects. Providers that don't implement real streaming get an automatic fallback in `BaseProvider` that wraps the full response in the same event format, so the UI code works identically for all providers.
556
+
557
+ ## Development
558
+
559
+ ```bash
560
+ git clone https://gitlab.com/jite-ai/omnimancer
561
+ cd omnimancer
562
+ pip install -e ".[dev]"
563
+ pytest tests/ -v
564
+ ```
565
+
566
+ Tests follow TDD. 1,460 tests across providers, CLI, streaming, agent operations, hooks, permissions, MCP, and integration scenarios (including a real MCP stdio server exercised end-to-end).
567
+
568
+ ## License
569
+
570
+ MIT