Update app.py
Browse files
app.py
CHANGED
|
@@ -22,72 +22,64 @@ def correct_apex_trigger(model: str, trigger_code: str, progress=None) -> Tuple[
|
|
| 22 |
"""Correct Apex Trigger with skeptical evaluation."""
|
| 23 |
if progress:
|
| 24 |
progress(0.1, desc="Validating input...")
|
| 25 |
-
|
| 26 |
# Input validation
|
| 27 |
if not trigger_code.strip():
|
| 28 |
return "Please provide Apex Trigger code to correct.", "", ""
|
| 29 |
-
|
| 30 |
if len(trigger_code.strip()) < 50:
|
| 31 |
return "Code too short to be a valid Apex trigger. Please provide complete code.", "", ""
|
| 32 |
-
|
| 33 |
# Perform initial syntax check
|
| 34 |
is_valid, syntax_issues = validate_apex_syntax(trigger_code)
|
| 35 |
-
|
| 36 |
if progress:
|
| 37 |
progress(0.3, desc="Analyzing code structure...")
|
| 38 |
-
|
| 39 |
# Perform skeptical evaluation
|
| 40 |
evaluation = perform_skeptical_evaluation(trigger_code, "trigger")
|
| 41 |
-
|
| 42 |
# Build comprehensive prompt with structured output format
|
| 43 |
prompt = f"""
|
| 44 |
Correct this Apex Trigger for B2B Lightning Experience migration. Be BRIEF and DIRECT.
|
| 45 |
-
|
| 46 |
ORIGINAL CODE:
|
| 47 |
```apex
|
| 48 |
{trigger_code}
|
| 49 |
```
|
| 50 |
-
|
| 51 |
DETECTED ISSUES:
|
| 52 |
- Syntax Errors: {len(syntax_issues)}
|
| 53 |
- Security Issues: {len(evaluation['security_concerns'])}
|
| 54 |
- Performance Issues: {len(evaluation['performance_issues'])}
|
| 55 |
- B2B Commerce Issues: {len(evaluation['b2b_commerce_issues'])}
|
| 56 |
-
|
| 57 |
PROVIDE EXACTLY THIS FORMAT:
|
| 58 |
-
|
| 59 |
## CORRECTED CODE
|
| 60 |
```apex
|
| 61 |
[Put the complete corrected trigger here with inline comments for changes]
|
| 62 |
```
|
| 63 |
-
|
| 64 |
## KEY CHANGES (bullet points only)
|
| 65 |
- [Change 1: Brief description]
|
| 66 |
- [Change 2: Brief description]
|
| 67 |
- [Maximum 7 bullet points]
|
| 68 |
-
|
| 69 |
## CRITICAL ISSUES FIXED
|
| 70 |
1. [Most important issue]: [One-line explanation]
|
| 71 |
2. [Second issue]: [One-line explanation]
|
| 72 |
3. [Third issue]: [One-line explanation]
|
| 73 |
-
|
| 74 |
## REMAINING WARNINGS
|
| 75 |
- [Any issues that need manual review]
|
| 76 |
-
|
| 77 |
BE CONCISE. NO VERBOSE EXPLANATIONS. FOCUS ON CODE QUALITY.
|
| 78 |
"""
|
| 79 |
|
| 80 |
if progress:
|
| 81 |
progress(0.5, desc="Calling AI model...")
|
| 82 |
-
|
| 83 |
response = call_llm(model, prompt, temperature=0.2) # Even lower temperature for consistency
|
| 84 |
-
|
| 85 |
if progress:
|
| 86 |
progress(0.8, desc="Processing response...")
|
| 87 |
-
|
| 88 |
# Extract code and explanations
|
| 89 |
code_output = extract_code_blocks(response)
|
| 90 |
-
|
| 91 |
# Validate the corrected code
|
| 92 |
validation_warnings = []
|
| 93 |
if code_output:
|
|
@@ -96,132 +88,120 @@ BE CONCISE. NO VERBOSE EXPLANATIONS. FOCUS ON CODE QUALITY.
|
|
| 96 |
error_count = len([i for i in corrected_issues if i["type"] == "error"])
|
| 97 |
warning_count = len([i for i in corrected_issues if i["type"] == "warning"])
|
| 98 |
validation_warnings.append(f"β οΈ Validation: {error_count} errors, {warning_count} warnings remain")
|
| 99 |
-
|
| 100 |
# Extract structured explanation
|
| 101 |
explanation = format_structured_explanation(response, code_output)
|
| 102 |
-
|
| 103 |
# Add validation warnings if any
|
| 104 |
if validation_warnings:
|
| 105 |
explanation = "\n".join(validation_warnings) + "\n\n" + explanation
|
| 106 |
-
|
| 107 |
# Add test case reference (brief)
|
| 108 |
explanation += "\n\n**Test Template:** Available in Full Response section"
|
| 109 |
-
|
| 110 |
if progress:
|
| 111 |
progress(1.0, desc="Complete!")
|
| 112 |
-
|
| 113 |
return response, code_output, explanation
|
| 114 |
|
| 115 |
def convert_cc_object(model: str, cc_object_code: str, progress=None) -> Tuple[str, str, str]:
|
| 116 |
"""Convert CloudCraze Object with skeptical evaluation."""
|
| 117 |
if progress:
|
| 118 |
progress(0.1, desc="Validating input...")
|
| 119 |
-
|
| 120 |
# Input validation
|
| 121 |
if not cc_object_code.strip():
|
| 122 |
return "Please provide CloudCraze Object code to convert.", "", ""
|
| 123 |
-
|
| 124 |
if len(cc_object_code.strip()) < 30:
|
| 125 |
return "Code too short to be a valid CloudCraze object. Please provide complete code.", "", ""
|
| 126 |
-
|
| 127 |
if progress:
|
| 128 |
progress(0.3, desc="Analyzing CloudCraze structure...")
|
| 129 |
-
|
| 130 |
# Check for CloudCraze patterns
|
| 131 |
import re
|
| 132 |
has_cc_pattern = bool(re.search(B2B_COMMERCE_PATTERNS["cloudcraze_reference"], cc_object_code))
|
| 133 |
if not has_cc_pattern:
|
| 134 |
logger.warning("No obvious CloudCraze patterns found in input")
|
| 135 |
-
|
| 136 |
# Perform evaluation
|
| 137 |
evaluation = perform_skeptical_evaluation(cc_object_code, "object")
|
| 138 |
-
|
| 139 |
prompt = f"""
|
| 140 |
Convert this CloudCraze Object to B2B Lightning Experience. Be BRIEF and PRECISE.
|
| 141 |
-
|
| 142 |
CLOUDCRAZE OBJECT:
|
| 143 |
```
|
| 144 |
{cc_object_code}
|
| 145 |
```
|
| 146 |
-
|
| 147 |
PROVIDE EXACTLY THIS FORMAT:
|
| 148 |
-
|
| 149 |
## B2B LEX OBJECT MAPPING
|
| 150 |
- Source: [CloudCraze object name]
|
| 151 |
- Target: [B2B LEX object name]
|
| 152 |
- Migration Complexity: [Low/Medium/High]
|
| 153 |
-
|
| 154 |
## CONVERTED CODE
|
| 155 |
```apex
|
| 156 |
[Complete B2B LEX implementation with inline comments]
|
| 157 |
```
|
| 158 |
-
|
| 159 |
## FIELD MAPPINGS (table format)
|
| 160 |
| CC Field | B2B Field | Type | Notes |
|
| 161 |
|----------|-----------|------|-------|
|
| 162 |
| field1 | newField1 | Text | Required |
|
| 163 |
| field2 | newField2 | Number | Optional |
|
| 164 |
-
|
| 165 |
## MIGRATION STEPS
|
| 166 |
1. [Step 1 - one line]
|
| 167 |
2. [Step 2 - one line]
|
| 168 |
3. [Maximum 5 steps]
|
| 169 |
-
|
| 170 |
## DATA MIGRATION SCRIPT
|
| 171 |
```apex
|
| 172 |
[Brief data migration code if needed, otherwise state "Not Required"]
|
| 173 |
```
|
| 174 |
-
|
| 175 |
## WARNINGS
|
| 176 |
- [Any manual steps or considerations]
|
| 177 |
-
|
| 178 |
BE CONCISE. FOCUS ON ACTIONABLE INFORMATION.
|
| 179 |
"""
|
| 180 |
|
| 181 |
if progress:
|
| 182 |
progress(0.5, desc="Calling AI model...")
|
| 183 |
-
|
| 184 |
response = call_llm(model, prompt, temperature=0.2)
|
| 185 |
-
|
| 186 |
if progress:
|
| 187 |
progress(0.8, desc="Processing response...")
|
| 188 |
-
|
| 189 |
# Extract code and explanations
|
| 190 |
code_output = extract_code_blocks(response)
|
| 191 |
-
|
| 192 |
# Extract structured explanation
|
| 193 |
explanation = format_object_conversion_explanation(response, code_output)
|
| 194 |
-
|
| 195 |
# Add brief test reference
|
| 196 |
explanation += "\n\n**Test Utilities:** See Full Response for test data creation utilities"
|
| 197 |
-
|
| 198 |
if progress:
|
| 199 |
progress(1.0, desc="Complete!")
|
| 200 |
-
|
| 201 |
return response, code_output, explanation
|
| 202 |
|
| 203 |
def validate_apex_trigger(validation_model: str, original_code: str, corrected_code: str) -> str:
|
| 204 |
"""Enhanced validation with skeptical evaluation and structured output."""
|
| 205 |
if not validation_model or not original_code.strip() or not corrected_code.strip():
|
| 206 |
return "Please provide all required inputs for validation."
|
| 207 |
-
|
| 208 |
# Perform syntax validation on both
|
| 209 |
orig_valid, orig_issues = validate_apex_syntax(original_code)
|
| 210 |
corr_valid, corr_issues = validate_apex_syntax(corrected_code)
|
| 211 |
-
|
| 212 |
prompt = f"""
|
| 213 |
Validate this Apex trigger correction. Be CRITICAL but CONCISE.
|
| 214 |
-
|
| 215 |
ORIGINAL ({len(orig_issues)} issues detected):
|
| 216 |
```apex
|
| 217 |
{original_code}
|
| 218 |
```
|
| 219 |
-
|
| 220 |
CORRECTED ({len(corr_issues)} issues detected):
|
| 221 |
```apex
|
| 222 |
{corrected_code}
|
| 223 |
```
|
| 224 |
-
|
| 225 |
PROVIDE THIS EXACT JSON FORMAT:
|
| 226 |
```json
|
| 227 |
{{
|
|
@@ -246,7 +226,6 @@ PROVIDE THIS EXACT JSON FORMAT:
|
|
| 246 |
]
|
| 247 |
}}
|
| 248 |
```
|
| 249 |
-
|
| 250 |
SCORING CRITERIA:
|
| 251 |
- quality_rating: Overall code quality (1=terrible, 10=excellent)
|
| 252 |
- accuracy: Correctness of fixes (0=wrong, 1=perfect)
|
|
@@ -255,30 +234,26 @@ SCORING CRITERIA:
|
|
| 255 |
- syntax_validity: No syntax errors (0=many errors, 1=error-free)
|
| 256 |
- security_score: Security best practices (0=vulnerable, 1=secure)
|
| 257 |
- performance_score: Efficiency and scalability (0=poor, 1=optimal)
|
| 258 |
-
|
| 259 |
BE HARSH. FIND PROBLEMS. Maximum 3 items per category.
|
| 260 |
"""
|
| 261 |
-
|
| 262 |
return call_llm(validation_model, prompt, temperature=0.1) # Very low temperature for consistent JSON
|
| 263 |
|
| 264 |
def validate_cc_object_conversion(validation_model: str, original_object: str, converted_object: str) -> str:
|
| 265 |
"""Enhanced validation for CloudCraze object conversion with structured output."""
|
| 266 |
if not validation_model or not original_object.strip() or not converted_object.strip():
|
| 267 |
return "Please provide all required inputs for validation."
|
| 268 |
-
|
| 269 |
prompt = f"""
|
| 270 |
Validate this CloudCraze to B2B LEX conversion. Be CRITICAL and BRIEF.
|
| 271 |
-
|
| 272 |
ORIGINAL CLOUDCRAZE:
|
| 273 |
```
|
| 274 |
{original_object}
|
| 275 |
```
|
| 276 |
-
|
| 277 |
CONVERTED B2B LEX:
|
| 278 |
```
|
| 279 |
{converted_object}
|
| 280 |
```
|
| 281 |
-
|
| 282 |
PROVIDE THIS EXACT JSON FORMAT:
|
| 283 |
```json
|
| 284 |
{{
|
|
@@ -303,24 +278,22 @@ PROVIDE THIS EXACT JSON FORMAT:
|
|
| 303 |
]
|
| 304 |
}}
|
| 305 |
```
|
| 306 |
-
|
| 307 |
FOCUS ON:
|
| 308 |
1. Missing field mappings
|
| 309 |
2. Data type conversions
|
| 310 |
3. Relationship integrity
|
| 311 |
4. Custom field handling
|
| 312 |
5. Performance at scale
|
| 313 |
-
|
| 314 |
BE HARSH. Maximum 3 items per category. Focus on REAL issues.
|
| 315 |
"""
|
| 316 |
-
|
| 317 |
return call_llm(validation_model, prompt, temperature=0.1)
|
| 318 |
|
| 319 |
def create_enhanced_radar_chart(metrics: Optional[Dict[str, float]]) -> Optional[object]:
|
| 320 |
"""Create an enhanced radar chart with more metrics."""
|
| 321 |
if not metrics:
|
| 322 |
return None
|
| 323 |
-
|
| 324 |
# Create data for the radar chart
|
| 325 |
categories = [
|
| 326 |
"Quality",
|
|
@@ -331,7 +304,7 @@ def create_enhanced_radar_chart(metrics: Optional[Dict[str, float]]) -> Optional
|
|
| 331 |
"Security",
|
| 332 |
"Performance"
|
| 333 |
]
|
| 334 |
-
|
| 335 |
values = [
|
| 336 |
metrics.get("quality_rating", 0) / 10, # Normalize to 0-1 scale
|
| 337 |
metrics.get("accuracy", 0),
|
|
@@ -341,13 +314,13 @@ def create_enhanced_radar_chart(metrics: Optional[Dict[str, float]]) -> Optional
|
|
| 341 |
metrics.get("security_score", 0),
|
| 342 |
metrics.get("performance_score", 0)
|
| 343 |
]
|
| 344 |
-
|
| 345 |
# Create a DataFrame for plotting
|
| 346 |
df = pd.DataFrame({
|
| 347 |
'Category': categories,
|
| 348 |
'Value': values
|
| 349 |
})
|
| 350 |
-
|
| 351 |
# Create the radar chart
|
| 352 |
fig = px.line_polar(
|
| 353 |
df, r='Value', theta='Category', line_close=True,
|
|
@@ -364,7 +337,7 @@ def create_enhanced_radar_chart(metrics: Optional[Dict[str, float]]) -> Optional
|
|
| 364 |
showlegend=False,
|
| 365 |
height=400
|
| 366 |
)
|
| 367 |
-
|
| 368 |
return fig
|
| 369 |
|
| 370 |
def get_theme_styles(theme_choice: str) -> Tuple[str, str, str, str]:
|
|
@@ -383,7 +356,7 @@ def get_theme_styles(theme_choice: str) -> Tuple[str, str, str, str]:
|
|
| 383 |
"error": "background-color: #ffe4e6; color: #d73a49; padding: 10px; border-radius: 5px; border: 1px solid #d73a49;"
|
| 384 |
}
|
| 385 |
}
|
| 386 |
-
|
| 387 |
theme = themes.get(theme_choice, themes["Light"])
|
| 388 |
return (theme["explanation"], theme["code"], theme["explanation"], theme["code"])
|
| 389 |
|
|
@@ -393,11 +366,11 @@ def trigger_correction_wrapper(model, code):
|
|
| 393 |
try:
|
| 394 |
if not model or not code.strip():
|
| 395 |
return "Please select a model and provide code.", "", "Please provide valid inputs."
|
| 396 |
-
|
| 397 |
# Create dummy progress function since Gradio progress doesn't work in lambda
|
| 398 |
def dummy_progress(value, desc=""):
|
| 399 |
pass
|
| 400 |
-
|
| 401 |
return correct_apex_trigger(model, code, progress=dummy_progress)
|
| 402 |
except Exception as e:
|
| 403 |
logger.error(f"Trigger correction error: {str(e)}")
|
|
@@ -409,10 +382,10 @@ def object_conversion_wrapper(model, code):
|
|
| 409 |
try:
|
| 410 |
if not model or not code.strip():
|
| 411 |
return "Please select a model and provide code.", "", "Please provide valid inputs."
|
| 412 |
-
|
| 413 |
def dummy_progress(value, desc=""):
|
| 414 |
pass
|
| 415 |
-
|
| 416 |
return convert_cc_object(model, code, progress=dummy_progress)
|
| 417 |
except Exception as e:
|
| 418 |
logger.error(f"Object conversion error: {str(e)}")
|
|
@@ -424,7 +397,7 @@ def validate_and_chart_trigger(model, original, corrected):
|
|
| 424 |
try:
|
| 425 |
if not model or not original.strip() or not corrected.strip():
|
| 426 |
return "Please provide all required inputs for validation.", None
|
| 427 |
-
|
| 428 |
validation_text = validate_apex_trigger(model, original, corrected)
|
| 429 |
metrics = extract_validation_metrics(validation_text)
|
| 430 |
chart = create_enhanced_radar_chart(metrics) if metrics else None
|
|
@@ -438,7 +411,7 @@ def validate_and_chart_object(model, original, converted):
|
|
| 438 |
try:
|
| 439 |
if not model or not original.strip() or not converted.strip():
|
| 440 |
return "Please provide all required inputs for validation.", None
|
| 441 |
-
|
| 442 |
validation_text = validate_cc_object_conversion(model, original, converted)
|
| 443 |
metrics = extract_validation_metrics(validation_text)
|
| 444 |
chart = create_enhanced_radar_chart(metrics) if metrics else None
|
|
@@ -450,9 +423,9 @@ def validate_and_chart_object(model, original, converted):
|
|
| 450 |
def main():
|
| 451 |
"""Main application entry point."""
|
| 452 |
with gr.Blocks(
|
| 453 |
-
|
| 454 |
-
|
| 455 |
-
|
| 456 |
.gradio-container {
|
| 457 |
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
| 458 |
}
|
|
@@ -467,7 +440,7 @@ def main():
|
|
| 467 |
}
|
| 468 |
"""
|
| 469 |
) as app:
|
| 470 |
-
|
| 471 |
gr.Markdown("# π Salesforce B2B Commerce Migration Assistant")
|
| 472 |
gr.Markdown("Advanced tool for migrating CloudCraze code to B2B Lightning Experience with skeptical AI validation.")
|
| 473 |
|
|
@@ -481,7 +454,7 @@ def main():
|
|
| 481 |
label="Select Primary AI Model for Conversion",
|
| 482 |
info="This model performs the initial code conversion"
|
| 483 |
)
|
| 484 |
-
|
| 485 |
with gr.Column():
|
| 486 |
gr.Markdown("### π Validation Model")
|
| 487 |
validation_model_dropdown = gr.Dropdown(
|
|
@@ -501,21 +474,21 @@ def main():
|
|
| 501 |
label="Apex Trigger Code",
|
| 502 |
elem_classes="code-input"
|
| 503 |
)
|
| 504 |
-
|
| 505 |
with gr.Row():
|
| 506 |
trigger_button = gr.Button("π§ Correct & Optimize", variant="primary", size="lg")
|
| 507 |
copy_code_button = gr.Button("π Copy Code", variant="secondary")
|
| 508 |
-
|
| 509 |
# Progress indicator
|
| 510 |
trigger_progress = gr.Textbox(label="Progress", visible=False)
|
| 511 |
-
|
| 512 |
with gr.Accordion("π Full Model Response", open=False):
|
| 513 |
trigger_full_response = gr.Textbox(
|
| 514 |
lines=20,
|
| 515 |
label="Full Model Response",
|
| 516 |
interactive=False
|
| 517 |
)
|
| 518 |
-
|
| 519 |
with gr.Row():
|
| 520 |
with gr.Column():
|
| 521 |
trigger_explanation = gr.Textbox(
|
|
@@ -525,7 +498,7 @@ def main():
|
|
| 525 |
interactive=False,
|
| 526 |
elem_id="trigger_explanation"
|
| 527 |
)
|
| 528 |
-
|
| 529 |
with gr.Column():
|
| 530 |
trigger_code_output = gr.Code(
|
| 531 |
language="python", # Using python highlighting as java is not supported
|
|
@@ -533,7 +506,7 @@ def main():
|
|
| 533 |
value="// Corrected Apex code will appear here",
|
| 534 |
elem_id="trigger_code_output"
|
| 535 |
)
|
| 536 |
-
|
| 537 |
gr.Markdown("### π― Validation Results")
|
| 538 |
with gr.Row():
|
| 539 |
with gr.Column(scale=2):
|
|
@@ -546,9 +519,9 @@ def main():
|
|
| 546 |
)
|
| 547 |
with gr.Column(scale=1):
|
| 548 |
trigger_chart = gr.Plot(label="π Validation Metrics")
|
| 549 |
-
|
| 550 |
validate_trigger_button = gr.Button("π Validate Correction", variant="secondary", size="lg")
|
| 551 |
-
|
| 552 |
# Wire up functionality - INSIDE the main function where UI elements are defined
|
| 553 |
trigger_button.click(
|
| 554 |
fn=trigger_correction_wrapper,
|
|
@@ -556,24 +529,24 @@ def main():
|
|
| 556 |
outputs=[trigger_full_response, trigger_code_output, trigger_explanation],
|
| 557 |
show_progress=True
|
| 558 |
)
|
| 559 |
-
|
| 560 |
validate_trigger_button.click(
|
| 561 |
fn=validate_and_chart_trigger,
|
| 562 |
inputs=[validation_model_dropdown, trigger_input, trigger_code_output],
|
| 563 |
outputs=[trigger_validation_output, trigger_chart],
|
| 564 |
show_progress=True
|
| 565 |
)
|
| 566 |
-
|
| 567 |
copy_code_button.click(
|
| 568 |
fn=lambda: gr.Info("Code copied! Use Ctrl+C/Cmd+C if automatic copy fails."),
|
| 569 |
inputs=[],
|
| 570 |
outputs=[]
|
| 571 |
)
|
| 572 |
-
|
| 573 |
with gr.Row():
|
| 574 |
trigger_clear = gr.Button("ποΈ Clear Input")
|
| 575 |
trigger_clear.click(lambda: "", [], trigger_input)
|
| 576 |
-
|
| 577 |
results_clear = gr.Button("π§Ή Clear Results")
|
| 578 |
results_clear.click(
|
| 579 |
lambda: ["", "", "", "", None],
|
|
@@ -591,21 +564,21 @@ def main():
|
|
| 591 |
label="CloudCraze Object Code",
|
| 592 |
elem_classes="code-input"
|
| 593 |
)
|
| 594 |
-
|
| 595 |
with gr.Row():
|
| 596 |
object_button = gr.Button("π Convert Object", variant="primary", size="lg")
|
| 597 |
object_copy_code_button = gr.Button("π Copy Code", variant="secondary")
|
| 598 |
-
|
| 599 |
# Progress indicator
|
| 600 |
object_progress = gr.Textbox(label="Progress", visible=False)
|
| 601 |
-
|
| 602 |
with gr.Accordion("π Full Model Response", open=False):
|
| 603 |
object_full_response = gr.Textbox(
|
| 604 |
lines=20,
|
| 605 |
label="Full Model Response",
|
| 606 |
interactive=False
|
| 607 |
)
|
| 608 |
-
|
| 609 |
with gr.Row():
|
| 610 |
with gr.Column():
|
| 611 |
object_explanation = gr.Textbox(
|
|
@@ -615,7 +588,7 @@ def main():
|
|
| 615 |
interactive=False,
|
| 616 |
elem_id="object_explanation"
|
| 617 |
)
|
| 618 |
-
|
| 619 |
with gr.Column():
|
| 620 |
object_code_output = gr.Code(
|
| 621 |
language="python", # Using python highlighting as java is not supported
|
|
@@ -623,7 +596,7 @@ def main():
|
|
| 623 |
value="// Converted B2B Lightning Experience code will appear here",
|
| 624 |
elem_id="object_code_output"
|
| 625 |
)
|
| 626 |
-
|
| 627 |
gr.Markdown("### π― Validation Results")
|
| 628 |
with gr.Row():
|
| 629 |
with gr.Column(scale=2):
|
|
@@ -636,9 +609,9 @@ def main():
|
|
| 636 |
)
|
| 637 |
with gr.Column(scale=1):
|
| 638 |
object_chart = gr.Plot(label="π Validation Metrics")
|
| 639 |
-
|
| 640 |
validate_object_button = gr.Button("π Validate Conversion", variant="secondary", size="lg")
|
| 641 |
-
|
| 642 |
# Wire up functionality - INSIDE the main function where UI elements are defined
|
| 643 |
object_button.click(
|
| 644 |
fn=object_conversion_wrapper,
|
|
@@ -646,24 +619,24 @@ def main():
|
|
| 646 |
outputs=[object_full_response, object_code_output, object_explanation],
|
| 647 |
show_progress=True
|
| 648 |
)
|
| 649 |
-
|
| 650 |
validate_object_button.click(
|
| 651 |
fn=validate_and_chart_object,
|
| 652 |
inputs=[validation_model_dropdown, object_input, object_code_output],
|
| 653 |
outputs=[object_validation_output, object_chart],
|
| 654 |
show_progress=True
|
| 655 |
)
|
| 656 |
-
|
| 657 |
object_copy_code_button.click(
|
| 658 |
fn=lambda: gr.Info("Code copied! Use Ctrl+C/Cmd+C if automatic copy fails."),
|
| 659 |
inputs=[],
|
| 660 |
outputs=[]
|
| 661 |
)
|
| 662 |
-
|
| 663 |
with gr.Row():
|
| 664 |
object_clear = gr.Button("ποΈ Clear Input")
|
| 665 |
object_clear.click(lambda: "", [], object_input)
|
| 666 |
-
|
| 667 |
object_results_clear = gr.Button("π§Ή Clear Results")
|
| 668 |
object_results_clear.click(
|
| 669 |
lambda: ["", "", "", "", None],
|
|
@@ -674,17 +647,17 @@ def main():
|
|
| 674 |
# UI Preferences
|
| 675 |
with gr.Accordion("βοΈ UI Preferences", open=False):
|
| 676 |
theme_radio = gr.Radio(
|
| 677 |
-
label="π¨ Theme",
|
| 678 |
-
choices=["Light", "Dark"],
|
| 679 |
value="Light"
|
| 680 |
)
|
| 681 |
-
|
| 682 |
# Comment out theme functionality for now to avoid conflicts
|
| 683 |
# theme_radio.change(
|
| 684 |
# fn=get_theme_styles,
|
| 685 |
# inputs=[theme_radio],
|
| 686 |
# outputs=[
|
| 687 |
-
# trigger_explanation,
|
| 688 |
# trigger_code_output,
|
| 689 |
# object_explanation,
|
| 690 |
# object_code_output
|
|
@@ -712,4 +685,4 @@ def main():
|
|
| 712 |
app.launch()
|
| 713 |
|
| 714 |
if __name__ == "__main__":
|
| 715 |
-
main()
|
|
|
|
| 22 |
"""Correct Apex Trigger with skeptical evaluation."""
|
| 23 |
if progress:
|
| 24 |
progress(0.1, desc="Validating input...")
|
| 25 |
+
|
| 26 |
# Input validation
|
| 27 |
if not trigger_code.strip():
|
| 28 |
return "Please provide Apex Trigger code to correct.", "", ""
|
| 29 |
+
|
| 30 |
if len(trigger_code.strip()) < 50:
|
| 31 |
return "Code too short to be a valid Apex trigger. Please provide complete code.", "", ""
|
| 32 |
+
|
| 33 |
# Perform initial syntax check
|
| 34 |
is_valid, syntax_issues = validate_apex_syntax(trigger_code)
|
| 35 |
+
|
| 36 |
if progress:
|
| 37 |
progress(0.3, desc="Analyzing code structure...")
|
| 38 |
+
|
| 39 |
# Perform skeptical evaluation
|
| 40 |
evaluation = perform_skeptical_evaluation(trigger_code, "trigger")
|
| 41 |
+
|
| 42 |
# Build comprehensive prompt with structured output format
|
| 43 |
prompt = f"""
|
| 44 |
Correct this Apex Trigger for B2B Lightning Experience migration. Be BRIEF and DIRECT.
|
|
|
|
| 45 |
ORIGINAL CODE:
|
| 46 |
```apex
|
| 47 |
{trigger_code}
|
| 48 |
```
|
|
|
|
| 49 |
DETECTED ISSUES:
|
| 50 |
- Syntax Errors: {len(syntax_issues)}
|
| 51 |
- Security Issues: {len(evaluation['security_concerns'])}
|
| 52 |
- Performance Issues: {len(evaluation['performance_issues'])}
|
| 53 |
- B2B Commerce Issues: {len(evaluation['b2b_commerce_issues'])}
|
|
|
|
| 54 |
PROVIDE EXACTLY THIS FORMAT:
|
|
|
|
| 55 |
## CORRECTED CODE
|
| 56 |
```apex
|
| 57 |
[Put the complete corrected trigger here with inline comments for changes]
|
| 58 |
```
|
|
|
|
| 59 |
## KEY CHANGES (bullet points only)
|
| 60 |
- [Change 1: Brief description]
|
| 61 |
- [Change 2: Brief description]
|
| 62 |
- [Maximum 7 bullet points]
|
|
|
|
| 63 |
## CRITICAL ISSUES FIXED
|
| 64 |
1. [Most important issue]: [One-line explanation]
|
| 65 |
2. [Second issue]: [One-line explanation]
|
| 66 |
3. [Third issue]: [One-line explanation]
|
|
|
|
| 67 |
## REMAINING WARNINGS
|
| 68 |
- [Any issues that need manual review]
|
|
|
|
| 69 |
BE CONCISE. NO VERBOSE EXPLANATIONS. FOCUS ON CODE QUALITY.
|
| 70 |
"""
|
| 71 |
|
| 72 |
if progress:
|
| 73 |
progress(0.5, desc="Calling AI model...")
|
| 74 |
+
|
| 75 |
response = call_llm(model, prompt, temperature=0.2) # Even lower temperature for consistency
|
| 76 |
+
|
| 77 |
if progress:
|
| 78 |
progress(0.8, desc="Processing response...")
|
| 79 |
+
|
| 80 |
# Extract code and explanations
|
| 81 |
code_output = extract_code_blocks(response)
|
| 82 |
+
|
| 83 |
# Validate the corrected code
|
| 84 |
validation_warnings = []
|
| 85 |
if code_output:
|
|
|
|
| 88 |
error_count = len([i for i in corrected_issues if i["type"] == "error"])
|
| 89 |
warning_count = len([i for i in corrected_issues if i["type"] == "warning"])
|
| 90 |
validation_warnings.append(f"β οΈ Validation: {error_count} errors, {warning_count} warnings remain")
|
| 91 |
+
|
| 92 |
# Extract structured explanation
|
| 93 |
explanation = format_structured_explanation(response, code_output)
|
| 94 |
+
|
| 95 |
# Add validation warnings if any
|
| 96 |
if validation_warnings:
|
| 97 |
explanation = "\n".join(validation_warnings) + "\n\n" + explanation
|
| 98 |
+
|
| 99 |
# Add test case reference (brief)
|
| 100 |
explanation += "\n\n**Test Template:** Available in Full Response section"
|
| 101 |
+
|
| 102 |
if progress:
|
| 103 |
progress(1.0, desc="Complete!")
|
| 104 |
+
|
| 105 |
return response, code_output, explanation
|
| 106 |
|
| 107 |
def convert_cc_object(model: str, cc_object_code: str, progress=None) -> Tuple[str, str, str]:
|
| 108 |
"""Convert CloudCraze Object with skeptical evaluation."""
|
| 109 |
if progress:
|
| 110 |
progress(0.1, desc="Validating input...")
|
| 111 |
+
|
| 112 |
# Input validation
|
| 113 |
if not cc_object_code.strip():
|
| 114 |
return "Please provide CloudCraze Object code to convert.", "", ""
|
| 115 |
+
|
| 116 |
if len(cc_object_code.strip()) < 30:
|
| 117 |
return "Code too short to be a valid CloudCraze object. Please provide complete code.", "", ""
|
| 118 |
+
|
| 119 |
if progress:
|
| 120 |
progress(0.3, desc="Analyzing CloudCraze structure...")
|
| 121 |
+
|
| 122 |
# Check for CloudCraze patterns
|
| 123 |
import re
|
| 124 |
has_cc_pattern = bool(re.search(B2B_COMMERCE_PATTERNS["cloudcraze_reference"], cc_object_code))
|
| 125 |
if not has_cc_pattern:
|
| 126 |
logger.warning("No obvious CloudCraze patterns found in input")
|
| 127 |
+
|
| 128 |
# Perform evaluation
|
| 129 |
evaluation = perform_skeptical_evaluation(cc_object_code, "object")
|
| 130 |
+
|
| 131 |
prompt = f"""
|
| 132 |
Convert this CloudCraze Object to B2B Lightning Experience. Be BRIEF and PRECISE.
|
|
|
|
| 133 |
CLOUDCRAZE OBJECT:
|
| 134 |
```
|
| 135 |
{cc_object_code}
|
| 136 |
```
|
|
|
|
| 137 |
PROVIDE EXACTLY THIS FORMAT:
|
|
|
|
| 138 |
## B2B LEX OBJECT MAPPING
|
| 139 |
- Source: [CloudCraze object name]
|
| 140 |
- Target: [B2B LEX object name]
|
| 141 |
- Migration Complexity: [Low/Medium/High]
|
|
|
|
| 142 |
## CONVERTED CODE
|
| 143 |
```apex
|
| 144 |
[Complete B2B LEX implementation with inline comments]
|
| 145 |
```
|
|
|
|
| 146 |
## FIELD MAPPINGS (table format)
|
| 147 |
| CC Field | B2B Field | Type | Notes |
|
| 148 |
|----------|-----------|------|-------|
|
| 149 |
| field1 | newField1 | Text | Required |
|
| 150 |
| field2 | newField2 | Number | Optional |
|
|
|
|
| 151 |
## MIGRATION STEPS
|
| 152 |
1. [Step 1 - one line]
|
| 153 |
2. [Step 2 - one line]
|
| 154 |
3. [Maximum 5 steps]
|
|
|
|
| 155 |
## DATA MIGRATION SCRIPT
|
| 156 |
```apex
|
| 157 |
[Brief data migration code if needed, otherwise state "Not Required"]
|
| 158 |
```
|
|
|
|
| 159 |
## WARNINGS
|
| 160 |
- [Any manual steps or considerations]
|
|
|
|
| 161 |
BE CONCISE. FOCUS ON ACTIONABLE INFORMATION.
|
| 162 |
"""
|
| 163 |
|
| 164 |
if progress:
|
| 165 |
progress(0.5, desc="Calling AI model...")
|
| 166 |
+
|
| 167 |
response = call_llm(model, prompt, temperature=0.2)
|
| 168 |
+
|
| 169 |
if progress:
|
| 170 |
progress(0.8, desc="Processing response...")
|
| 171 |
+
|
| 172 |
# Extract code and explanations
|
| 173 |
code_output = extract_code_blocks(response)
|
| 174 |
+
|
| 175 |
# Extract structured explanation
|
| 176 |
explanation = format_object_conversion_explanation(response, code_output)
|
| 177 |
+
|
| 178 |
# Add brief test reference
|
| 179 |
explanation += "\n\n**Test Utilities:** See Full Response for test data creation utilities"
|
| 180 |
+
|
| 181 |
if progress:
|
| 182 |
progress(1.0, desc="Complete!")
|
| 183 |
+
|
| 184 |
return response, code_output, explanation
|
| 185 |
|
| 186 |
def validate_apex_trigger(validation_model: str, original_code: str, corrected_code: str) -> str:
|
| 187 |
"""Enhanced validation with skeptical evaluation and structured output."""
|
| 188 |
if not validation_model or not original_code.strip() or not corrected_code.strip():
|
| 189 |
return "Please provide all required inputs for validation."
|
| 190 |
+
|
| 191 |
# Perform syntax validation on both
|
| 192 |
orig_valid, orig_issues = validate_apex_syntax(original_code)
|
| 193 |
corr_valid, corr_issues = validate_apex_syntax(corrected_code)
|
| 194 |
+
|
| 195 |
prompt = f"""
|
| 196 |
Validate this Apex trigger correction. Be CRITICAL but CONCISE.
|
|
|
|
| 197 |
ORIGINAL ({len(orig_issues)} issues detected):
|
| 198 |
```apex
|
| 199 |
{original_code}
|
| 200 |
```
|
|
|
|
| 201 |
CORRECTED ({len(corr_issues)} issues detected):
|
| 202 |
```apex
|
| 203 |
{corrected_code}
|
| 204 |
```
|
|
|
|
| 205 |
PROVIDE THIS EXACT JSON FORMAT:
|
| 206 |
```json
|
| 207 |
{{
|
|
|
|
| 226 |
]
|
| 227 |
}}
|
| 228 |
```
|
|
|
|
| 229 |
SCORING CRITERIA:
|
| 230 |
- quality_rating: Overall code quality (1=terrible, 10=excellent)
|
| 231 |
- accuracy: Correctness of fixes (0=wrong, 1=perfect)
|
|
|
|
| 234 |
- syntax_validity: No syntax errors (0=many errors, 1=error-free)
|
| 235 |
- security_score: Security best practices (0=vulnerable, 1=secure)
|
| 236 |
- performance_score: Efficiency and scalability (0=poor, 1=optimal)
|
|
|
|
| 237 |
BE HARSH. FIND PROBLEMS. Maximum 3 items per category.
|
| 238 |
"""
|
| 239 |
+
|
| 240 |
return call_llm(validation_model, prompt, temperature=0.1) # Very low temperature for consistent JSON
|
| 241 |
|
| 242 |
def validate_cc_object_conversion(validation_model: str, original_object: str, converted_object: str) -> str:
|
| 243 |
"""Enhanced validation for CloudCraze object conversion with structured output."""
|
| 244 |
if not validation_model or not original_object.strip() or not converted_object.strip():
|
| 245 |
return "Please provide all required inputs for validation."
|
| 246 |
+
|
| 247 |
prompt = f"""
|
| 248 |
Validate this CloudCraze to B2B LEX conversion. Be CRITICAL and BRIEF.
|
|
|
|
| 249 |
ORIGINAL CLOUDCRAZE:
|
| 250 |
```
|
| 251 |
{original_object}
|
| 252 |
```
|
|
|
|
| 253 |
CONVERTED B2B LEX:
|
| 254 |
```
|
| 255 |
{converted_object}
|
| 256 |
```
|
|
|
|
| 257 |
PROVIDE THIS EXACT JSON FORMAT:
|
| 258 |
```json
|
| 259 |
{{
|
|
|
|
| 278 |
]
|
| 279 |
}}
|
| 280 |
```
|
|
|
|
| 281 |
FOCUS ON:
|
| 282 |
1. Missing field mappings
|
| 283 |
2. Data type conversions
|
| 284 |
3. Relationship integrity
|
| 285 |
4. Custom field handling
|
| 286 |
5. Performance at scale
|
|
|
|
| 287 |
BE HARSH. Maximum 3 items per category. Focus on REAL issues.
|
| 288 |
"""
|
| 289 |
+
|
| 290 |
return call_llm(validation_model, prompt, temperature=0.1)
|
| 291 |
|
| 292 |
def create_enhanced_radar_chart(metrics: Optional[Dict[str, float]]) -> Optional[object]:
|
| 293 |
"""Create an enhanced radar chart with more metrics."""
|
| 294 |
if not metrics:
|
| 295 |
return None
|
| 296 |
+
|
| 297 |
# Create data for the radar chart
|
| 298 |
categories = [
|
| 299 |
"Quality",
|
|
|
|
| 304 |
"Security",
|
| 305 |
"Performance"
|
| 306 |
]
|
| 307 |
+
|
| 308 |
values = [
|
| 309 |
metrics.get("quality_rating", 0) / 10, # Normalize to 0-1 scale
|
| 310 |
metrics.get("accuracy", 0),
|
|
|
|
| 314 |
metrics.get("security_score", 0),
|
| 315 |
metrics.get("performance_score", 0)
|
| 316 |
]
|
| 317 |
+
|
| 318 |
# Create a DataFrame for plotting
|
| 319 |
df = pd.DataFrame({
|
| 320 |
'Category': categories,
|
| 321 |
'Value': values
|
| 322 |
})
|
| 323 |
+
|
| 324 |
# Create the radar chart
|
| 325 |
fig = px.line_polar(
|
| 326 |
df, r='Value', theta='Category', line_close=True,
|
|
|
|
| 337 |
showlegend=False,
|
| 338 |
height=400
|
| 339 |
)
|
| 340 |
+
|
| 341 |
return fig
|
| 342 |
|
| 343 |
def get_theme_styles(theme_choice: str) -> Tuple[str, str, str, str]:
|
|
|
|
| 356 |
"error": "background-color: #ffe4e6; color: #d73a49; padding: 10px; border-radius: 5px; border: 1px solid #d73a49;"
|
| 357 |
}
|
| 358 |
}
|
| 359 |
+
|
| 360 |
theme = themes.get(theme_choice, themes["Light"])
|
| 361 |
return (theme["explanation"], theme["code"], theme["explanation"], theme["code"])
|
| 362 |
|
|
|
|
| 366 |
try:
|
| 367 |
if not model or not code.strip():
|
| 368 |
return "Please select a model and provide code.", "", "Please provide valid inputs."
|
| 369 |
+
|
| 370 |
# Create dummy progress function since Gradio progress doesn't work in lambda
|
| 371 |
def dummy_progress(value, desc=""):
|
| 372 |
pass
|
| 373 |
+
|
| 374 |
return correct_apex_trigger(model, code, progress=dummy_progress)
|
| 375 |
except Exception as e:
|
| 376 |
logger.error(f"Trigger correction error: {str(e)}")
|
|
|
|
| 382 |
try:
|
| 383 |
if not model or not code.strip():
|
| 384 |
return "Please select a model and provide code.", "", "Please provide valid inputs."
|
| 385 |
+
|
| 386 |
def dummy_progress(value, desc=""):
|
| 387 |
pass
|
| 388 |
+
|
| 389 |
return convert_cc_object(model, code, progress=dummy_progress)
|
| 390 |
except Exception as e:
|
| 391 |
logger.error(f"Object conversion error: {str(e)}")
|
|
|
|
| 397 |
try:
|
| 398 |
if not model or not original.strip() or not corrected.strip():
|
| 399 |
return "Please provide all required inputs for validation.", None
|
| 400 |
+
|
| 401 |
validation_text = validate_apex_trigger(model, original, corrected)
|
| 402 |
metrics = extract_validation_metrics(validation_text)
|
| 403 |
chart = create_enhanced_radar_chart(metrics) if metrics else None
|
|
|
|
| 411 |
try:
|
| 412 |
if not model or not original.strip() or not converted.strip():
|
| 413 |
return "Please provide all required inputs for validation.", None
|
| 414 |
+
|
| 415 |
validation_text = validate_cc_object_conversion(model, original, converted)
|
| 416 |
metrics = extract_validation_metrics(validation_text)
|
| 417 |
chart = create_enhanced_radar_chart(metrics) if metrics else None
|
|
|
|
| 423 |
def main():
|
| 424 |
"""Main application entry point."""
|
| 425 |
with gr.Blocks(
|
| 426 |
+
title="Salesforce B2B Commerce Migration Assistant",
|
| 427 |
+
theme=gr.themes.Soft(primary_hue="blue"),
|
| 428 |
+
css="""
|
| 429 |
.gradio-container {
|
| 430 |
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
| 431 |
}
|
|
|
|
| 440 |
}
|
| 441 |
"""
|
| 442 |
) as app:
|
| 443 |
+
|
| 444 |
gr.Markdown("# π Salesforce B2B Commerce Migration Assistant")
|
| 445 |
gr.Markdown("Advanced tool for migrating CloudCraze code to B2B Lightning Experience with skeptical AI validation.")
|
| 446 |
|
|
|
|
| 454 |
label="Select Primary AI Model for Conversion",
|
| 455 |
info="This model performs the initial code conversion"
|
| 456 |
)
|
| 457 |
+
|
| 458 |
with gr.Column():
|
| 459 |
gr.Markdown("### π Validation Model")
|
| 460 |
validation_model_dropdown = gr.Dropdown(
|
|
|
|
| 474 |
label="Apex Trigger Code",
|
| 475 |
elem_classes="code-input"
|
| 476 |
)
|
| 477 |
+
|
| 478 |
with gr.Row():
|
| 479 |
trigger_button = gr.Button("π§ Correct & Optimize", variant="primary", size="lg")
|
| 480 |
copy_code_button = gr.Button("π Copy Code", variant="secondary")
|
| 481 |
+
|
| 482 |
# Progress indicator
|
| 483 |
trigger_progress = gr.Textbox(label="Progress", visible=False)
|
| 484 |
+
|
| 485 |
with gr.Accordion("π Full Model Response", open=False):
|
| 486 |
trigger_full_response = gr.Textbox(
|
| 487 |
lines=20,
|
| 488 |
label="Full Model Response",
|
| 489 |
interactive=False
|
| 490 |
)
|
| 491 |
+
|
| 492 |
with gr.Row():
|
| 493 |
with gr.Column():
|
| 494 |
trigger_explanation = gr.Textbox(
|
|
|
|
| 498 |
interactive=False,
|
| 499 |
elem_id="trigger_explanation"
|
| 500 |
)
|
| 501 |
+
|
| 502 |
with gr.Column():
|
| 503 |
trigger_code_output = gr.Code(
|
| 504 |
language="python", # Using python highlighting as java is not supported
|
|
|
|
| 506 |
value="// Corrected Apex code will appear here",
|
| 507 |
elem_id="trigger_code_output"
|
| 508 |
)
|
| 509 |
+
|
| 510 |
gr.Markdown("### π― Validation Results")
|
| 511 |
with gr.Row():
|
| 512 |
with gr.Column(scale=2):
|
|
|
|
| 519 |
)
|
| 520 |
with gr.Column(scale=1):
|
| 521 |
trigger_chart = gr.Plot(label="π Validation Metrics")
|
| 522 |
+
|
| 523 |
validate_trigger_button = gr.Button("π Validate Correction", variant="secondary", size="lg")
|
| 524 |
+
|
| 525 |
# Wire up functionality - INSIDE the main function where UI elements are defined
|
| 526 |
trigger_button.click(
|
| 527 |
fn=trigger_correction_wrapper,
|
|
|
|
| 529 |
outputs=[trigger_full_response, trigger_code_output, trigger_explanation],
|
| 530 |
show_progress=True
|
| 531 |
)
|
| 532 |
+
|
| 533 |
validate_trigger_button.click(
|
| 534 |
fn=validate_and_chart_trigger,
|
| 535 |
inputs=[validation_model_dropdown, trigger_input, trigger_code_output],
|
| 536 |
outputs=[trigger_validation_output, trigger_chart],
|
| 537 |
show_progress=True
|
| 538 |
)
|
| 539 |
+
|
| 540 |
copy_code_button.click(
|
| 541 |
fn=lambda: gr.Info("Code copied! Use Ctrl+C/Cmd+C if automatic copy fails."),
|
| 542 |
inputs=[],
|
| 543 |
outputs=[]
|
| 544 |
)
|
| 545 |
+
|
| 546 |
with gr.Row():
|
| 547 |
trigger_clear = gr.Button("ποΈ Clear Input")
|
| 548 |
trigger_clear.click(lambda: "", [], trigger_input)
|
| 549 |
+
|
| 550 |
results_clear = gr.Button("π§Ή Clear Results")
|
| 551 |
results_clear.click(
|
| 552 |
lambda: ["", "", "", "", None],
|
|
|
|
| 564 |
label="CloudCraze Object Code",
|
| 565 |
elem_classes="code-input"
|
| 566 |
)
|
| 567 |
+
|
| 568 |
with gr.Row():
|
| 569 |
object_button = gr.Button("π Convert Object", variant="primary", size="lg")
|
| 570 |
object_copy_code_button = gr.Button("π Copy Code", variant="secondary")
|
| 571 |
+
|
| 572 |
# Progress indicator
|
| 573 |
object_progress = gr.Textbox(label="Progress", visible=False)
|
| 574 |
+
|
| 575 |
with gr.Accordion("π Full Model Response", open=False):
|
| 576 |
object_full_response = gr.Textbox(
|
| 577 |
lines=20,
|
| 578 |
label="Full Model Response",
|
| 579 |
interactive=False
|
| 580 |
)
|
| 581 |
+
|
| 582 |
with gr.Row():
|
| 583 |
with gr.Column():
|
| 584 |
object_explanation = gr.Textbox(
|
|
|
|
| 588 |
interactive=False,
|
| 589 |
elem_id="object_explanation"
|
| 590 |
)
|
| 591 |
+
|
| 592 |
with gr.Column():
|
| 593 |
object_code_output = gr.Code(
|
| 594 |
language="python", # Using python highlighting as java is not supported
|
|
|
|
| 596 |
value="// Converted B2B Lightning Experience code will appear here",
|
| 597 |
elem_id="object_code_output"
|
| 598 |
)
|
| 599 |
+
|
| 600 |
gr.Markdown("### π― Validation Results")
|
| 601 |
with gr.Row():
|
| 602 |
with gr.Column(scale=2):
|
|
|
|
| 609 |
)
|
| 610 |
with gr.Column(scale=1):
|
| 611 |
object_chart = gr.Plot(label="π Validation Metrics")
|
| 612 |
+
|
| 613 |
validate_object_button = gr.Button("π Validate Conversion", variant="secondary", size="lg")
|
| 614 |
+
|
| 615 |
# Wire up functionality - INSIDE the main function where UI elements are defined
|
| 616 |
object_button.click(
|
| 617 |
fn=object_conversion_wrapper,
|
|
|
|
| 619 |
outputs=[object_full_response, object_code_output, object_explanation],
|
| 620 |
show_progress=True
|
| 621 |
)
|
| 622 |
+
|
| 623 |
validate_object_button.click(
|
| 624 |
fn=validate_and_chart_object,
|
| 625 |
inputs=[validation_model_dropdown, object_input, object_code_output],
|
| 626 |
outputs=[object_validation_output, object_chart],
|
| 627 |
show_progress=True
|
| 628 |
)
|
| 629 |
+
|
| 630 |
object_copy_code_button.click(
|
| 631 |
fn=lambda: gr.Info("Code copied! Use Ctrl+C/Cmd+C if automatic copy fails."),
|
| 632 |
inputs=[],
|
| 633 |
outputs=[]
|
| 634 |
)
|
| 635 |
+
|
| 636 |
with gr.Row():
|
| 637 |
object_clear = gr.Button("ποΈ Clear Input")
|
| 638 |
object_clear.click(lambda: "", [], object_input)
|
| 639 |
+
|
| 640 |
object_results_clear = gr.Button("π§Ή Clear Results")
|
| 641 |
object_results_clear.click(
|
| 642 |
lambda: ["", "", "", "", None],
|
|
|
|
| 647 |
# UI Preferences
|
| 648 |
with gr.Accordion("βοΈ UI Preferences", open=False):
|
| 649 |
theme_radio = gr.Radio(
|
| 650 |
+
label="π¨ Theme",
|
| 651 |
+
choices=["Light", "Dark"],
|
| 652 |
value="Light"
|
| 653 |
)
|
| 654 |
+
|
| 655 |
# Comment out theme functionality for now to avoid conflicts
|
| 656 |
# theme_radio.change(
|
| 657 |
# fn=get_theme_styles,
|
| 658 |
# inputs=[theme_radio],
|
| 659 |
# outputs=[
|
| 660 |
+
# trigger_explanation,
|
| 661 |
# trigger_code_output,
|
| 662 |
# object_explanation,
|
| 663 |
# object_code_output
|
|
|
|
| 685 |
app.launch()
|
| 686 |
|
| 687 |
if __name__ == "__main__":
|
| 688 |
+
main()
|