omnimancer-cli 0.2.20__tar.gz → 0.2.22__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {omnimancer_cli-0.2.20/omnimancer_cli.egg-info → omnimancer_cli-0.2.22}/PKG-INFO +1 -1
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/cli/headless.py +77 -4
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22/omnimancer_cli.egg-info}/PKG-INFO +1 -1
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/pyproject.toml +1 -1
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/LICENSE +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/README.md +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/__init__.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/__main__.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/cli/__init__.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/cli/agent_loop.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/cli/approval_formatter.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/cli/approval_integration.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/cli/approval_prompt.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/cli/command_dispatch.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/cli/commands.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/cli/completion.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/cli/display.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/cli/dynamic_commands.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/cli/handlers/__init__.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/cli/interface.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/cli/subagent.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/cli/system_prompts.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/cli/tool_handler.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/__init__.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/agent/__init__.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/agent/approval_context.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/agent/approval_interface.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/agent/approval_manager.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/agent/config.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/agent/file_system_manager.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/agent/program_executor.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/agent/read_before_write_errors.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/agent/status_core.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/agent/status_manager.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/agent/tool_definitions.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/agent/types.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/agent/web_client.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/agent/workflow_orchestrator.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/agent_engine.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/agent_managers.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/agent_mode_manager.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/chat_manager.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/config_manager.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/config_migration.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/config_validator.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/conversation_manager.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/engine.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/env_loader.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/fallback_manager.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/health_monitor.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/history_manager.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/hooks.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/mcp_integration_layer.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/models.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/provider_capabilities.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/provider_initializer.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/provider_registry.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/rate_limit_fallback.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/security/__init__.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/security/approval_workflow.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/security/audit_logger.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/security/permission_controller.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/security/permission_rules.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/security/sandbox_manager.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/security/security_manager.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/signal_handler.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/mcp/__init__.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/mcp/client.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/mcp/manager.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/providers/__init__.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/providers/azure.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/providers/base.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/providers/bedrock.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/providers/claude.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/providers/claude_code.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/providers/claude_credentials.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/providers/cohere.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/providers/digitalocean.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/providers/factory.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/providers/gemini.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/providers/mistral.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/providers/ollama.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/providers/openai.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/providers/openrouter.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/providers/perplexity.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/providers/vertex.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/providers/xai.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/ui/__init__.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/ui/cancellation_handler.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/ui/progress_indicator.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/ui/streaming_display.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/utils/__init__.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/utils/error_handler.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/utils/errors.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/utils/retry.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer_cli.egg-info/SOURCES.txt +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer_cli.egg-info/dependency_links.txt +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer_cli.egg-info/entry_points.txt +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer_cli.egg-info/requires.txt +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer_cli.egg-info/top_level.txt +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/setup.cfg +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_approval_integration_compatibility.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_approval_preview_format.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_approval_remember.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_approval_system.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_azure_provider.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_bedrock_provider.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_claude_code_provider.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_claude_credentials.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_claude_provider.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_cohere_provider.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_command_approval_security.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_config_comprehensive.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_conversation_history.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_conversation_manager.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_core_engine.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_digitalocean_provider.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_enhanced_model_info.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_env_loader.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_error_handling_robustness.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_execution_timeout_errors.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_fallback_manager.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_fixtures.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_gemini_provider.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_hooks.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_httpx_compatibility.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_import_validation.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_interface_smoke_tests.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_mcp_integration.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_mcp_integration_layer.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_mcp_management_commands.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_mistral_provider.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_models.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_ollama_provider.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_openai_context_fit.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_openai_provider_tools.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_openai_request_timeout.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_openrouter_provider.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_permission_rules.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_perplexity_provider.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_program_executor.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_provider_base.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_provider_capability_consistency.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_provider_discovery.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_provider_integration.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_provider_registry.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_rate_limit_fallback.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_retry.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_security_validation.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_system_integration.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_system_prompts.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_tool_calling_integration.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_tool_handler.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_vertex_provider.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_web_request_markers.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_workflows_comprehensive.py +0 -0
- {omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_xai_provider.py +0 -0
|
@@ -5,6 +5,8 @@ results to stdout. No Rich console, no readline, no interactive UI.
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import json
|
|
8
|
+
import logging
|
|
9
|
+
import os
|
|
8
10
|
import sys
|
|
9
11
|
import uuid
|
|
10
12
|
from enum import Enum
|
|
@@ -24,6 +26,53 @@ from .tool_handler import (
|
|
|
24
26
|
ToolHandler,
|
|
25
27
|
)
|
|
26
28
|
|
|
29
|
+
logger = logging.getLogger(__name__)
|
|
30
|
+
|
|
31
|
+
# A turn with no tool calls used to end the run immediately. Models that
|
|
32
|
+
# narrate their plan ("Let me look into X...") without attaching a tool call
|
|
33
|
+
# made headless runs "complete" with zero work done, so the runner now nudges
|
|
34
|
+
# the model to either keep working or explicitly declare completion.
|
|
35
|
+
NO_TOOL_CALL_NUDGE = (
|
|
36
|
+
"You did not call any tools. If the task is fully complete, reply with "
|
|
37
|
+
"exactly DONE. Otherwise continue working now by calling tools — do not "
|
|
38
|
+
"describe what you plan to do without doing it."
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
# Consecutive tool-less turns tolerated before the run is ended anyway.
|
|
42
|
+
MAX_NO_TOOL_NUDGES = 2
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _is_done_reply(content: Optional[str]) -> bool:
|
|
46
|
+
"""True when the model explicitly declares completion per the nudge."""
|
|
47
|
+
if not content:
|
|
48
|
+
return False
|
|
49
|
+
lines = content.strip().splitlines()
|
|
50
|
+
if not lines:
|
|
51
|
+
return False
|
|
52
|
+
return lines[-1].strip().rstrip(".!").upper() == "DONE"
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _resolve_max_iterations(explicit: Optional[int]) -> int:
|
|
56
|
+
"""Resolve the tool-iteration cap: explicit value wins, then the
|
|
57
|
+
OMNIMANCER_MAX_ITERATIONS environment variable, then the default.
|
|
58
|
+
|
|
59
|
+
The default (25) suits interactive use; orchestrators running real
|
|
60
|
+
coding tasks inject a higher cap — exhausting it mid-task previously
|
|
61
|
+
looked like a clean "completed" run with no changes.
|
|
62
|
+
"""
|
|
63
|
+
if explicit:
|
|
64
|
+
return explicit
|
|
65
|
+
raw = os.environ.get("OMNIMANCER_MAX_ITERATIONS")
|
|
66
|
+
if raw:
|
|
67
|
+
try:
|
|
68
|
+
value = int(raw)
|
|
69
|
+
if value > 0:
|
|
70
|
+
return value
|
|
71
|
+
logger.warning("Ignoring non-positive OMNIMANCER_MAX_ITERATIONS %r", raw)
|
|
72
|
+
except ValueError:
|
|
73
|
+
logger.warning("Ignoring invalid OMNIMANCER_MAX_ITERATIONS %r", raw)
|
|
74
|
+
return MAX_TOOL_ITERATIONS
|
|
75
|
+
|
|
27
76
|
|
|
28
77
|
class OutputFormat(Enum):
|
|
29
78
|
TEXT = "text"
|
|
@@ -229,7 +278,7 @@ class HeadlessRunner:
|
|
|
229
278
|
self._verbose = verbose
|
|
230
279
|
# Headless runs are unattended, so a cap (not a check-in prompt) is
|
|
231
280
|
# the safety net; --max-iterations sizes it to the job.
|
|
232
|
-
self._max_iterations = max_iterations
|
|
281
|
+
self._max_iterations = _resolve_max_iterations(max_iterations)
|
|
233
282
|
session_id = str(uuid.uuid4())
|
|
234
283
|
self._emitter = HeadlessOutputEmitter(output_format, session_id, verbose)
|
|
235
284
|
self._tokens = TokenAccumulator()
|
|
@@ -296,6 +345,7 @@ class HeadlessRunner:
|
|
|
296
345
|
|
|
297
346
|
current_message = f"{agent_prompt}\n\nUser: {prompt}"
|
|
298
347
|
last_content = ""
|
|
348
|
+
prev_content = ""
|
|
299
349
|
last_model = model
|
|
300
350
|
last_stop_reason = "end_turn"
|
|
301
351
|
# Record of the actions the agent took, surfaced in the JSON result.
|
|
@@ -304,6 +354,7 @@ class HeadlessRunner:
|
|
|
304
354
|
# Identical repeated calls get skipped with a corrective nudge; the
|
|
305
355
|
# run is aborted only if the model keeps repeating despite nudges.
|
|
306
356
|
repeat_tracker = RepeatedCallTracker()
|
|
357
|
+
no_tool_nudges = 0
|
|
307
358
|
|
|
308
359
|
for iteration in range(self._max_iterations):
|
|
309
360
|
turns = iteration + 1
|
|
@@ -322,6 +373,7 @@ class HeadlessRunner:
|
|
|
322
373
|
last_stop_reason = response.stop_reason or "end_turn"
|
|
323
374
|
|
|
324
375
|
if response.content:
|
|
376
|
+
prev_content = last_content
|
|
325
377
|
last_content = response.content
|
|
326
378
|
self._emitter.emit_assistant(
|
|
327
379
|
response.content,
|
|
@@ -334,9 +386,30 @@ class HeadlessRunner:
|
|
|
334
386
|
# those so the run doesn't end with the work undone.
|
|
335
387
|
if not response.tool_calls:
|
|
336
388
|
recovered = parse_described_tool_calls(response.content)
|
|
337
|
-
if
|
|
338
|
-
|
|
339
|
-
|
|
389
|
+
if recovered:
|
|
390
|
+
response.tool_calls = recovered
|
|
391
|
+
else:
|
|
392
|
+
# No tool call: either the final answer or narration from
|
|
393
|
+
# a model that stopped without acting. End the run only on
|
|
394
|
+
# an explicit DONE or after repeated nudges — breaking
|
|
395
|
+
# immediately made agents "complete" with zero changes.
|
|
396
|
+
if (
|
|
397
|
+
_is_done_reply(response.content)
|
|
398
|
+
or no_tool_nudges >= MAX_NO_TOOL_NUDGES
|
|
399
|
+
):
|
|
400
|
+
# A bare "DONE" acknowledgment must not replace the
|
|
401
|
+
# model's actual final summary in the result payload.
|
|
402
|
+
if (
|
|
403
|
+
response.content
|
|
404
|
+
and response.content.strip().rstrip(".!").upper() == "DONE"
|
|
405
|
+
and prev_content
|
|
406
|
+
):
|
|
407
|
+
last_content = prev_content
|
|
408
|
+
break
|
|
409
|
+
no_tool_nudges += 1
|
|
410
|
+
current_message = NO_TOOL_CALL_NUDGE
|
|
411
|
+
continue
|
|
412
|
+
no_tool_nudges = 0
|
|
340
413
|
|
|
341
414
|
repeat_tracker.record(response.tool_calls)
|
|
342
415
|
offender = repeat_tracker.abort_offender(response.tool_calls)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/agent/file_system_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
{omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/agent/read_before_write_errors.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/agent/workflow_orchestrator.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/security/approval_workflow.py
RENAMED
|
File without changes
|
|
File without changes
|
{omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/security/permission_controller.py
RENAMED
|
File without changes
|
{omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/security/permission_rules.py
RENAMED
|
File without changes
|
|
File without changes
|
{omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer/core/security/security_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/omnimancer_cli.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_approval_integration_compatibility.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{omnimancer_cli-0.2.20 → omnimancer_cli-0.2.22}/tests/test_provider_capability_consistency.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|