Fix gutter repair: detect short fragments + show spell alternatives
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 48s
CI / test-go-edu-search (push) Successful in 49s
CI / test-python-klausur (push) Failing after 2m37s
CI / test-python-agent-core (push) Successful in 35s
CI / test-nodejs-website (push) Successful in 35s
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 48s
CI / test-go-edu-search (push) Successful in 49s
CI / test-python-klausur (push) Failing after 2m37s
CI / test-python-agent-core (push) Successful in 35s
CI / test-nodejs-website (push) Successful in 35s
- Lower min word length from 3→2 for hyphen-join candidates so fragments like "ve" (from "ver-künden") are no longer skipped - Return all spellchecker candidates instead of just top-1, so user can pick the correct form (e.g. "stammeln" vs "stammelt") - Frontend shows clickable alternative buttons for spell_fix suggestions - Backend accepts text_overrides in apply endpoint for user-selected alternatives Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,7 @@ interface GutterSuggestion {
|
||||
next_row_text: string
|
||||
missing_chars: string
|
||||
display_parts: string[]
|
||||
alternatives: string[]
|
||||
confidence: number
|
||||
reason: string
|
||||
}
|
||||
@@ -50,6 +51,7 @@ export function StepGutterRepair({ sessionId, onNext }: StepGutterRepairProps) {
|
||||
const [result, setResult] = useState<GutterRepairResult | null>(null)
|
||||
const [accepted, setAccepted] = useState<Set<string>>(new Set())
|
||||
const [rejected, setRejected] = useState<Set<string>>(new Set())
|
||||
const [selectedText, setSelectedText] = useState<Record<string, string>>({})
|
||||
const [applied, setApplied] = useState(false)
|
||||
const [error, setError] = useState('')
|
||||
const [applyMessage, setApplyMessage] = useState('')
|
||||
@@ -128,7 +130,10 @@ export function StepGutterRepair({ sessionId, onNext }: StepGutterRepairProps) {
|
||||
{
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ accepted: Array.from(accepted) }),
|
||||
body: JSON.stringify({
|
||||
accepted: Array.from(accepted),
|
||||
text_overrides: selectedText,
|
||||
}),
|
||||
},
|
||||
)
|
||||
if (!res.ok) {
|
||||
@@ -304,14 +309,38 @@ export function StepGutterRepair({ sessionId, onNext }: StepGutterRepairProps) {
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center gap-2 text-sm">
|
||||
<span className="font-mono text-red-600 dark:text-red-400 line-through">
|
||||
{s.original_text}
|
||||
</span>
|
||||
<span className="text-gray-400">→</span>
|
||||
<span className="font-mono text-green-600 dark:text-green-400 font-semibold">
|
||||
{s.suggested_text}
|
||||
</span>
|
||||
<div className="space-y-1">
|
||||
<div className="flex items-center gap-2 text-sm">
|
||||
<span className="font-mono text-red-600 dark:text-red-400 line-through">
|
||||
{s.original_text}
|
||||
</span>
|
||||
<span className="text-gray-400">→</span>
|
||||
<span className="font-mono text-green-600 dark:text-green-400 font-semibold">
|
||||
{selectedText[s.id] || s.suggested_text}
|
||||
</span>
|
||||
</div>
|
||||
{/* Alternatives: show other candidates the user can pick */}
|
||||
{s.alternatives && s.alternatives.length > 0 && !applied && (
|
||||
<div className="flex items-center gap-1.5 flex-wrap">
|
||||
<span className="text-[10px] text-gray-400">Alternativen:</span>
|
||||
{[s.suggested_text, ...s.alternatives].map((alt) => {
|
||||
const isSelected = (selectedText[s.id] || s.suggested_text) === alt
|
||||
return (
|
||||
<button
|
||||
key={alt}
|
||||
onClick={() => setSelectedText(prev => ({ ...prev, [s.id]: alt }))}
|
||||
className={`px-1.5 py-0.5 text-[11px] font-mono rounded transition-colors ${
|
||||
isSelected
|
||||
? 'bg-green-200 dark:bg-green-800 text-green-800 dark:text-green-200 font-semibold'
|
||||
: 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600'
|
||||
}`}
|
||||
>
|
||||
{alt}
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user