omnimancer-cli 0.2.13__tar.gz → 0.2.15__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 (156) hide show
  1. {omnimancer_cli-0.2.13/omnimancer_cli.egg-info → omnimancer_cli-0.2.15}/PKG-INFO +1 -1
  2. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/cli/headless.py +21 -0
  3. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/agent/file_system_manager.py +8 -0
  4. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/agent/program_executor.py +9 -0
  5. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/agent_managers.py +24 -0
  6. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/security/permission_controller.py +16 -1
  7. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/security/security_manager.py +11 -0
  8. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15/omnimancer_cli.egg-info}/PKG-INFO +1 -1
  9. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/pyproject.toml +1 -1
  10. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/LICENSE +0 -0
  11. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/README.md +0 -0
  12. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/__init__.py +0 -0
  13. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/__main__.py +0 -0
  14. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/cli/__init__.py +0 -0
  15. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/cli/agent_loop.py +0 -0
  16. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/cli/approval_formatter.py +0 -0
  17. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/cli/approval_integration.py +0 -0
  18. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/cli/approval_prompt.py +0 -0
  19. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/cli/command_dispatch.py +0 -0
  20. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/cli/commands.py +0 -0
  21. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/cli/completion.py +0 -0
  22. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/cli/display.py +0 -0
  23. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/cli/dynamic_commands.py +0 -0
  24. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/cli/handlers/__init__.py +0 -0
  25. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/cli/interface.py +0 -0
  26. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/cli/subagent.py +0 -0
  27. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/cli/system_prompts.py +0 -0
  28. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/cli/tool_handler.py +0 -0
  29. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/__init__.py +0 -0
  30. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/agent/__init__.py +0 -0
  31. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/agent/approval_context.py +0 -0
  32. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/agent/approval_interface.py +0 -0
  33. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/agent/approval_manager.py +0 -0
  34. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/agent/config.py +0 -0
  35. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/agent/read_before_write_errors.py +0 -0
  36. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/agent/status_core.py +0 -0
  37. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/agent/status_manager.py +0 -0
  38. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/agent/tool_definitions.py +0 -0
  39. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/agent/types.py +0 -0
  40. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/agent/web_client.py +0 -0
  41. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/agent/workflow_orchestrator.py +0 -0
  42. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/agent_engine.py +0 -0
  43. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/agent_mode_manager.py +0 -0
  44. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/chat_manager.py +0 -0
  45. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/config_manager.py +0 -0
  46. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/config_migration.py +0 -0
  47. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/config_validator.py +0 -0
  48. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/conversation_manager.py +0 -0
  49. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/engine.py +0 -0
  50. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/env_loader.py +0 -0
  51. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/fallback_manager.py +0 -0
  52. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/health_monitor.py +0 -0
  53. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/history_manager.py +0 -0
  54. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/hooks.py +0 -0
  55. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/mcp_integration_layer.py +0 -0
  56. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/models.py +0 -0
  57. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/provider_capabilities.py +0 -0
  58. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/provider_initializer.py +0 -0
  59. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/provider_registry.py +0 -0
  60. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/rate_limit_fallback.py +0 -0
  61. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/security/__init__.py +0 -0
  62. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/security/approval_workflow.py +0 -0
  63. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/security/audit_logger.py +0 -0
  64. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/security/permission_rules.py +0 -0
  65. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/security/sandbox_manager.py +0 -0
  66. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/core/signal_handler.py +0 -0
  67. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/mcp/__init__.py +0 -0
  68. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/mcp/client.py +0 -0
  69. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/mcp/manager.py +0 -0
  70. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/providers/__init__.py +0 -0
  71. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/providers/azure.py +0 -0
  72. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/providers/base.py +0 -0
  73. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/providers/bedrock.py +0 -0
  74. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/providers/claude.py +0 -0
  75. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/providers/claude_code.py +0 -0
  76. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/providers/claude_credentials.py +0 -0
  77. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/providers/cohere.py +0 -0
  78. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/providers/digitalocean.py +0 -0
  79. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/providers/factory.py +0 -0
  80. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/providers/gemini.py +0 -0
  81. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/providers/mistral.py +0 -0
  82. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/providers/ollama.py +0 -0
  83. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/providers/openai.py +0 -0
  84. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/providers/openrouter.py +0 -0
  85. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/providers/perplexity.py +0 -0
  86. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/providers/vertex.py +0 -0
  87. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/providers/xai.py +0 -0
  88. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/ui/__init__.py +0 -0
  89. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/ui/cancellation_handler.py +0 -0
  90. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/ui/progress_indicator.py +0 -0
  91. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/ui/streaming_display.py +0 -0
  92. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/utils/__init__.py +0 -0
  93. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/utils/error_handler.py +0 -0
  94. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/utils/errors.py +0 -0
  95. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer/utils/retry.py +0 -0
  96. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer_cli.egg-info/SOURCES.txt +0 -0
  97. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer_cli.egg-info/dependency_links.txt +0 -0
  98. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer_cli.egg-info/entry_points.txt +0 -0
  99. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer_cli.egg-info/requires.txt +0 -0
  100. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/omnimancer_cli.egg-info/top_level.txt +0 -0
  101. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/setup.cfg +0 -0
  102. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_approval_integration_compatibility.py +0 -0
  103. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_approval_preview_format.py +0 -0
  104. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_approval_remember.py +0 -0
  105. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_approval_system.py +0 -0
  106. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_azure_provider.py +0 -0
  107. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_bedrock_provider.py +0 -0
  108. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_claude_code_provider.py +0 -0
  109. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_claude_credentials.py +0 -0
  110. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_claude_provider.py +0 -0
  111. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_cohere_provider.py +0 -0
  112. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_command_approval_security.py +0 -0
  113. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_config_comprehensive.py +0 -0
  114. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_conversation_history.py +0 -0
  115. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_conversation_manager.py +0 -0
  116. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_core_engine.py +0 -0
  117. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_digitalocean_provider.py +0 -0
  118. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_enhanced_model_info.py +0 -0
  119. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_env_loader.py +0 -0
  120. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_error_handling_robustness.py +0 -0
  121. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_execution_timeout_errors.py +0 -0
  122. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_fallback_manager.py +0 -0
  123. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_fixtures.py +0 -0
  124. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_gemini_provider.py +0 -0
  125. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_hooks.py +0 -0
  126. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_httpx_compatibility.py +0 -0
  127. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_import_validation.py +0 -0
  128. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_interface_smoke_tests.py +0 -0
  129. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_mcp_integration.py +0 -0
  130. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_mcp_integration_layer.py +0 -0
  131. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_mcp_management_commands.py +0 -0
  132. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_mistral_provider.py +0 -0
  133. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_models.py +0 -0
  134. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_ollama_provider.py +0 -0
  135. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_openai_context_fit.py +0 -0
  136. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_openai_provider_tools.py +0 -0
  137. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_openrouter_provider.py +0 -0
  138. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_permission_rules.py +0 -0
  139. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_perplexity_provider.py +0 -0
  140. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_program_executor.py +0 -0
  141. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_provider_base.py +0 -0
  142. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_provider_capability_consistency.py +0 -0
  143. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_provider_discovery.py +0 -0
  144. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_provider_integration.py +0 -0
  145. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_provider_registry.py +0 -0
  146. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_rate_limit_fallback.py +0 -0
  147. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_retry.py +0 -0
  148. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_security_validation.py +0 -0
  149. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_system_integration.py +0 -0
  150. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_system_prompts.py +0 -0
  151. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_tool_calling_integration.py +0 -0
  152. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_tool_handler.py +0 -0
  153. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_vertex_provider.py +0 -0
  154. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_web_request_markers.py +0 -0
  155. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/tests/test_workflows_comprehensive.py +0 -0
  156. {omnimancer_cli-0.2.13 → omnimancer_cli-0.2.15}/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.13
3
+ Version: 0.2.15
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
@@ -255,6 +255,26 @@ class HeadlessRunner:
255
255
  if enhanced is not None:
256
256
  enhanced.set_approval_callback(_approve)
257
257
 
258
+ @staticmethod
259
+ def _enable_full_trust(agent_engine: Any) -> None:
260
+ """Relax the hard security layers for unattended full-trust runs.
261
+
262
+ Auto-approval alone is not enough: the command argument sanitizer
263
+ (pipes, &&, redirects), the forbidden-command list, the sensitive
264
+ filename patterns (*key*, *token*, .env, ...), and the 30s default
265
+ command timeout all block operations before/outside the approval
266
+ step, so a --dangerously-skip-permissions run still could not do real
267
+ work. The caller (e.g. a CI or agent container) is the security
268
+ boundary; hard-restricted system paths (~/.ssh, /etc, ...) stay
269
+ blocked.
270
+ """
271
+ executor = getattr(agent_engine, "executor", None)
272
+ if executor is not None and hasattr(executor, "set_full_trust"):
273
+ executor.set_full_trust(True)
274
+ file_system = getattr(agent_engine, "file_system", None)
275
+ if file_system is not None and hasattr(file_system, "set_full_trust"):
276
+ file_system.set_full_trust(True)
277
+
258
278
  async def run(self, prompt: str) -> int:
259
279
  agent_engine = getattr(self._engine, "agent_engine", None)
260
280
  if not agent_engine:
@@ -263,6 +283,7 @@ class HeadlessRunner:
263
283
 
264
284
  if self._no_approval:
265
285
  self._enable_auto_approval(agent_engine)
286
+ self._enable_full_trust(agent_engine)
266
287
 
267
288
  model = self._engine.config_manager.get_config().default_provider or "unknown"
268
289
  self._emitter.emit_init(model)
@@ -79,6 +79,14 @@ class FileSystemManager:
79
79
  # Operation tracking
80
80
  self.active_operations: Dict[str, Dict[str, Any]] = {}
81
81
 
82
+ def set_full_trust(self, enabled: bool) -> None:
83
+ """Enable/disable full-trust mode on the underlying security manager.
84
+
85
+ In full trust, sensitive name patterns (.env, *key*, *token*, ...)
86
+ stop blocking reads/writes; hard-restricted system paths still deny.
87
+ """
88
+ self.security.set_full_trust(enabled)
89
+
82
90
  async def _request_approval_if_needed(self, operation: Operation) -> bool:
83
91
  """Request approval for operation if approval manager is configured."""
84
92
  if not self.require_approval or not self.approval_manager:
@@ -86,6 +86,10 @@ class CommandValidator:
86
86
  """Validates commands against security policies."""
87
87
 
88
88
  def __init__(self) -> None:
89
+ # Full-trust mode (unattended headless runs where an outer sandbox is
90
+ # the security boundary): argument sanitization is skipped so shell
91
+ # constructs (pipes, &&, redirects) reach the shell executor intact.
92
+ self.full_trust = False
89
93
  self.command_categories = {
90
94
  CommandCategory.SAFE_READ: {
91
95
  "ls",
@@ -295,6 +299,11 @@ class CommandValidator:
295
299
 
296
300
  def validate_command_args(self, command: str, args: List[str]) -> List[str]:
297
301
  """Validate and sanitize command arguments."""
302
+ # Full trust: commands run via the shell on purpose — pipes, &&, and
303
+ # redirects are legitimate agent usage there.
304
+ if self.full_trust:
305
+ return list(args)
306
+
298
307
  import re
299
308
 
300
309
  # Define dangerous shell metacharacters and patterns
@@ -159,6 +159,10 @@ class ProgramExecutor(BaseManager):
159
159
  }
160
160
  self.timeout_seconds = self.default_config.timeout_seconds
161
161
 
162
+ # Full-trust mode (unattended headless runs where an outer sandbox is
163
+ # the security boundary) — see set_full_trust().
164
+ self.full_trust = False
165
+
162
166
  async def execute_operation(self, operation: Operation) -> OperationResult:
163
167
  """Execute command operation using enhanced executor.
164
168
 
@@ -261,6 +265,22 @@ class ProgramExecutor(BaseManager):
261
265
  """Terminate a running command."""
262
266
  return await self.enhanced_executor.terminate_command(execution_id)
263
267
 
268
+ def set_full_trust(self, enabled: bool) -> None:
269
+ """Enable full-trust mode for unattended runs.
270
+
271
+ The caller (e.g. a headless agent inside a container) is the security
272
+ boundary: the forbidden-command list and argument sanitization stop
273
+ blocking, and the default per-command timeout is raised so real build/
274
+ test runs can finish. Explicit per-operation timeouts are still honored.
275
+ """
276
+ self.full_trust = enabled
277
+ if enabled:
278
+ self.timeout_seconds = 600
279
+ self.default_config.timeout_seconds = 600
280
+ validator = getattr(self.enhanced_executor, "validator", None)
281
+ if validator is not None:
282
+ validator.full_trust = enabled
283
+
264
284
  def _validate_command(self, command: str) -> bool:
265
285
  """
266
286
  Validate command for backward compatibility with tests.
@@ -278,6 +298,10 @@ class ProgramExecutor(BaseManager):
278
298
  Security is provided through the approval system's risk assessment
279
299
  and user confirmation. Only explicitly dangerous commands are blocked.
280
300
  """
301
+ # Full trust: forbidden-command blocking is disabled.
302
+ if self.full_trust:
303
+ return True
304
+
281
305
  # Extract the base command (first word)
282
306
  base_command = command.strip().split()[0] if command.strip() else ""
283
307
 
@@ -46,6 +46,11 @@ class PermissionController:
46
46
  self.allowed_commands = self._get_default_allowed_commands()
47
47
  self.permission_rules = self._get_default_permission_rules()
48
48
 
49
+ # Full-trust mode (unattended headless runs where an outer sandbox is
50
+ # the security boundary): sensitive name patterns and the command
51
+ # allowlist stop blocking. Hard-restricted paths still deny.
52
+ self.full_trust = False
53
+
49
54
  # Initialize approval memory storage
50
55
  self._approval_memory: Dict[str, Dict[str, Any]] = {}
51
56
 
@@ -193,11 +198,16 @@ class PermissionController:
193
198
  # Normalize path
194
199
  normalized_path = str(Path(path).resolve())
195
200
 
196
- # Hard-restricted paths are denied regardless of approval.
201
+ # Hard-restricted paths are denied regardless of approval —
202
+ # including full-trust mode.
197
203
  for restricted in self.restricted_paths:
198
204
  if self._path_matches_pattern(normalized_path, restricted):
199
205
  return False
200
206
 
207
+ # Full trust treats every operation as explicitly allowed.
208
+ if self.full_trust:
209
+ allow_sensitive = True
210
+
201
211
  # Sensitive name patterns are denied unless explicitly allowed.
202
212
  if not allow_sensitive:
203
213
  for pattern in self.sensitive_patterns:
@@ -238,6 +248,11 @@ class PermissionController:
238
248
 
239
249
  def validate_command(self, command: str) -> bool:
240
250
  """Validate if command execution is allowed."""
251
+ # Full trust: the allowlist and pattern checks stop blocking — the
252
+ # outer sandbox is the security boundary.
253
+ if self.full_trust:
254
+ return True
255
+
241
256
  # Extract base command (first word)
242
257
  base_command = command.strip().split()[0]
243
258
 
@@ -327,6 +327,17 @@ class SecurityManager:
327
327
  result["stderr"] = f"Security manager error: {str(e)}"
328
328
  return result
329
329
 
330
+ def set_full_trust(self, enabled: bool) -> None:
331
+ """Enable/disable full-trust mode on the permission controller.
332
+
333
+ Full trust is for unattended runs (e.g. headless agents inside a
334
+ container) where the caller is the security boundary: sensitive name
335
+ patterns and the command allowlist stop blocking operations. The
336
+ hard-restricted system paths in PermissionController.restricted_paths
337
+ still deny.
338
+ """
339
+ self.permissions.full_trust = enabled
340
+
330
341
  async def secure_file_access(
331
342
  self,
332
343
  file_path: str,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: omnimancer-cli
3
- Version: 0.2.13
3
+ Version: 0.2.15
4
4
  Summary: A unified command-line interface for multiple AI language models
5
5
  Author-email: Kellan Strong <kellan@jite.ai>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "omnimancer-cli"
7
- version = "0.2.13"
7
+ version = "0.2.15"
8
8
  description = "A unified command-line interface for multiple AI language models"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
File without changes