v0.18.18:失敗原因真的顯示在畫面上(前面幾版只做了一半)

## 補完「上游錯誤要看得到」這條線
- 退避中的檔案也進 `status.failures`(先前退避期間該欄是空的
  ⇒ 畫面只有「⚠ N 份失敗」沒有原因,等於前面白做)
- `shortError` 從 120 放寬到 240 字:真因在訊息**後半段**,砍 120 會整段切掉

## 實測輸出(不是推測,是印出來的卡片內容)
  有 2 份沒有送進知識庫
   · 2021超新星品牌白皮書-科特勒.pdf
     今天的免費 AI 額度用完了 ⇒ 明天會自動恢復,這些檔案會自己補上,你不用做什麼。
   · 台灣青年創新創業協會謝侑霖.pdf
     這份 PDF 看起來是掃描的圖片 ⇒ 需要先做文字辨識(OCR),或換一份有文字的版本。
⇒ 同樣是「失敗」,處置完全相反(等就好/要動手),使用者現在分得出來。
(測試資料取自 leo Windows collector.log 的原文。)
This commit is contained in:
2026-08-06 21:41:28 +08:00
parent c7675a10a0
commit 857420dfa7
2 changed files with 24 additions and 3 deletions
+2 -1
View File
@@ -1,4 +1,5 @@
{
"_algo": 2,
"v0.18.17": "cb6e53a052b87482"
"v0.18.17": "cb6e53a052b87482",
"v0.18.18": "a495451d9d9da78a"
}
+22 -2
View File
@@ -685,6 +685,17 @@ func RunDirectOnce(cfg *DirectConfig, dryRun bool) ([]DirectResult, int, *Trigge
Path: r.Path,
Error: shortError(r.Error),
})
case "skipped":
// 🔴 leo 2026-08-06:退避期間這個檔**不會**再產生 "failed"
// 於是 status.failures 是空的 ⇒ 畫面只剩「⚠ N 份失敗」沒有原因。
// 退避訊息裡已經帶了上游真因(retrySkipReason),一併收進來,
// 使用者才看得到「為什麼」而不只是「幾份」。
if strings.Contains(r.Error, "後重試") || strings.Contains(r.Error, "已暫停自動重試") {
st.Failures = append(st.Failures, ExtractFail{
Path: r.Path,
Error: shortError(r.Error),
})
}
}
}
}
@@ -711,12 +722,21 @@ func RunDirectOnce(cfg *DirectConfig, dryRun bool) ([]DirectResult, int, *Trigge
}
// shortError 把錯誤字串截為一句話(供 UI 顯示,不要超過 120 字)。
// shortError 限制錯誤訊息長度。
//
// 🔴 2026-08-06 放寬到 240:訊息現在會**帶上游真因**
//
// (「上次失敗(第 4 次),58m 後重試|原因:…Workers AI…4006: you have used up
// your daily free allocation of 10,000 neurons…」),
// 而真因在**後半段**——砍 120 會把它整段切掉,等於又回到「只說失敗不說原因」。
// (leo 原則:別人的錯誤一律要顯示給用戶看。)
func shortError(msg string) string {
if len([]rune(msg)) <= 120 {
const max = 240
if len([]rune(msg)) <= max {
return msg
}
runes := []rune(msg)
return string(runes[:120]) + "…"
return string(runes[:max]) + "…"
}
// CheckExtractor 預檢萃取器是否可用(不執行萃取、不打 API)。