feat(devgen/modules): streamline provider guard and enhance ManifestInspector flexibility

Add token‑limit error handling and switch git diff to null‑delimited output for reliable file detection.
This commit is contained in:
sankalp committed 2026-07-03 18:07:26 +05:45
1 parent 11a9db7986
commit f7001d4243
3 files changed
+30 -20

No files matched your search

+15 -7
View File
@@ -33,6 +33,8 @@ from devgen.utils import (
extract_commit_messages,
get_commit_dry_run_path,
is_file_recent,
is_token_limit_error,
format_token_limit_error,
load_template,
render_template,
sanitize_ai_commit_message,
@@ -241,9 +243,10 @@ class CommitEngine:
if not self._process_group(group, group_files, cache_map):
failed.append(group)
if len(groups) > 1 and i < len(groups) - 1:
import time
if self.provider != "ollama":
import time
time.sleep(15) # Conservative 4 RPM guard for free-tier
time.sleep(15) # Conservative 4 RPM guard for free-tier
return failed
def _process_group(
@@ -265,7 +268,7 @@ class CommitEngine:
return self._apply_message(group, cache[group], files)
try:
manifest_context = ManifestInspector.summary()
manifest_context = ManifestInspector.summary(cwd=self.git.cwd)
if manifest_context:
self.logger.info("Including manifest context in prompt")
with self.console.status(
@@ -279,10 +282,15 @@ class CommitEngine:
)
message = sanitize_ai_commit_message(raw)
except Exception as e:
self.logger.error(
f"Failed to generate message for group {group!r}: {e}",
exc_info=True,
)
if is_token_limit_error(e):
msg = format_token_limit_error(self.provider, e, group=group)
self.console.print(f"[bold red]{msg}[/bold red]")
self.logger.error(msg)
else:
self.logger.error(
f"Failed to generate message for group {group!r}: {e}",
exc_info=True,
)
self.git.reset(files)
return False
+11 -10
View File
@@ -143,13 +143,14 @@ class ManifestInspector:
"""
@staticmethod
def summary() -> str:
def summary(cwd: Optional[Path] = None) -> str:
cwd = cwd or get_git_root() or Path(".")
lines = [
s
for s in (
ManifestInspector._pyproject(),
ManifestInspector._package_json(),
ManifestInspector._requirements(),
ManifestInspector._pyproject(cwd),
ManifestInspector._package_json(cwd),
ManifestInspector._requirements(cwd),
)
if s
]
@@ -164,8 +165,8 @@ class ManifestInspector:
return re.split(r"[><=!~\[]", spec, 1)[0].strip()
@staticmethod
def _pyproject() -> Optional[str]:
path = Path("pyproject.toml")
def _pyproject(cwd: Path) -> Optional[str]:
path = cwd / "pyproject.toml"
if not path.exists():
return None
try:
@@ -186,8 +187,8 @@ class ManifestInspector:
return f"[pyproject.toml] {' '.join(parts)}" if parts else None
@staticmethod
def _package_json() -> Optional[str]:
path = Path("package.json")
def _package_json(cwd: Path) -> Optional[str]:
path = cwd / "package.json"
if not path.exists():
return None
try:
@@ -203,8 +204,8 @@ class ManifestInspector:
return f"[package.json] {' '.join(parts)}" if parts else None
@staticmethod
def _requirements() -> Optional[str]:
path = Path("requirements.txt")
def _requirements(cwd: Path) -> Optional[str]:
path = cwd / "requirements.txt"
if not path.exists():
return None
try:
+4 -3
View File
@@ -91,15 +91,16 @@ class GitOperator:
[
"git",
"ls-files",
"-z",
"--deleted",
"--modified",
"--others",
"--exclude-standard",
]
)
files = {f.strip() for f in out.split("\n") if f.strip()}
staged_out = self._run(["git", "diff", "--name-only", "--cached"])
files.update(f.strip() for f in staged_out.split("\n") if f.strip())
files = {f for f in out.split("\0") if f}
staged_out = self._run(["git", "diff", "-z", "--name-only", "--cached"])
files.update(f for f in staged_out.split("\0") if f)
return sorted(files)
# ------------------------------------------------------------------ actions