diff --git a/devgen/modules/commit_generator.py b/devgen/modules/commit_generator.py index 057c190..031c478 100644 --- a/devgen/modules/commit_generator.py +++ b/devgen/modules/commit_generator.py @@ -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 diff --git a/devgen/modules/diff_builder.py b/devgen/modules/diff_builder.py index dd627b9..6703b02 100644 --- a/devgen/modules/diff_builder.py +++ b/devgen/modules/diff_builder.py @@ -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: diff --git a/devgen/modules/git_ops.py b/devgen/modules/git_ops.py index c0e9c52..c231157 100644 --- a/devgen/modules/git_ops.py +++ b/devgen/modules/git_ops.py @@ -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