Skip to content

Commit 2e97e0a

Browse files
committed
fix: stabilize typing compatibility and workflow error handling
1 parent ff90825 commit 2e97e0a

63 files changed

Lines changed: 1324 additions & 694 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

engine/codeflow_engine/actions/ai_actions/autogen/__init__.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,9 @@
44
from codeflow_engine.actions.autogen.models import AutoGenInputs, AutoGenOutputs
55
from codeflow_engine.actions.autogen.system import AutoGenAgentSystem
66

7-
__all__ = ["AutoGenAgentFactory", "AutoGenAgentSystem", "AutoGenInputs", "AutoGenOutputs"]
7+
__all__ = [
8+
"AutoGenAgentFactory",
9+
"AutoGenAgentSystem",
10+
"AutoGenInputs",
11+
"AutoGenOutputs",
12+
]

engine/codeflow_engine/actions/ai_actions/llm/__init__.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
"""CODEFLOW LLM Package - compatibility wrapper under grouped actions."""
22

3-
from codeflow_engine.actions.ai_actions.llm.manager import ActionLLMProviderManager, LLMProviderManager
3+
from codeflow_engine.actions.ai_actions.llm.manager import (
4+
ActionLLMProviderManager,
5+
LLMProviderManager,
6+
)
47
from codeflow_engine.actions.ai_actions.llm.providers import (
58
AnthropicProvider,
69
AzureOpenAIProvider,
@@ -18,7 +21,11 @@
1821
Message,
1922
MessageRole,
2023
)
21-
from codeflow_engine.core.llm import BaseLLMProvider, LLMProviderRegistry, OpenAICompatibleProvider
24+
from codeflow_engine.core.llm import (
25+
BaseLLMProvider,
26+
LLMProviderRegistry,
27+
OpenAICompatibleProvider,
28+
)
2229

2330

2431
def get_llm_provider_manager() -> ActionLLMProviderManager:
@@ -54,4 +61,4 @@ def complete_chat(*args, **kwargs):
5461
"TogetherAIProvider",
5562
"complete_chat",
5663
"get_llm_provider_manager",
57-
]
64+
]
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
"""Compatibility wrapper for grouped LLM manager imports."""
22

3-
from codeflow_engine.actions.llm.manager import ActionLLMProviderManager, LLMProviderManager
3+
from codeflow_engine.actions.llm.manager import (
4+
ActionLLMProviderManager,
5+
LLMProviderManager,
6+
)
47

5-
__all__ = ["ActionLLMProviderManager", "LLMProviderManager"]
8+
__all__ = ["ActionLLMProviderManager", "LLMProviderManager"]

engine/codeflow_engine/actions/ai_actions/llm/providers/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@
2020
"OpenAIProvider",
2121
"PerplexityProvider",
2222
"TogetherAIProvider",
23-
]
23+
]
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
"""Compatibility wrapper for grouped LLM types imports."""
22

3-
from codeflow_engine.actions.llm.types import LLMConfig, LLMProviderType, LLMResponse, Message, MessageRole
3+
from codeflow_engine.actions.llm.types import (
4+
LLMConfig,
5+
LLMProviderType,
6+
LLMResponse,
7+
Message,
8+
MessageRole,
9+
)
410

5-
__all__ = ["LLMConfig", "LLMProviderType", "LLMResponse", "Message", "MessageRole"]
11+
__all__ = ["LLMConfig", "LLMProviderType", "LLMResponse", "Message", "MessageRole"]

engine/codeflow_engine/actions/ai_linting_fixer/__init__.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,31 @@
77
from .core import AILintingFixer
88
from .display import display_provider_status, print_feature_status
99
from .main import ai_linting_fixer
10-
from .models import AILintingFixerInputs, AILintingFixerOutputs, LintingIssue, create_empty_outputs
10+
from .models import (
11+
AILintingFixerInputs,
12+
AILintingFixerOutputs,
13+
LintingIssue,
14+
WorkflowContext,
15+
WorkflowResult,
16+
create_empty_outputs,
17+
)
1118
from .workflow_orchestrator import WorkflowOrchestrator, orchestrate_ai_linting_workflow
1219

1320

1421
__all__ = [
1522
# Core classes
1623
"AILintingFixer",
1724
"WorkflowOrchestrator",
18-
1925
# Main functions
2026
"ai_linting_fixer",
2127
"orchestrate_ai_linting_workflow",
22-
2328
# Models
2429
"AILintingFixerInputs",
2530
"AILintingFixerOutputs",
2631
"LintingIssue",
32+
"WorkflowContext",
33+
"WorkflowResult",
2734
"create_empty_outputs",
28-
2935
# Legacy compatibility
3036
"print_feature_status",
3137
"display_provider_status",

engine/codeflow_engine/actions/ai_linting_fixer/ai_linting_fixer.py

Lines changed: 77 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,23 @@
1313
from codeflow_engine.actions.ai_linting_fixer.ai_agent_manager import AIAgentManager
1414
from codeflow_engine.actions.ai_linting_fixer.code_analyzer import CodeAnalyzer
1515
from codeflow_engine.actions.ai_linting_fixer.detection import IssueDetector
16-
from codeflow_engine.actions.ai_linting_fixer.display import (AILintingFixerDisplay,
17-
DisplayConfig)
16+
from codeflow_engine.actions.ai_linting_fixer.display import (
17+
AILintingFixerDisplay,
18+
DisplayConfig,
19+
)
1820
from codeflow_engine.actions.ai_linting_fixer.error_handler import ErrorHandler
1921
from codeflow_engine.actions.ai_linting_fixer.file_manager import FileManager
20-
from codeflow_engine.actions.ai_linting_fixer.issue_converter import \
21-
convert_detection_issue_to_model_issue
22+
from codeflow_engine.actions.ai_linting_fixer.issue_converter import (
23+
convert_detection_issue_to_model_issue,
24+
)
2225
from codeflow_engine.actions.ai_linting_fixer.issue_fixer import IssueFixer
23-
from codeflow_engine.actions.ai_linting_fixer.models import (AILintingFixerInputs,
24-
AILintingFixerOutputs)
25-
from codeflow_engine.actions.ai_linting_fixer.performance_tracker import \
26-
PerformanceTracker
26+
from codeflow_engine.actions.ai_linting_fixer.models import (
27+
AILintingFixerInputs,
28+
AILintingFixerOutputs,
29+
)
30+
from codeflow_engine.actions.ai_linting_fixer.performance_tracker import (
31+
PerformanceTracker,
32+
)
2733
from codeflow_engine.actions.llm.manager import ActionLLMProviderManager
2834

2935
logger = logging.getLogger(__name__)
@@ -37,7 +43,9 @@ class AILintingFixer:
3743
def __init__(self, display_config: DisplayConfig | None = None):
3844
"""Initialize the AI Linting Fixer with all components."""
3945
# Set logging levels to ERROR by default to prevent clutter
40-
logging.getLogger("codeflow_engine.actions.ai_linting_fixer").setLevel(logging.ERROR)
46+
logging.getLogger("codeflow_engine.actions.ai_linting_fixer").setLevel(
47+
logging.ERROR
48+
)
4149
logging.getLogger("codeflow_engine.actions.llm").setLevel(logging.ERROR)
4250
logging.getLogger("httpx").setLevel(logging.ERROR)
4351

@@ -49,31 +57,36 @@ def __init__(self, display_config: DisplayConfig | None = None):
4957
self.error_handler = ErrorHandler()
5058

5159
# Get Azure OpenAI configuration
52-
azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT", "https://<your-azure-openai-endpoint>/")
60+
azure_endpoint = os.getenv(
61+
"AZURE_OPENAI_ENDPOINT", "https://<your-azure-openai-endpoint>/"
62+
)
5363
azure_api_key = os.getenv("AZURE_OPENAI_API_KEY")
5464

5565
# Soft validation: check if Azure OpenAI is properly configured
5666
azure_configured = (
57-
azure_api_key and
58-
azure_endpoint and
59-
"<" not in azure_endpoint and
60-
"your-azure-openai-endpoint" not in azure_endpoint
67+
azure_api_key
68+
and azure_endpoint
69+
and "<" not in azure_endpoint
70+
and "your-azure-openai-endpoint" not in azure_endpoint
6171
)
6272

6373
# Build LLM configuration with fallback providers
64-
llm_config = {
74+
providers_config: dict[str, dict[str, str | None]] = {}
75+
llm_config: dict[str, Any] = {
6576
"default_provider": None, # Will be set based on available providers
6677
"fallback_order": [], # Will be populated based on available providers
67-
"providers": {},
78+
"providers": providers_config,
6879
}
6980

7081
# Add Azure OpenAI provider only if properly configured
7182
if azure_configured:
72-
llm_config["providers"]["azure_openai"] = {
83+
providers_config["azure_openai"] = {
7384
"azure_endpoint": azure_endpoint,
7485
"api_key": azure_api_key,
7586
"api_version": os.getenv("AZURE_OPENAI_API_VERSION", "2024-02-01"),
76-
"deployment_name": os.getenv("AZURE_OPENAI_DEPLOYMENT_NAME", "gpt-35-turbo"),
87+
"deployment_name": os.getenv(
88+
"AZURE_OPENAI_DEPLOYMENT_NAME", "gpt-35-turbo"
89+
),
7790
}
7891
logger.info("Azure OpenAI provider configured successfully")
7992
else:
@@ -83,32 +96,36 @@ def __init__(self, display_config: DisplayConfig | None = None):
8396
"Azure OpenAI API key not configured. "
8497
"Set AZURE_OPENAI_API_KEY environment variable to enable Azure OpenAI provider."
8598
)
86-
if (not azure_endpoint or "<" in azure_endpoint or
87-
"your-azure-openai-endpoint" in azure_endpoint):
99+
if (
100+
not azure_endpoint
101+
or "<" in azure_endpoint
102+
or "your-azure-openai-endpoint" in azure_endpoint
103+
):
88104
logger.warning(
89105
"Azure OpenAI endpoint not properly configured. "
90106
"Set AZURE_OPENAI_ENDPOINT environment variable to enable "
91-
"Azure OpenAI provider. Current value: %s", azure_endpoint
107+
"Azure OpenAI provider. Current value: %s",
108+
azure_endpoint,
92109
)
93110
logger.info("Azure OpenAI provider skipped due to missing configuration")
94111

95112
# Add other providers for fallback
96113
openai_api_key = os.getenv("OPENAI_API_KEY")
97114
if openai_api_key:
98-
llm_config["providers"]["openai"] = {
115+
providers_config["openai"] = {
99116
"api_key": openai_api_key,
100117
}
101118
logger.info("OpenAI provider configured")
102119

103120
anthropic_api_key = os.getenv("ANTHROPIC_API_KEY")
104121
if anthropic_api_key:
105-
llm_config["providers"]["anthropic"] = {
122+
providers_config["anthropic"] = {
106123
"api_key": anthropic_api_key,
107124
}
108125
logger.info("Anthropic provider configured")
109126

110127
# Determine default provider and fallback order based on available providers
111-
available_providers = list(llm_config["providers"].keys())
128+
available_providers = list(providers_config.keys())
112129
if available_providers:
113130
# Set default provider to the first available one
114131
llm_config["default_provider"] = available_providers[0]
@@ -124,22 +141,24 @@ def __init__(self, display_config: DisplayConfig | None = None):
124141
logger.warning(" - ANTHROPIC_API_KEY")
125142

126143
# Log final configuration
127-
configured_providers = list(llm_config["providers"].keys())
144+
configured_providers = list(providers_config.keys())
128145
logger.info(
129146
"LLM configuration: default_provider=%s, fallback_order=%s, "
130147
"configured_providers=%s",
131-
llm_config['default_provider'], llm_config['fallback_order'],
132-
configured_providers
148+
llm_config["default_provider"],
149+
llm_config["fallback_order"],
150+
configured_providers,
133151
)
134152

135153
# Initialize LLM manager with validation
154+
self.llm_manager: ActionLLMProviderManager | None
136155
if llm_config["default_provider"] is not None:
137156
self.llm_manager = ActionLLMProviderManager(
138157
llm_config, display=self.display
139158
)
140159
logger.info(
141160
"LLM manager initialized successfully with provider: %s",
142-
llm_config["default_provider"]
161+
llm_config["default_provider"],
143162
)
144163
else:
145164
self.llm_manager = None
@@ -151,6 +170,7 @@ def __init__(self, display_config: DisplayConfig | None = None):
151170

152171
# Initialize AI agent manager only if LLM manager is available
153172
if self.llm_manager is not None:
173+
self.ai_agent_manager: AIAgentManager | None
154174
self.ai_agent_manager = AIAgentManager(
155175
self.llm_manager, self.performance_tracker
156176
)
@@ -164,20 +184,20 @@ def __init__(self, display_config: DisplayConfig | None = None):
164184

165185
# Initialize issue fixer only if AI agent manager is available
166186
if self.ai_agent_manager is not None:
187+
self.issue_fixer: IssueFixer | None
167188
self.issue_fixer = IssueFixer(
168189
self.ai_agent_manager, self.file_manager, self.error_handler
169190
)
170191
logger.info("Issue fixer initialized successfully")
171192
else:
172193
self.issue_fixer = None
173-
logger.warning(
174-
"Issue fixer not initialized - no AI capabilities available"
175-
)
194+
logger.warning("Issue fixer not initialized - no AI capabilities available")
176195

177196
# Initialize database for logging interactions
178197
try:
179-
from codeflow_engine.actions.ai_linting_fixer.database import \
180-
AIInteractionDB
198+
from codeflow_engine.actions.ai_linting_fixer.database import (
199+
AIInteractionDB,
200+
)
181201

182202
self.database = AIInteractionDB()
183203
if self.issue_fixer is not None:
@@ -353,23 +373,31 @@ def _get_error_recovery_suggestions(
353373

354374
def is_ai_available(self) -> bool:
355375
"""Check if AI features are available (LLM provider configured)."""
356-
return (self.llm_manager is not None and
357-
self.ai_agent_manager is not None and
358-
self.issue_fixer is not None)
376+
return (
377+
self.llm_manager is not None
378+
and self.ai_agent_manager is not None
379+
and self.issue_fixer is not None
380+
)
359381

360382
def get_ai_availability_message(self) -> str:
361383
"""Get a user-friendly message about AI availability and configuration instructions."""
362384
if self.is_ai_available():
363385
return "AI features are available and ready to use."
364386

365-
message = ("AI features are not available. To enable AI-powered linting fixes, "
366-
"configure at least one LLM provider:\n\n")
387+
message = (
388+
"AI features are not available. To enable AI-powered linting fixes, "
389+
"configure at least one LLM provider:\n\n"
390+
)
367391
message += "1. OpenAI: Set OPENAI_API_KEY environment variable\n"
368392
message += "2. Anthropic: Set ANTHROPIC_API_KEY environment variable\n"
369-
message += ("3. Azure OpenAI: Set AZURE_OPENAI_API_KEY and "
370-
"AZURE_OPENAI_ENDPOINT environment variables\n\n")
371-
message += ("Without AI providers, only issue detection will be available "
372-
"(no automatic fixes).")
393+
message += (
394+
"3. Azure OpenAI: Set AZURE_OPENAI_API_KEY and "
395+
"AZURE_OPENAI_ENDPOINT environment variables\n\n"
396+
)
397+
message += (
398+
"Without AI providers, only issue detection will be available "
399+
"(no automatic fixes)."
400+
)
373401
return message
374402

375403
def run(self, inputs: AILintingFixerInputs) -> AILintingFixerOutputs:
@@ -424,7 +452,7 @@ def run(self, inputs: AILintingFixerInputs) -> AILintingFixerOutputs:
424452
self.display.operation.show_detection_results(
425453
filtered_count=len(filtered_issues),
426454
total_count=len(issues),
427-
unique_files_count=unique_files_count
455+
unique_files_count=unique_files_count,
428456
)
429457

430458
if not filtered_issues:
@@ -492,7 +520,9 @@ def run(self, inputs: AILintingFixerInputs) -> AILintingFixerOutputs:
492520

493521
for i, issue in enumerate(issues_to_process, 1):
494522
self.display.operation.show_processing_progress(
495-
i, len(issues_to_process), convert_detection_issue_to_model_issue(issue)
523+
i,
524+
len(issues_to_process),
525+
convert_detection_issue_to_model_issue(issue),
496526
)
497527

498528
try:
@@ -567,7 +597,9 @@ def run(self, inputs: AILintingFixerInputs) -> AILintingFixerOutputs:
567597
processing_duration = time.time() - start_time
568598

569599
# Get performance metrics with defensive guard
570-
get_perf = getattr(self.performance_tracker, "get_performance_summary", None)
600+
get_perf = getattr(
601+
self.performance_tracker, "get_performance_summary", None
602+
)
571603
if callable(get_perf):
572604
performance_summary = get_perf()
573605
else:

0 commit comments

Comments
 (0)