gemcode 0.3.67__tar.gz → 0.3.68__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.
- {gemcode-0.3.67/src/gemcode.egg-info → gemcode-0.3.68}/PKG-INFO +1 -1
- {gemcode-0.3.67 → gemcode-0.3.68}/pyproject.toml +1 -1
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/callbacks.py +19 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/config.py +10 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/dynamic_policy.py +50 -24
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/invoke.py +26 -0
- {gemcode-0.3.67 → gemcode-0.3.68/src/gemcode.egg-info}/PKG-INFO +1 -1
- {gemcode-0.3.67 → gemcode-0.3.68}/LICENSE +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/MANIFEST.in +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/README.md +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/setup.cfg +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/__init__.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/__main__.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/agent.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/audit.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/autocompact.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/capability_routing.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/cli.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/compaction.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/computer_use/__init__.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/computer_use/browser_computer.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/context_budget.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/context_warning.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/credentials.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/hitl_session.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/hooks.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/intent_classifier.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/interactions.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/kairos_daemon.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/limits.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/live_audio_engine.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/logging_config.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/mcp_loader.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/memory/__init__.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/memory/embedding_memory_service.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/memory/file_memory_service.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/modality_tools.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/model_errors.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/model_routing.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/openapi_loader.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/paths.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/permissions.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/plugins/__init__.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/plugins/terminal_hooks_plugin.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/plugins/tool_recovery_plugin.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/pricing.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/prompt_suggestions.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/query/__init__.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/query/config.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/query/deps.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/query/engine.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/query/stop_hooks.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/query/token_budget.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/query/transitions.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/refine.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/repl_commands.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/repl_slash.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/review_agent.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/session_runtime.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/session_store.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/slash_commands.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/thinking.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/tool_prompt_manifest.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/tool_registry.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/tool_result_store.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/tools/__init__.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/tools/bash.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/tools/browser.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/tools/edit.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/tools/filesystem.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/tools/notebook.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/tools/notes.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/tools/repo_map.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/tools/search.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/tools/shell.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/tools/shell_gate.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/tools/subtask.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/tools/tasks.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/tools/think.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/tools/todo.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/tools/web.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/tools/web_search.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/tools_inspector.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/trust.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/tui/input_handler.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/tui/scrollback.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/tui/spinner.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/tui/welcome_banner.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/tui/welcome_rich.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/version.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/vertex.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/web/__init__.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/web/claude_sse_adapter.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/web/terminal_repl.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode/workspace_hints.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode.egg-info/SOURCES.txt +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode.egg-info/dependency_links.txt +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode.egg-info/entry_points.txt +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode.egg-info/requires.txt +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/src/gemcode.egg-info/top_level.txt +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/tests/test_agent_instruction.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/tests/test_autocompact.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/tests/test_capability_routing.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/tests/test_claude_web_adapter_sse.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/tests/test_cli_init.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/tests/test_computer_use_permissions.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/tests/test_context_budget.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/tests/test_context_warning.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/tests/test_credentials.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/tests/test_interactive_permission_ask.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/tests/test_kairos_scheduler.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/tests/test_modality_tools.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/tests/test_model_error_retry.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/tests/test_model_errors.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/tests/test_model_routing.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/tests/test_paths.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/tests/test_permissions.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/tests/test_prompt_suggestions.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/tests/test_repl_commands.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/tests/test_repl_slash.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/tests/test_slash_commands.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/tests/test_thinking_config.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/tests/test_token_budget.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/tests/test_tool_context_circulation.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/tests/test_tools.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/tests/test_tools_inspector.py +0 -0
- {gemcode-0.3.67 → gemcode-0.3.68}/tests/test_workspace_hints.py +0 -0
|
@@ -384,6 +384,25 @@ def make_after_tool_callback(cfg: GemCodeConfig):
|
|
|
384
384
|
st[_STATE_FAILURE_KEY] = 0
|
|
385
385
|
else:
|
|
386
386
|
st[_STATE_FAILURE_KEY] = 0
|
|
387
|
+
|
|
388
|
+
# Risk feedback: if tools are failing or commands return non-zero, treat the
|
|
389
|
+
# task as higher-risk and allow more evidence in subsequent tool outputs.
|
|
390
|
+
try:
|
|
391
|
+
cur = float(getattr(cfg, "_risk_score", 0.0) or 0.0)
|
|
392
|
+
bump = 0.0
|
|
393
|
+
if err:
|
|
394
|
+
bump += 0.15
|
|
395
|
+
if isinstance(tool_response, dict) and isinstance(tool_response.get("exit_code"), int):
|
|
396
|
+
if int(tool_response["exit_code"]) != 0:
|
|
397
|
+
bump += 0.10
|
|
398
|
+
# decay slowly when things are healthy
|
|
399
|
+
if bump == 0.0:
|
|
400
|
+
cur = max(0.0, cur * 0.90)
|
|
401
|
+
else:
|
|
402
|
+
cur = min(1.0, cur + bump)
|
|
403
|
+
object.__setattr__(cfg, "_risk_score", cur)
|
|
404
|
+
except Exception:
|
|
405
|
+
pass
|
|
387
406
|
# ── Shell hooks: post_tool_use ────────────────────────────────────────
|
|
388
407
|
try:
|
|
389
408
|
from gemcode.hooks import run_post_tool_use_hook
|
|
@@ -143,6 +143,16 @@ class GemCodeConfig:
|
|
|
143
143
|
dynamic_token_policy: bool = field(
|
|
144
144
|
default_factory=lambda: _truthy_env("GEMCODE_DYNAMIC_TOKEN_POLICY", default=True)
|
|
145
145
|
)
|
|
146
|
+
|
|
147
|
+
# Dynamic risk policy: boosts caps when the current task appears risky/complex.
|
|
148
|
+
dynamic_risk_policy: bool = field(
|
|
149
|
+
default_factory=lambda: _truthy_env("GEMCODE_DYNAMIC_RISK_POLICY", default=True)
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
# How much the risk score can expand caps (0.0-1.5 reasonable).
|
|
153
|
+
dynamic_risk_boost: float = field(
|
|
154
|
+
default_factory=lambda: float(os.environ.get("GEMCODE_DYNAMIC_RISK_BOOST", "0.6"))
|
|
155
|
+
)
|
|
146
156
|
# Trim oldest text in llm_request.contents when over budget (see context_budget.py).
|
|
147
157
|
context_shrink_enabled: bool = field(
|
|
148
158
|
default_factory=lambda: _truthy_env("GEMCODE_CONTEXT_SHRINK", default=True)
|
|
@@ -32,6 +32,20 @@ def _pct_left(cfg) -> int | None:
|
|
|
32
32
|
return None
|
|
33
33
|
|
|
34
34
|
|
|
35
|
+
def _risk(cfg) -> float:
|
|
36
|
+
try:
|
|
37
|
+
v = getattr(cfg, "_risk_score", None)
|
|
38
|
+
if isinstance(v, (int, float)):
|
|
39
|
+
return float(v)
|
|
40
|
+
except Exception:
|
|
41
|
+
return 0.0
|
|
42
|
+
return 0.0
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _clamp(x: float, lo: float, hi: float) -> float:
|
|
46
|
+
return lo if x < lo else hi if x > hi else x
|
|
47
|
+
|
|
48
|
+
|
|
35
49
|
@dataclass(frozen=True)
|
|
36
50
|
class DynamicCaps:
|
|
37
51
|
tool_inline_chars: int
|
|
@@ -52,6 +66,8 @@ def get_dynamic_caps(cfg) -> DynamicCaps:
|
|
|
52
66
|
- Healthy (>=45% left): generous caps (better evidence, less re-asking).
|
|
53
67
|
- Warning (20-44%): moderate caps.
|
|
54
68
|
- Tight (<20%): strict caps + prefer offload.
|
|
69
|
+
|
|
70
|
+
Then apply a risk-based boost (if enabled) so complex tasks stay evidence-rich.
|
|
55
71
|
"""
|
|
56
72
|
# cfg can be None in some tool contexts; treat as enabled with defaults.
|
|
57
73
|
enabled = _truthy(getattr(cfg, "dynamic_token_policy", True) if cfg is not None else True, default=True)
|
|
@@ -76,42 +92,52 @@ def get_dynamic_caps(cfg) -> DynamicCaps:
|
|
|
76
92
|
base_tool = int(getattr(cfg, "tool_result_max_chars", 12000) or 12000) if cfg is not None else 12000
|
|
77
93
|
base_tool = max(1000, base_tool)
|
|
78
94
|
|
|
95
|
+
# Risk boost: scale caps upward for risky tasks, but keep bounded.
|
|
96
|
+
risk_enabled = _truthy(getattr(cfg, "dynamic_risk_policy", True) if cfg is not None else True, default=True)
|
|
97
|
+
risk_boost = float(getattr(cfg, "dynamic_risk_boost", 0.6) if cfg is not None else 0.6)
|
|
98
|
+
risk_score = _risk(cfg) if (cfg is not None and risk_enabled) else 0.0
|
|
99
|
+
risk_score = _clamp(risk_score, 0.0, 1.0)
|
|
100
|
+
boost = 1.0 + (_clamp(risk_boost, 0.0, 1.5) * risk_score)
|
|
101
|
+
|
|
102
|
+
def _scale(n: int, *, cap: int) -> int:
|
|
103
|
+
return min(cap, max(1000, int(n * boost)))
|
|
104
|
+
|
|
79
105
|
if pct >= 45:
|
|
80
106
|
mult = 1.4
|
|
81
107
|
return DynamicCaps(
|
|
82
|
-
tool_inline_chars=min(24_000, int(base_tool * mult)),
|
|
83
|
-
read_file_max_bytes=140_000,
|
|
84
|
-
web_fetch_max_chars=30_000,
|
|
85
|
-
bash_stdout_chars=30_000,
|
|
86
|
-
bash_stderr_chars=15_000,
|
|
87
|
-
run_stdout_chars=30_000,
|
|
88
|
-
run_stderr_chars=30_000,
|
|
89
|
-
grep_max_matches=60,
|
|
108
|
+
tool_inline_chars=_scale(min(24_000, int(base_tool * mult)), cap=30_000),
|
|
109
|
+
read_file_max_bytes=min(200_000, int(140_000 * boost)),
|
|
110
|
+
web_fetch_max_chars=min(60_000, int(30_000 * boost)),
|
|
111
|
+
bash_stdout_chars=min(80_000, int(30_000 * boost)),
|
|
112
|
+
bash_stderr_chars=min(40_000, int(15_000 * boost)),
|
|
113
|
+
run_stdout_chars=min(80_000, int(30_000 * boost)),
|
|
114
|
+
run_stderr_chars=min(80_000, int(30_000 * boost)),
|
|
115
|
+
grep_max_matches=min(200, int(60 * boost)),
|
|
90
116
|
)
|
|
91
117
|
|
|
92
118
|
if pct >= 20:
|
|
93
119
|
mult = 1.0
|
|
94
120
|
return DynamicCaps(
|
|
95
|
-
tool_inline_chars=min(18_000, int(base_tool * mult)),
|
|
96
|
-
read_file_max_bytes=80_000,
|
|
97
|
-
web_fetch_max_chars=20_000,
|
|
98
|
-
bash_stdout_chars=20_000,
|
|
99
|
-
bash_stderr_chars=10_000,
|
|
100
|
-
run_stdout_chars=20_000,
|
|
101
|
-
run_stderr_chars=20_000,
|
|
102
|
-
grep_max_matches=40,
|
|
121
|
+
tool_inline_chars=_scale(min(18_000, int(base_tool * mult)), cap=24_000),
|
|
122
|
+
read_file_max_bytes=min(160_000, int(80_000 * boost)),
|
|
123
|
+
web_fetch_max_chars=min(40_000, int(20_000 * boost)),
|
|
124
|
+
bash_stdout_chars=min(50_000, int(20_000 * boost)),
|
|
125
|
+
bash_stderr_chars=min(30_000, int(10_000 * boost)),
|
|
126
|
+
run_stdout_chars=min(50_000, int(20_000 * boost)),
|
|
127
|
+
run_stderr_chars=min(50_000, int(20_000 * boost)),
|
|
128
|
+
grep_max_matches=min(120, int(40 * boost)),
|
|
103
129
|
)
|
|
104
130
|
|
|
105
131
|
# Tight
|
|
106
132
|
mult = 0.6
|
|
107
133
|
return DynamicCaps(
|
|
108
|
-
tool_inline_chars=max(2000, int(base_tool * mult)),
|
|
109
|
-
read_file_max_bytes=35_000,
|
|
110
|
-
web_fetch_max_chars=10_000,
|
|
111
|
-
bash_stdout_chars=10_000,
|
|
112
|
-
bash_stderr_chars=8_000,
|
|
113
|
-
run_stdout_chars=10_000,
|
|
114
|
-
run_stderr_chars=10_000,
|
|
115
|
-
grep_max_matches=20,
|
|
134
|
+
tool_inline_chars=max(2000, min(12_000, int(base_tool * mult * boost))),
|
|
135
|
+
read_file_max_bytes=min(90_000, int(35_000 * boost)),
|
|
136
|
+
web_fetch_max_chars=min(20_000, int(10_000 * boost)),
|
|
137
|
+
bash_stdout_chars=min(25_000, int(10_000 * boost)),
|
|
138
|
+
bash_stderr_chars=min(20_000, int(8_000 * boost)),
|
|
139
|
+
run_stdout_chars=min(25_000, int(10_000 * boost)),
|
|
140
|
+
run_stderr_chars=min(25_000, int(10_000 * boost)),
|
|
141
|
+
grep_max_matches=min(80, int(20 * boost)),
|
|
116
142
|
)
|
|
117
143
|
|
|
@@ -68,6 +68,32 @@ async def run_turn(
|
|
|
68
68
|
cfg: "GemCodeConfig | None" = None,
|
|
69
69
|
) -> list:
|
|
70
70
|
"""Execute one user message; collect all Events (caller aggregates text)."""
|
|
71
|
+
# Dynamic risk score: updated each user message; later refined by tool outcomes.
|
|
72
|
+
# This is intentionally heuristic but configurable via env knobs.
|
|
73
|
+
if cfg is not None:
|
|
74
|
+
try:
|
|
75
|
+
import re
|
|
76
|
+
p = (prompt or "")[:20_000]
|
|
77
|
+
risk = 0.0
|
|
78
|
+
# Complexity signals
|
|
79
|
+
if len(p) > 600:
|
|
80
|
+
risk += 0.15
|
|
81
|
+
if len(p) > 2000:
|
|
82
|
+
risk += 0.15
|
|
83
|
+
if re.search(r"\\b(refactor|migrate|rewrite|optimi[sz]e|architecture)\\b", p, re.I):
|
|
84
|
+
risk += 0.2
|
|
85
|
+
if re.search(r"\\b(bug|fix|regression|error|traceback|failing)\\b", p, re.I):
|
|
86
|
+
risk += 0.2
|
|
87
|
+
if re.search(r"\\b(test|pytest|ci|build|deploy|release)\\b", p, re.I):
|
|
88
|
+
risk += 0.1
|
|
89
|
+
# Multi-file hints
|
|
90
|
+
if p.count(\"/\") >= 6 or p.count(\".py\") + p.count(\".ts\") + p.count(\".tsx\") >= 3:
|
|
91
|
+
risk += 0.1
|
|
92
|
+
# Clamp 0..1
|
|
93
|
+
risk = max(0.0, min(1.0, float(risk)))
|
|
94
|
+
object.__setattr__(cfg, \"_risk_score\", risk)
|
|
95
|
+
except Exception:
|
|
96
|
+
pass
|
|
71
97
|
run_config = (
|
|
72
98
|
RunConfig(max_llm_calls=max_llm_calls) if max_llm_calls is not None else None
|
|
73
99
|
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|