feat: add Java JRXML-to-PNG rendering pipeline with pixel-level SSIM comparison

- lib/java/: Java renderer (JrxmlRenderer) using JasperReports 6.21.0
  - JrxmlDebug for diagnostics, JrxmlGen for format reference
  - download_jars.sh for one-time dependency setup
- agent/nodes.py: _render_jrxml_to_png() and _compute_pixel_similarity()
  - Pixel comparison integrates into validate node (SSIM < 0.4 fails)
  - Pixel fidelity context injected into correct_jrxml for targeted fixes
- tests/test_pixel_comparison.py: 15 unit tests (render, SSIM, integration)
- .gitignore: exclude lib/java/*.jar, lib/java/*.class, tmp/
- CLAUDE.md: v11 changelog documenting the rendering pipeline
- All non-LLM tests pass (97/97)
This commit is contained in:
2026-05-23 15:09:55 +08:00
parent 9de75d2f25
commit bb6cc6e241
16 changed files with 837 additions and 8 deletions
+7 -2
View File
@@ -70,6 +70,7 @@ async function handleSend(text: string, files: File[]) {
jrxml_length: data.jrxml_length,
error_msg: data.error_msg,
natural_explanation: data.natural_explanation,
consult_answer: data.consult_answer,
retry_count: data.retry_count,
total_duration_ms: data.total_duration_ms,
ocr_extraction_result: data.ocr_extraction_result,
@@ -88,8 +89,12 @@ async function handleSend(text: string, files: File[]) {
type: 'error',
})
} else if (data.intent === 'consult_question') {
if (streamContent) {
chat.addMessage({ role: 'assistant', content: streamContent, type: 'consult' })
// 咨询回答:优先用 streamContent,其次用 consult_answer
const answerText = streamContent || data.consult_answer || ''
if (answerText) {
chat.addMessage({ role: 'assistant', content: answerText, type: 'consult' })
} else {
chat.addMessage({ role: 'assistant', content: '咨询已完成,但未获取到回答内容。', type: 'error' })
}
} else {
if (streamContent) {