regcode 0.4.1__tar.gz → 0.5.0__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.
- {regcode-0.4.1 → regcode-0.5.0}/PKG-INFO +1 -1
- {regcode-0.4.1 → regcode-0.5.0}/pyproject.toml +1 -1
- {regcode-0.4.1 → regcode-0.5.0}/regcode/__init__.py +1 -1
- {regcode-0.4.1 → regcode-0.5.0}/regcode/tui.py +32 -3
- {regcode-0.4.1 → regcode-0.5.0}/uv.lock +1 -1
- regcode-0.4.1/repair_tui.md +0 -115
- {regcode-0.4.1 → regcode-0.5.0}/.gitignore +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/.python-version +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/.qwen/settings.json +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/AGENTS.md +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/GOALS.md +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/README.md +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/config.yaml.template +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/main.py +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/regcode/cli.py +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/regcode/config.py +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/regcode/conversation_manager.py +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/regcode/dependencies.py +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/regcode/main.py +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/regcode/monty_sandbox.py +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/regcode/permissions.py +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/regcode/sandbox.py +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/regcode/tools/__init__.py +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/regcode/tools/base.py +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/regcode/tools/builtins.py +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/regcode/tools/registry.py +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/regcode/tools/review_notes.py +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/regcode/tools/web_crawl.py +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/regcode/tracing.py +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/tests/__init__.py +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/tests/conftest.py +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/tests/test_api.py +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/tests/test_cli.py +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/tests/test_config.py +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/tests/test_context_manager.py +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/tests/test_dependencies.py +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/tests/test_main.py +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/tests/test_monty_sandbox.py +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/tests/test_osv_cve.py +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/tests/test_provider_extra.py +0 -0
- {regcode-0.4.1 → regcode-0.5.0}/tests/test_review_notes.py +0 -0
|
@@ -44,7 +44,6 @@ class ChatMessage:
|
|
|
44
44
|
# ChatApp — main Textual application
|
|
45
45
|
# ---------------------------------------------------------------------------
|
|
46
46
|
|
|
47
|
-
|
|
48
47
|
class ChatApp(App):
|
|
49
48
|
"""Clean modern TUI for RegCode agent."""
|
|
50
49
|
|
|
@@ -150,6 +149,7 @@ class ChatApp(App):
|
|
|
150
149
|
self._cumulative_cost: float = 0.0
|
|
151
150
|
self._total_tokens: int = 0
|
|
152
151
|
self._context_window: int = 128000
|
|
152
|
+
self._pending_tool_line: str = ""
|
|
153
153
|
|
|
154
154
|
# ── Compose ───────────────────────────────────────────────────
|
|
155
155
|
|
|
@@ -338,6 +338,27 @@ class ChatApp(App):
|
|
|
338
338
|
|
|
339
339
|
def _run_agent_sync(self, message: str) -> None:
|
|
340
340
|
"""Run agent.chat synchronously in a background thread."""
|
|
341
|
+
# Suppress noise from litellm, mlflow, crawl4ai, and other
|
|
342
|
+
# library loggers during agent execution — they spew logging
|
|
343
|
+
# lines to stdout/stderr which corrupt the TUI display.
|
|
344
|
+
_noisy_loggers = (
|
|
345
|
+
"LiteLLM",
|
|
346
|
+
"mlflow",
|
|
347
|
+
"mlflow.tracking",
|
|
348
|
+
"crawl4ai",
|
|
349
|
+
"urllib3",
|
|
350
|
+
"httpx",
|
|
351
|
+
"httpcore",
|
|
352
|
+
"openai",
|
|
353
|
+
"http11",
|
|
354
|
+
"hpack",
|
|
355
|
+
)
|
|
356
|
+
_old_levels: dict[str, int] = {}
|
|
357
|
+
for name in _noisy_loggers:
|
|
358
|
+
logger = logging.getLogger(name)
|
|
359
|
+
_old_levels[name] = logger.level
|
|
360
|
+
logger.setLevel(logging.WARNING)
|
|
361
|
+
|
|
341
362
|
try:
|
|
342
363
|
with self._lock:
|
|
343
364
|
if self._agent is None:
|
|
@@ -364,6 +385,9 @@ class ChatApp(App):
|
|
|
364
385
|
)
|
|
365
386
|
finally:
|
|
366
387
|
self.call_from_thread(self._finish_message)
|
|
388
|
+
# Restore logger levels in the same thread (background thread, not main)
|
|
389
|
+
for name, level in _old_levels.items():
|
|
390
|
+
logging.getLogger(name).setLevel(level)
|
|
367
391
|
|
|
368
392
|
# ── Agent callbacks (any thread → main thread) ────────────────
|
|
369
393
|
|
|
@@ -383,6 +407,9 @@ class ChatApp(App):
|
|
|
383
407
|
self._flush_stream_for_status()
|
|
384
408
|
|
|
385
409
|
if status == AgentStatus.TOOL_CALL and tool_call_info is not None:
|
|
410
|
+
# Buffer the tool call text — RichLog always starts a new line
|
|
411
|
+
# per write(), so we can't append the ✓ on the same line until
|
|
412
|
+
# TOOL_RESULT arrives.
|
|
386
413
|
tool_name = rich_escape(str(tool_call_info.tool_name))
|
|
387
414
|
parts = [f"[dim] [dim]⚙[/dim] {tool_name}[/dim]"]
|
|
388
415
|
if tool_call_info.tool_args:
|
|
@@ -391,11 +418,13 @@ class ChatApp(App):
|
|
|
391
418
|
parts.append(
|
|
392
419
|
f" [dim]{rich_escape(str(k))}=[/dim]{val}"
|
|
393
420
|
)
|
|
394
|
-
|
|
421
|
+
self._pending_tool_line = " ".join(parts)
|
|
395
422
|
|
|
396
423
|
elif status == AgentStatus.TOOL_RESULT \
|
|
397
424
|
and tool_call_info is not None:
|
|
398
|
-
|
|
425
|
+
# Emit the complete tool line with ✓ appended
|
|
426
|
+
log.write(self._pending_tool_line + " [dim]✓[/dim]\n")
|
|
427
|
+
self._pending_tool_line = ""
|
|
399
428
|
|
|
400
429
|
elif status == AgentStatus.COMPACTION_START:
|
|
401
430
|
log.write(
|
regcode-0.4.1/repair_tui.md
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
# TUI Streaming Repair — step by step
|
|
2
|
-
|
|
3
|
-
File to edit: `regcode/tui.py` — class `ChatApp`.
|
|
4
|
-
|
|
5
|
-
## Goal
|
|
6
|
-
Stop printing every streamed text chunk on its own line in the chat history.
|
|
7
|
-
Instead, buffer all chunks during streaming and render one final markdown block when the agent finishes.
|
|
8
|
-
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
## Step 1 — add a state flag
|
|
12
|
-
|
|
13
|
-
In `__init__`, after the other streaming-related lines, add:
|
|
14
|
-
|
|
15
|
-
```python
|
|
16
|
-
self._streaming = False
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
Also reset it in every place that already resets streaming state. For example, in the reset method that sets `_streaming_started = False`, also set:
|
|
20
|
-
|
|
21
|
-
```python
|
|
22
|
-
self._streaming = False
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
And in the final cleanup block of `_finish_message`, also set:
|
|
26
|
-
|
|
27
|
-
```python
|
|
28
|
-
self._streaming = False
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
---
|
|
32
|
-
|
|
33
|
-
## Step 2 — stop high-frequency live writes
|
|
34
|
-
|
|
35
|
-
Replace `on_text_chunk`:
|
|
36
|
-
|
|
37
|
-
- Keep appending to `self._current_response`.
|
|
38
|
-
- Keep updating `self._streaming_started = True`.
|
|
39
|
-
- Remove the call to `_write_streaming_chunk`.
|
|
40
|
-
- Add logic so the first chunk starts a single visual “AGENT:” label.
|
|
41
|
-
|
|
42
|
-
Example:
|
|
43
|
-
|
|
44
|
-
```python
|
|
45
|
-
def on_text_chunk(self, chunk: str) -> None:
|
|
46
|
-
self._current_response.append(chunk)
|
|
47
|
-
self._streaming_started = True
|
|
48
|
-
if not self._streaming:
|
|
49
|
-
self._streaming = True
|
|
50
|
-
self.call_from_thread(self._start_streaming_label)
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
Add this new method:
|
|
54
|
-
|
|
55
|
-
```python
|
|
56
|
-
def _start_streaming_label(self) -> None:
|
|
57
|
-
log = self.query_one("#history", RichLog)
|
|
58
|
-
log.write("[bold blue]AGENT:[/]\n")
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
Remove the old `_write_streaming_chunk` method entirely (or leave it unused if your agent does not delete code).
|
|
62
|
-
|
|
63
|
-
---
|
|
64
|
-
|
|
65
|
-
## Step 3 — fix the final render
|
|
66
|
-
|
|
67
|
-
In `_finish_message`:
|
|
68
|
-
|
|
69
|
-
- Save the flag at the start: `streaming = self._streaming`
|
|
70
|
-
- Then set `self._streaming = False`
|
|
71
|
-
- Only write the `AGENT:` label if we never started streaming
|
|
72
|
-
- Keep the existing markdown rendering logic
|
|
73
|
-
|
|
74
|
-
Example:
|
|
75
|
-
|
|
76
|
-
```python
|
|
77
|
-
def _finish_message(self) -> None:
|
|
78
|
-
self._agent_running = False
|
|
79
|
-
streaming = self._streaming
|
|
80
|
-
self._streaming = False
|
|
81
|
-
try:
|
|
82
|
-
if self._current_response:
|
|
83
|
-
response = "".join(self._current_response).lstrip("\n")
|
|
84
|
-
response = re.sub(r"\n{3,}", "\n\n", response)
|
|
85
|
-
log = self.query_one("#history", RichLog)
|
|
86
|
-
if not streaming:
|
|
87
|
-
log.write("[bold blue]AGENT:[/]\n")
|
|
88
|
-
log.write(self._render_markdown_to_string(response))
|
|
89
|
-
log.write("[dim]────────────────────────────────────────────────────[/]\n")
|
|
90
|
-
except Exception:
|
|
91
|
-
self._write_error_line("Failed to render agent response.")
|
|
92
|
-
finally:
|
|
93
|
-
# reset buffers here
|
|
94
|
-
...
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
---
|
|
98
|
-
|
|
99
|
-
## Step 4 — verify the reset paths
|
|
100
|
-
|
|
101
|
-
Any place that currently resets `_streaming_started = False` must also reset `self._streaming = False`.
|
|
102
|
-
|
|
103
|
-
If a reset method exists, update it. If several reset points exist, patch all of them.
|
|
104
|
-
|
|
105
|
-
---
|
|
106
|
-
|
|
107
|
-
## Rules for the agent
|
|
108
|
-
- Do only the edits above.
|
|
109
|
-
- Do not change CSS or widgets.
|
|
110
|
-
- Do not change markdown rendering in `_render_markdown_to_string`.
|
|
111
|
-
- Do not add extra logs or prints.
|
|
112
|
-
- After editing, the expected behavior is:
|
|
113
|
-
- One `AGENT:` label per message
|
|
114
|
-
- Final markdown appears once
|
|
115
|
-
- Streaming chunks are no longer written one per line
|
|
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
|