Spaces:
Runtime error
Runtime error
Polish demo readability and summary fallback
Browse filesCo-authored-by: Codex <codex@openai.com>
app.py
CHANGED
|
@@ -64,27 +64,27 @@ CSS = """
|
|
| 64 |
}
|
| 65 |
|
| 66 |
.score-card {
|
| 67 |
-
background:
|
| 68 |
border: 1px solid var(--line);
|
| 69 |
border-radius: 8px;
|
| 70 |
padding: 12px;
|
| 71 |
}
|
| 72 |
|
| 73 |
.score-label {
|
| 74 |
-
color:
|
| 75 |
font-size: 12px;
|
| 76 |
text-transform: uppercase;
|
| 77 |
}
|
| 78 |
|
| 79 |
.score-value {
|
| 80 |
-
color:
|
| 81 |
font-size: 24px;
|
| 82 |
font-weight: 700;
|
| 83 |
margin-top: 2px;
|
| 84 |
}
|
| 85 |
|
| 86 |
.diff-wrap {
|
| 87 |
-
background:
|
| 88 |
border: 1px solid var(--line);
|
| 89 |
border-radius: 8px;
|
| 90 |
overflow: hidden;
|
|
@@ -123,33 +123,40 @@ CSS = """
|
|
| 123 |
}
|
| 124 |
|
| 125 |
.line-code {
|
|
|
|
|
|
|
| 126 |
white-space: pre-wrap;
|
| 127 |
overflow-wrap: anywhere;
|
| 128 |
padding: 3px 10px;
|
| 129 |
}
|
| 130 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 131 |
.line.add .line-code {
|
| 132 |
-
background: var(--add-bg);
|
| 133 |
-
color: var(--add-ink);
|
| 134 |
}
|
| 135 |
|
| 136 |
.line.del .line-code {
|
| 137 |
-
background: var(--del-bg);
|
| 138 |
-
color: var(--del-ink);
|
| 139 |
}
|
| 140 |
|
| 141 |
.finding {
|
| 142 |
border-top: 1px solid var(--line);
|
| 143 |
padding: 10px 12px 12px 66px;
|
| 144 |
-
background: #fff7ed;
|
| 145 |
}
|
| 146 |
|
| 147 |
.finding.critical {
|
| 148 |
-
background: #fff1f2;
|
| 149 |
}
|
| 150 |
|
| 151 |
.finding.nitpick {
|
| 152 |
-
background: #f8fafc;
|
| 153 |
}
|
| 154 |
|
| 155 |
.badge {
|
|
@@ -174,20 +181,20 @@ CSS = """
|
|
| 174 |
}
|
| 175 |
|
| 176 |
.finding-body {
|
| 177 |
-
color:
|
| 178 |
margin-top: 6px;
|
| 179 |
}
|
| 180 |
|
| 181 |
.suggestion {
|
| 182 |
-
color: #334155;
|
| 183 |
margin-top: 5px;
|
| 184 |
}
|
| 185 |
|
| 186 |
.empty-state {
|
| 187 |
-
background:
|
| 188 |
border: 1px dashed var(--line);
|
| 189 |
border-radius: 8px;
|
| 190 |
-
color:
|
| 191 |
padding: 18px;
|
| 192 |
}
|
| 193 |
|
|
@@ -519,11 +526,15 @@ def summarize_with_model(
|
|
| 519 |
hf_token: gr.OAuthToken | None = None,
|
| 520 |
) -> str:
|
| 521 |
if not enabled:
|
| 522 |
-
return
|
| 523 |
|
| 524 |
token = hf_token.token if hf_token else os.getenv("HF_TOKEN")
|
| 525 |
if not token:
|
| 526 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
| 527 |
|
| 528 |
compact_diff = "\n".join(
|
| 529 |
f"{file.path}\n"
|
|
@@ -566,7 +577,33 @@ def summarize_with_model(
|
|
| 566 |
)
|
| 567 |
return response.choices[0].message.content or "Model returned an empty summary."
|
| 568 |
except Exception as exc: # The app must stay demoable when endpoints are unavailable.
|
| 569 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 570 |
|
| 571 |
|
| 572 |
def finding_to_dict(finding: Finding) -> dict[str, Any]:
|
|
|
|
| 64 |
}
|
| 65 |
|
| 66 |
.score-card {
|
| 67 |
+
background: #ffffff !important;
|
| 68 |
border: 1px solid var(--line);
|
| 69 |
border-radius: 8px;
|
| 70 |
padding: 12px;
|
| 71 |
}
|
| 72 |
|
| 73 |
.score-label {
|
| 74 |
+
color: #475569 !important;
|
| 75 |
font-size: 12px;
|
| 76 |
text-transform: uppercase;
|
| 77 |
}
|
| 78 |
|
| 79 |
.score-value {
|
| 80 |
+
color: #111827 !important;
|
| 81 |
font-size: 24px;
|
| 82 |
font-weight: 700;
|
| 83 |
margin-top: 2px;
|
| 84 |
}
|
| 85 |
|
| 86 |
.diff-wrap {
|
| 87 |
+
background: #ffffff !important;
|
| 88 |
border: 1px solid var(--line);
|
| 89 |
border-radius: 8px;
|
| 90 |
overflow: hidden;
|
|
|
|
| 123 |
}
|
| 124 |
|
| 125 |
.line-code {
|
| 126 |
+
background: #ffffff;
|
| 127 |
+
color: #111827;
|
| 128 |
white-space: pre-wrap;
|
| 129 |
overflow-wrap: anywhere;
|
| 130 |
padding: 3px 10px;
|
| 131 |
}
|
| 132 |
|
| 133 |
+
.line.ctx .line-code {
|
| 134 |
+
background: #ffffff !important;
|
| 135 |
+
color: #334155 !important;
|
| 136 |
+
}
|
| 137 |
+
|
| 138 |
.line.add .line-code {
|
| 139 |
+
background: var(--add-bg) !important;
|
| 140 |
+
color: var(--add-ink) !important;
|
| 141 |
}
|
| 142 |
|
| 143 |
.line.del .line-code {
|
| 144 |
+
background: var(--del-bg) !important;
|
| 145 |
+
color: var(--del-ink) !important;
|
| 146 |
}
|
| 147 |
|
| 148 |
.finding {
|
| 149 |
border-top: 1px solid var(--line);
|
| 150 |
padding: 10px 12px 12px 66px;
|
| 151 |
+
background: #fff7ed !important;
|
| 152 |
}
|
| 153 |
|
| 154 |
.finding.critical {
|
| 155 |
+
background: #fff1f2 !important;
|
| 156 |
}
|
| 157 |
|
| 158 |
.finding.nitpick {
|
| 159 |
+
background: #f8fafc !important;
|
| 160 |
}
|
| 161 |
|
| 162 |
.badge {
|
|
|
|
| 181 |
}
|
| 182 |
|
| 183 |
.finding-body {
|
| 184 |
+
color: #111827 !important;
|
| 185 |
margin-top: 6px;
|
| 186 |
}
|
| 187 |
|
| 188 |
.suggestion {
|
| 189 |
+
color: #334155 !important;
|
| 190 |
margin-top: 5px;
|
| 191 |
}
|
| 192 |
|
| 193 |
.empty-state {
|
| 194 |
+
background: #ffffff !important;
|
| 195 |
border: 1px dashed var(--line);
|
| 196 |
border-radius: 8px;
|
| 197 |
+
color: #475569 !important;
|
| 198 |
padding: 18px;
|
| 199 |
}
|
| 200 |
|
|
|
|
| 526 |
hf_token: gr.OAuthToken | None = None,
|
| 527 |
) -> str:
|
| 528 |
if not enabled:
|
| 529 |
+
return summarize_deterministic(files, findings, prefix="Deterministic review complete.")
|
| 530 |
|
| 531 |
token = hf_token.token if hf_token else os.getenv("HF_TOKEN")
|
| 532 |
if not token:
|
| 533 |
+
return summarize_deterministic(
|
| 534 |
+
files,
|
| 535 |
+
findings,
|
| 536 |
+
prefix="Mellum summary needs Hugging Face OAuth or HF_TOKEN; showing deterministic summary.",
|
| 537 |
+
)
|
| 538 |
|
| 539 |
compact_diff = "\n".join(
|
| 540 |
f"{file.path}\n"
|
|
|
|
| 577 |
)
|
| 578 |
return response.choices[0].message.content or "Model returned an empty summary."
|
| 579 |
except Exception as exc: # The app must stay demoable when endpoints are unavailable.
|
| 580 |
+
return summarize_deterministic(
|
| 581 |
+
files,
|
| 582 |
+
findings,
|
| 583 |
+
prefix=f"Model summary unavailable from {DEFAULT_MODEL}: {exc}",
|
| 584 |
+
)
|
| 585 |
+
|
| 586 |
+
|
| 587 |
+
def summarize_deterministic(files: list[FileDiff], findings: list[Finding], prefix: str) -> str:
|
| 588 |
+
hunk_count = sum(len(file.hunks) for file in files)
|
| 589 |
+
counts = {
|
| 590 |
+
"critical": sum(item.severity == "critical" for item in findings),
|
| 591 |
+
"warning": sum(item.severity == "warning" for item in findings),
|
| 592 |
+
"nitpick": sum(item.severity == "nitpick" for item in findings),
|
| 593 |
+
}
|
| 594 |
+
top_findings = findings[:3]
|
| 595 |
+
bullets = [
|
| 596 |
+
f"- Reviewed {len(files)} files and {hunk_count} hunks.",
|
| 597 |
+
f"- Found {counts['critical']} critical, {counts['warning']} warning, and {counts['nitpick']} nitpick findings.",
|
| 598 |
+
]
|
| 599 |
+
for finding in top_findings:
|
| 600 |
+
location = f"{finding.file}:{finding.line}" if finding.line else finding.file
|
| 601 |
+
bullets.append(f"- {finding.severity.title()} in `{location}`: {finding.comment}")
|
| 602 |
+
|
| 603 |
+
if not findings:
|
| 604 |
+
bullets.append("- No high-signal risks matched the current deterministic rules.")
|
| 605 |
+
|
| 606 |
+
return prefix + "\n\n" + "\n".join(bullets)
|
| 607 |
|
| 608 |
|
| 609 |
def finding_to_dict(finding: Finding) -> dict[str, Any]:
|