regcode 0.6.1__tar.gz → 0.6.2__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 (43) hide show
  1. {regcode-0.6.1 → regcode-0.6.2}/.gitlab-ci.yml +12 -0
  2. {regcode-0.6.1 → regcode-0.6.2}/GOALS.md +33 -3
  3. {regcode-0.6.1 → regcode-0.6.2}/PKG-INFO +2 -2
  4. {regcode-0.6.1 → regcode-0.6.2}/pyproject.toml +2 -2
  5. {regcode-0.6.1 → regcode-0.6.2}/regcode/__init__.py +1 -1
  6. {regcode-0.6.1 → regcode-0.6.2}/regcode/main.py +52 -2
  7. {regcode-0.6.1 → regcode-0.6.2}/regcode/tui.py +273 -284
  8. {regcode-0.6.1 → regcode-0.6.2}/tests/test_osv_cve.py +98 -55
  9. {regcode-0.6.1 → regcode-0.6.2}/uv.lock +5 -5
  10. {regcode-0.6.1 → regcode-0.6.2}/.gitignore +0 -0
  11. {regcode-0.6.1 → regcode-0.6.2}/.python-version +0 -0
  12. {regcode-0.6.1 → regcode-0.6.2}/.qwen/settings.json +0 -0
  13. {regcode-0.6.1 → regcode-0.6.2}/AGENTS.md +0 -0
  14. {regcode-0.6.1 → regcode-0.6.2}/README.md +0 -0
  15. {regcode-0.6.1 → regcode-0.6.2}/config.yaml.template +0 -0
  16. {regcode-0.6.1 → regcode-0.6.2}/main.py +0 -0
  17. {regcode-0.6.1 → regcode-0.6.2}/regcode/cli.py +0 -0
  18. {regcode-0.6.1 → regcode-0.6.2}/regcode/config.py +0 -0
  19. {regcode-0.6.1 → regcode-0.6.2}/regcode/conversation_manager.py +0 -0
  20. {regcode-0.6.1 → regcode-0.6.2}/regcode/dependencies.py +0 -0
  21. {regcode-0.6.1 → regcode-0.6.2}/regcode/monty_sandbox.py +0 -0
  22. {regcode-0.6.1 → regcode-0.6.2}/regcode/permissions.py +0 -0
  23. {regcode-0.6.1 → regcode-0.6.2}/regcode/sandbox.py +0 -0
  24. {regcode-0.6.1 → regcode-0.6.2}/regcode/tools/__init__.py +0 -0
  25. {regcode-0.6.1 → regcode-0.6.2}/regcode/tools/base.py +0 -0
  26. {regcode-0.6.1 → regcode-0.6.2}/regcode/tools/builtins.py +0 -0
  27. {regcode-0.6.1 → regcode-0.6.2}/regcode/tools/registry.py +0 -0
  28. {regcode-0.6.1 → regcode-0.6.2}/regcode/tools/review_notes.py +0 -0
  29. {regcode-0.6.1 → regcode-0.6.2}/regcode/tools/web_crawl.py +0 -0
  30. {regcode-0.6.1 → regcode-0.6.2}/regcode/tools/web_search.py +0 -0
  31. {regcode-0.6.1 → regcode-0.6.2}/regcode/tracing.py +0 -0
  32. {regcode-0.6.1 → regcode-0.6.2}/tests/__init__.py +0 -0
  33. {regcode-0.6.1 → regcode-0.6.2}/tests/conftest.py +0 -0
  34. {regcode-0.6.1 → regcode-0.6.2}/tests/test_api.py +0 -0
  35. {regcode-0.6.1 → regcode-0.6.2}/tests/test_cli.py +0 -0
  36. {regcode-0.6.1 → regcode-0.6.2}/tests/test_config.py +0 -0
  37. {regcode-0.6.1 → regcode-0.6.2}/tests/test_context_manager.py +0 -0
  38. {regcode-0.6.1 → regcode-0.6.2}/tests/test_dependencies.py +0 -0
  39. {regcode-0.6.1 → regcode-0.6.2}/tests/test_main.py +0 -0
  40. {regcode-0.6.1 → regcode-0.6.2}/tests/test_monty_sandbox.py +0 -0
  41. {regcode-0.6.1 → regcode-0.6.2}/tests/test_provider_extra.py +0 -0
  42. {regcode-0.6.1 → regcode-0.6.2}/tests/test_review_notes.py +0 -0
  43. {regcode-0.6.1 → regcode-0.6.2}/tests/test_web_search.py +0 -0
@@ -41,6 +41,14 @@ build:
41
41
  paths:
42
42
  - dist/
43
43
  expire_in: 1 week
44
+ rules:
45
+ - if: $CI_COMMIT_BRANCH == "main"
46
+ changes:
47
+ paths:
48
+ - "regcode/**/*"
49
+ - "pyproject.toml"
50
+ when: on_success
51
+ - when: never
44
52
 
45
53
  publish:
46
54
  stage: publish
@@ -51,5 +59,9 @@ publish:
51
59
  - uv publish --token $UV_PUBLISH_TOKEN
52
60
  rules:
53
61
  - if: $CI_COMMIT_BRANCH == "main"
62
+ changes:
63
+ paths:
64
+ - "regcode/**/*"
65
+ - "pyproject.toml"
54
66
  when: on_success
55
67
  - when: never
@@ -497,7 +497,7 @@ All phases complete. 50/50 tests passing. Lint clean.
497
497
 
498
498
  1. ✅ **Remove model config params from AgentConfig** — `model`, `max_tokens`, `temperature` moved from `Config.agent` to `Config.provider`. `AgentConfig` now only holds `context_window`, `compaction_threshold`, and `enable_compaction`. All tests updated to use new format.
499
499
 
500
- 2. ✅ **TUI complete overhaul** — `tui.py` rewritten from scratch. New layout: (1) top status bar showing `[RegCode <version>] [model] [$cost] [tokens]`, (2) large chat history area with clearly separated user/agent/tool/system message blocks, (3) bottom bar with progress indicator and input field. Streaming works correctly: text chunks stream live, then on completion full Markdown is rendered. Tool calls are interleaved after streaming text (stream buffer flushed before status rendering). Context compaction shows status indicators. All 137 tests pass, lint clean.
500
+ 2. ✅ **TUI complete overhaul** — `tui.py` rewritten from scratch. New layout: (1) top status bar showing `[RegCode <version>] [model] [$cost] [tokens]`, (2) large chat history area with RichLog widget and clearly separated user/agent/tool/system message blocks, (3) bottom bar with progress indicator and input field. Streaming works correctly: text chunks stream live, then on completion full Markdown is rendered. Tool calls are interleaved after streaming text (stream buffer flushed before status rendering). Context compaction shows status indicators. RichLog renders Rich markup for colors; text selection is available via terminal scrollback. All 164 tests pass, lint clean.
501
501
 
502
502
  3. ✅ **WebSearchTool** — New `regcode/tools/web_search.py` tool connecting to SearXNG instances. Defaults to `https://search.regmi.dev`, supports custom SearXNG URL, language code, and result count (1-20). Uses only stdlib `urllib` — no extra dependencies. Registered in `create_default_tools()`. 15 tests pass.
503
503
 
@@ -505,5 +505,35 @@ All phases complete. 50/50 tests passing. Lint clean.
505
505
 
506
506
  - ✅ WebSearchTool: connects to SearXNG, defaults to https://search.regmi.dev, no extra deps needed
507
507
 
508
- ## To Dos:
509
- - If current Dir has `Agents.MD`, or `AGENTS.md` or `agents.md`, read it and provide it clearly marked as content of Agents.md to the model as extra context about the project.
508
+ ## Completed (2026-06-30 — TUI fixes)
509
+
510
+ 1. ✅ AGENTS.md injection — Agent now reads AGENTS.md/agents.md from CWD or allowed directory and injects it into system prompt (both `_build_system_prompt` and `_build_system_prompt_no_tools`). Appended after base system_prompt, before tool descriptions.
511
+
512
+ 2. ✅ TUI text selectability — Replaced RichLog with TextArea for the chat area. TextArea is the only Textual widget with real text selection and copy support (`action_copy`, `action_select_all`, `selected_text`). All write paths use `_append_text()` which converts Rich markup to ANSI escape codes via Rich's `Console.print()`, so text displays with colors AND remains selectable/copyable.
513
+
514
+ 3. ✅ Context window config — Hardcoded `_context_window: int = 128000` replaced with 0 default, with fallback chain in `_update_progress()`: `_context_window` → `self._agent.config.agent.context_window` → 128000.
515
+
516
+ 4. ✅ Hardcoded context window — Fixed `_update_progress()` to check `self._agent.config.agent.context_window` before falling back to 128000.
517
+
518
+ ## Completed (2026-06-30 — TUI overhaul)
519
+
520
+ - ✅ `tui.py` rewritten: 3-zone layout (status bar, chat area, input bar). Chat area uses TextArea (selectable/copyable) instead of RichLog. All Rich markup tags are stripped before insertion so text is readable. Agent runs in background thread, callbacks use `call_from_thread`.
521
+ - ✅ All 164 tests pass, lint clean.
522
+
523
+ ## Completed (2026-06-30 — TUI cleanup)
524
+
525
+ 1. ✅ **Added `textual>=2.0.0` dependency** — was imported but missing from `pyproject.toml`.
526
+ 2. ✅ **Replaced top-bar `TextArea` with `Label`** — the status bar only displays plain text; Label is lighter-weight and semantically correct. Same for progress bar widget.
527
+ 3. ✅ **Simplified streaming state machine** — reduced from 7 state variables (`_streaming`, `_streaming_started`, `_stream_pending`, `_stream_has_label`, `_stream_line_open`, `_stream_trim_leading`, `_current_response`) and 5 flushing methods down to 2 (`_streaming`, `_current_response`) and 1 flush method (`_flush_stream_for_status`). The old code buffered partial lines with complex state tracking; the new approach simply accumulates chunks in `_current_response` and flushes them as a single block when needed.
528
+ 4. ✅ **Optimized `_rich_to_ansi`** — replaced per-call `Console()` instantiation with a cached `_rich_console` instance created once in `__init__`, eliminating redundant object allocation on every text write.
529
+ 5. ✅ **All 164 tests pass**, lint clean.
530
+
531
+ ## Completed (2026-06-30 — TUI rewrite)
532
+
533
+ Complete rewrite of `tui.py` from scratch using Textual's `RichLog` widget instead of `TextArea`:
534
+
535
+ 1. ✅ **`RichLog` instead of `TextArea`** — RichLog natively renders Rich markup (`[bold]`, `[dim]`, etc.) so no fragile Rich→ANSI conversion is needed. Users see properly colored, styled text. RichLog also supports scrollback selection/copy via terminal features.
536
+ 2. ✅ **Clean Catppuccin Mocha dark theme** — uses the Catppuccin color palette (`#1e1e2e` background, `#cdd6f4` text, `#313244` surfaces, `#89b4fa` accents) for a modern, polished look.
537
+ 3. ✅ **Proper three-zone layout** — status bar (version | model | cost | tokens), scrollable chat history, bottom input bar with progress indicator. No raw markup tags visible.
538
+ 4. ✅ **Same backward-compatible API** — `ChatUI` facade, `ChatApp` class, `_ColorFormatter`, all callback methods (`handle_status`, `handle_result`, `handle_cost`, `print_text_chunk`, etc.) preserved exactly as before for CLI integration.
539
+ 5. ✅ **All 164 tests pass**, lint clean.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: regcode
3
- Version: 0.6.1
3
+ Version: 0.6.2
4
4
  Summary: Minimalistic coding agent with Python API and CLI
5
5
  Requires-Python: >=3.10
6
6
  Requires-Dist: click>=8.0
@@ -12,7 +12,7 @@ Requires-Dist: pydantic-settings>=2.14.2
12
12
  Requires-Dist: pytest>=8.0
13
13
  Requires-Dist: pyyaml>=6.0
14
14
  Requires-Dist: ruff>=0.8
15
- Requires-Dist: textual>=8.2.7
15
+ Requires-Dist: textual>=2.0.0
16
16
  Provides-Extra: dev
17
17
  Description-Content-Type: text/markdown
18
18
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "regcode"
3
- version = "0.6.1"
3
+ version = "0.6.2"
4
4
  description = "Minimalistic coding agent with Python API and CLI"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -13,8 +13,8 @@ dependencies = [
13
13
  "pytest>=8.0",
14
14
  "ruff>=0.8",
15
15
  "pydantic-monty>=0.0.18",
16
- "textual>=8.2.7",
17
16
  "mlflow>=3.14.0",
17
+ "textual>=2.0.0",
18
18
  ]
19
19
 
20
20
  [project.scripts]
@@ -2,4 +2,4 @@ from regcode.config import Config
2
2
  from regcode.main import Agent, AgentStatus, ToolCall
3
3
 
4
4
  __all__ = ["Agent", "Config", "AgentStatus", "ToolCall"]
5
- __version__ = "0.6.1"
5
+ __version__ = "0.6.2"
@@ -4,6 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  import json
6
6
  import warnings
7
+ from datetime import datetime, timezone
7
8
  from enum import Enum
8
9
  from pathlib import Path
9
10
  from typing import Any, Callable
@@ -444,11 +445,48 @@ class Agent:
444
445
  self._history = [m for m in messages if m.get("role") != "system"]
445
446
  return final_text or response_message.get("content", "") or ""
446
447
 
448
+ @staticmethod
449
+ def _read_agents_md(directory: str | None = None) -> str:
450
+ """Read AGENTS.md from the given directory if it exists.
451
+
452
+ Returns the file contents with a header, or an empty string if
453
+ the file is not found.
454
+ """
455
+ search_dirs: list[Path] = []
456
+ if directory:
457
+ search_dirs.append(Path(directory))
458
+ search_dirs.append(Path.cwd())
459
+ for candidate in search_dirs:
460
+ for name in ("AGENTS.md", "agents.md", "Agents.md"):
461
+ p = candidate / name
462
+ if p.exists():
463
+ try:
464
+ return p.read_text(encoding="utf-8")
465
+ except OSError:
466
+ continue
467
+ return ""
468
+
447
469
  def _build_system_prompt(self) -> str:
448
470
  """Build the full system prompt including tool definitions."""
471
+ now = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S UTC")
472
+ date_section = f"\n\nCurrent time: {now}\n"
473
+ agents_md = self._read_agents_md(self._allowed_dir)
474
+ agents_md_section = ""
475
+ if agents_md:
476
+ agents_md_section = (
477
+ f"\n\n{'=' * 60}\n"
478
+ "AGENT INSTRUCTIONS (injected from AGENTS.md):\n"
479
+ f"{'=' * 60}\n\n{agents_md}"
480
+ )
449
481
  tool_descriptions = self._format_tool_descriptions()
450
482
  notes_section = self._format_review_notes()
451
- return f"{self.system_prompt}{tool_descriptions}{notes_section}"
483
+ return (
484
+ f"{self.system_prompt}"
485
+ f"{date_section}"
486
+ f"{agents_md_section}"
487
+ f"{tool_descriptions}"
488
+ f"{notes_section}"
489
+ )
452
490
 
453
491
  def _build_system_prompt_no_tools(self) -> str:
454
492
  """Build the system prompt WITHOUT tool definitions.
@@ -460,7 +498,19 @@ class Agent:
460
498
  stripped, because the accumulated review findings remain relevant
461
499
  context for the LLM's final response.
462
500
  """
463
- return f"{self.system_prompt}{self._format_review_notes()}"
501
+ now = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S UTC")
502
+ date_section = f"\n\nCurrent time: {now}\n"
503
+ agents_md = self._read_agents_md(self._allowed_dir)
504
+ agents_md_section = ""
505
+ if agents_md:
506
+ agents_md_section = (
507
+ f"\n\n{'=' * 60}\n"
508
+ "AGENT INSTRUCTIONS (injected from AGENTS.md):\n"
509
+ f"{'=' * 60}\n\n{agents_md}"
510
+ )
511
+ parts = [self.system_prompt, date_section, agents_md_section]
512
+ parts.append(self._format_review_notes())
513
+ return "".join(parts)
464
514
 
465
515
  def _stream(
466
516
  self,