Skip to content

Commit c8cfc87

Browse files
committed
refactor: consolidate package layout and improve code quality
- Consolidate package layout by moving __init__.py - Refactor GroqProvider to use _convert_to_provider_messages - Improve error handling in GitHubClient - Fix potential TypeError in CodeFlowSettings - Remove BOM from github_client.py
1 parent 4d33125 commit c8cfc87

9 files changed

Lines changed: 2244 additions & 56 deletions

File tree

codeflow_engine/__init__.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
"""Development shim for the canonical monorepo package.
2+
3+
The only source-of-truth package lives at ``engine/codeflow_engine``.
4+
This shim makes ``import codeflow_engine`` work from the repository root
5+
without recreating or maintaining a duplicate source tree.
6+
"""
7+
8+
from __future__ import annotations
9+
10+
from pathlib import Path
11+
12+
_CANONICAL_PACKAGE_DIR = (
13+
Path(__file__).resolve().parent.parent / "engine" / "codeflow_engine"
14+
)
15+
_CANONICAL_INIT = _CANONICAL_PACKAGE_DIR / "__init__.py"
16+
17+
if not _CANONICAL_INIT.exists():
18+
raise ImportError(
19+
"The canonical package was not found at engine/codeflow_engine. "
20+
"Check the monorepo layout."
21+
)
22+
23+
__path__ = [str(_CANONICAL_PACKAGE_DIR)]
24+
__file__ = str(_CANONICAL_INIT)
25+
26+
if __spec__ is not None:
27+
__spec__.submodule_search_locations = __path__
28+
29+
exec(
30+
compile(_CANONICAL_INIT.read_text(encoding="utf-8"), __file__, "exec"),
31+
globals(),
32+
globals(),
33+
)

engine/codeflow_engine/__init__.py

Lines changed: 80 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,43 @@
1-
"""
2-
CodeFlow Engine - Automated Code Review and Quality Management System
3-
4-
This package provides AI-powered code analysis, automated fixes, and quality assurance workflows.
1+
"""CodeFlow Engine public package API.
52
6-
Main Components:
7-
- CodeFlowEngine: Main orchestrator for all automation activities
8-
- ActionRegistry: Registry for managing action plugins
9-
- WorkflowEngine: Workflow execution engine
10-
- LLMProviderManager: Multi-provider LLM abstraction
11-
- MetricsCollector: Quality metrics collection
3+
The canonical package lives under ``engine/codeflow_engine`` in the monorepo.
4+
Keep this module lightweight so submodule imports such as
5+
``codeflow_engine.actions.analysis.ai_comment_analyzer`` do not eagerly import
6+
optional runtime dependencies during package initialization.
127
"""
138

9+
from __future__ import annotations
10+
11+
import importlib
1412
import logging
1513
import os
16-
from typing import Any, cast
17-
18-
from codeflow_engine.actions.registry import ActionRegistry
19-
from codeflow_engine.ai.core.base import LLMProvider
20-
from codeflow_engine.ai.core.providers.manager import LLMProviderManager
21-
from codeflow_engine.config import CodeFlowConfig
22-
from codeflow_engine.engine import CodeFlowEngine
23-
from codeflow_engine.exceptions import (
24-
ActionError,
25-
AuthenticationError,
26-
CodeFlowException,
27-
CodeFlowPermissionError,
28-
ConfigurationError,
29-
IntegrationError,
30-
LLMProviderError,
31-
RateLimitError,
32-
ValidationError,
33-
WorkflowError,
34-
)
35-
from codeflow_engine.integrations.base import Integration
36-
from codeflow_engine.quality.metrics_collector import MetricsCollector
37-
38-
# Security - guarded import
39-
EnterpriseAuthorizationManager: type[Any] | None = None
40-
try:
14+
from typing import TYPE_CHECKING, Any, cast
15+
16+
if TYPE_CHECKING:
17+
from codeflow_engine.actions.registry import ActionRegistry
18+
from codeflow_engine.ai.core.base import LLMProvider
19+
from codeflow_engine.ai.core.providers.manager import LLMProviderManager
20+
from codeflow_engine.config import CodeFlowConfig
21+
from codeflow_engine.engine import CodeFlowEngine
22+
from codeflow_engine.exceptions import (
23+
ActionError,
24+
AuthenticationError,
25+
CodeFlowException,
26+
CodeFlowPermissionError,
27+
ConfigurationError,
28+
IntegrationError,
29+
LLMProviderError,
30+
RateLimitError,
31+
ValidationError,
32+
WorkflowError,
33+
)
34+
from codeflow_engine.integrations.base import Integration
35+
from codeflow_engine.quality.metrics_collector import MetricsCollector
4136
from codeflow_engine.security.authorization.enterprise_manager import (
4237
EnterpriseAuthorizationManager,
4338
)
44-
except (ImportError, OSError):
45-
pass
46-
47-
from codeflow_engine.workflows.base import Workflow
48-
from codeflow_engine.workflows.engine import WorkflowEngine
39+
from codeflow_engine.workflows.base import Workflow
40+
from codeflow_engine.workflows.engine import WorkflowEngine
4941

5042
# Import structlog with error handling
5143
STRUCTLOG_AVAILABLE: bool
@@ -60,6 +52,29 @@
6052

6153
__version__ = "0.2.0-alpha.1"
6254

55+
_LAZY_EXPORTS = {
56+
"CodeFlowEngine": "codeflow_engine.engine:CodeFlowEngine",
57+
"CodeFlowConfig": "codeflow_engine.config:CodeFlowConfig",
58+
"ActionRegistry": "codeflow_engine.actions.registry:ActionRegistry",
59+
"LLMProvider": "codeflow_engine.ai.core.base:LLMProvider",
60+
"LLMProviderManager": "codeflow_engine.ai.core.providers.manager:LLMProviderManager",
61+
"Integration": "codeflow_engine.integrations.base:Integration",
62+
"Workflow": "codeflow_engine.workflows.base:Workflow",
63+
"WorkflowEngine": "codeflow_engine.workflows.engine:WorkflowEngine",
64+
"MetricsCollector": "codeflow_engine.quality.metrics_collector:MetricsCollector",
65+
"EnterpriseAuthorizationManager": "codeflow_engine.security.authorization.enterprise_manager:EnterpriseAuthorizationManager",
66+
"ActionError": "codeflow_engine.exceptions:ActionError",
67+
"AuthenticationError": "codeflow_engine.exceptions:AuthenticationError",
68+
"CodeFlowException": "codeflow_engine.exceptions:CodeFlowException",
69+
"CodeFlowPermissionError": "codeflow_engine.exceptions:CodeFlowPermissionError",
70+
"ConfigurationError": "codeflow_engine.exceptions:ConfigurationError",
71+
"IntegrationError": "codeflow_engine.exceptions:IntegrationError",
72+
"LLMProviderError": "codeflow_engine.exceptions:LLMProviderError",
73+
"RateLimitError": "codeflow_engine.exceptions:RateLimitError",
74+
"ValidationError": "codeflow_engine.exceptions:ValidationError",
75+
"WorkflowError": "codeflow_engine.exceptions:WorkflowError",
76+
}
77+
6378
# Public API exports
6479
__all__ = [
6580
# Core engine
@@ -127,6 +142,31 @@ def configure_logging(level: str = "INFO", *, format_json: bool = False) -> None
127142
)
128143

129144

145+
def __getattr__(name: str) -> Any:
146+
"""Lazily load public exports to avoid importing optional dependencies."""
147+
target = _LAZY_EXPORTS.get(name)
148+
if target is None:
149+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
150+
151+
module_name, attribute_name = target.split(":", 1)
152+
try:
153+
module = importlib.import_module(module_name)
154+
value = getattr(module, attribute_name)
155+
except (ImportError, OSError):
156+
if name == "EnterpriseAuthorizationManager":
157+
value = None
158+
else:
159+
raise
160+
161+
globals()[name] = value
162+
return value
163+
164+
165+
def __dir__() -> list[str]:
166+
"""Return module attributes including lazy exports for interactive tooling."""
167+
return sorted(set(globals()) | set(__all__))
168+
169+
130170
# Configure logging on import
131171
log_level = os.getenv("CODEFLOW_LOG_LEVEL", "INFO")
132172
json_logging = os.getenv("CODEFLOW_JSON_LOGGING", "false").lower() == "true"

engine/codeflow_engine/actions/llm/providers/groq.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,11 @@ def complete(self, request: dict[str, Any]) -> LLMResponse:
4141
max_tokens = request.get("max_tokens", 1024)
4242
temperature = request.get("temperature", 0.7)
4343

44-
filtered_messages = [
45-
{"role": m.get("role", "user"), "content": m.get("content", "")}
46-
for m in messages
47-
if m.get("content")
48-
]
44+
groq_messages = self._convert_to_provider_messages(messages, "groq")
4945

50-
response = self.client.chat.completions.create( # type: ignore[arg-type]
46+
response = self.client.chat.completions.create(
5147
model=str(model),
52-
messages=filtered_messages,
48+
messages=groq_messages,
5349
max_tokens=max_tokens,
5450
temperature=temperature,
5551
)

engine/codeflow_engine/clients/github_client.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""GitHub API client for CodeFlow with retry logic and rate limiting."""
1+
"""GitHub API client for CodeFlow with retry logic and rate limiting."""
22

33
import asyncio
44
from dataclasses import dataclass
@@ -222,21 +222,23 @@ async def _request(
222222
return {}
223223

224224
except ClientResponseError as e:
225-
if e.status == 403 and "rate limit" in (e.message or "").lower():
225+
# Handle status code safely for type checking
226+
status = e.status or 0
227+
if status == 403 and "rate limit" in (e.message or "").lower():
226228
last_error = RateLimitExceeded(
227229
"GitHub API rate limit exceeded",
228-
status_code=e.status,
230+
status_code=status,
229231
response=e.request_info,
230232
)
231233
else:
232234
last_error = GitHubError(
233235
f"GitHub API request failed: {e}",
234-
status_code=e.status,
236+
status_code=status,
235237
response=e.request_info,
236238
)
237239

238240
# Don't retry on client errors (4xx) except for rate limits
239-
if 400 <= (e.status or 0) < 500 and e.status != 429:
241+
if 400 <= status < 500 and status != 429:
240242
break
241243

242244
except (TimeoutError, ClientError) as e:

engine/codeflow_engine/config/settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ class CodeFlowSettings(BaseSettings):
335335
custom: dict[str, Any] = Field(default_factory=dict)
336336

337337
# Pydantic V2 configuration using SettingsConfigDict
338-
if _PYDANTIC_V2 and SettingsConfigDict:
338+
if _PYDANTIC_V2 and SettingsConfigDict is not None:
339339
model_config = SettingsConfigDict(
340340
env_file=".env",
341341
env_file_encoding="utf-8",

engine/templates/discovery/template_validators.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,10 @@ def check_security_documentation(
479479
category="security",
480480
message="Missing security considerations",
481481
location=str(file_path),
482-
suggestion=("Add security considerations to help users understand "
482+
suggestion=(
483+
"Add security considerations to help users understand "
484+
"security implications and recommended safeguards"
485+
),
483486
rule_id=rule.rule_id,
484487
)
485488
)

mypy.ini

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ explicit_package_bases = True
1010
mypy_path = engine
1111

1212
# Keep recursive discovery away from non-source trees and template folders that
13-
# intentionally use hyphenated names such as `example-hybrid`.
14-
exclude = ^(\.git|\.venv|\.pytest_cache|\.mypy_cache|dist|docs|desktop|website|vscode-extension|orchestration|tools|scripts|engine[/\\]templates|engine[/\\]tests|engine[/\\]alembic)([/\\]|$)
13+
# intentionally use hyphenated names such as `example-hybrid`. The repo-root
14+
# `codeflow_engine/` directory is a development shim only; the canonical source
15+
# package that should be type-checked lives under `engine/codeflow_engine`.
16+
exclude = ^(\.git|\.venv|\.pytest_cache|\.mypy_cache|dist|docs|desktop|website|vscode-extension|orchestration|tools|scripts|codeflow_engine|engine[/\\]templates|engine[/\\]tests|engine[/\\]alembic)([/\\]|$)
1517

1618
# Default to the canonical engine package when mypy is launched from the repo
1719
# root by editor integrations.

0 commit comments

Comments
 (0)