diff --git a/cmd/arcrun-app/.version-source.json b/cmd/arcrun-app/.version-source.json index 1acf739..f4fd0bb 100644 --- a/cmd/arcrun-app/.version-source.json +++ b/cmd/arcrun-app/.version-source.json @@ -6,5 +6,6 @@ "v0.18.13": "fbf7342d0d0e27b4", "v0.18.14": "bfcb4f2701fc23b4", "v0.18.15": "447b59ea3ade430e", - "v0.18.16": "12de01a21cd6bf38" + "v0.18.16": "12de01a21cd6bf38", + "v0.18.17": "c13b08dec6a0fbef" } diff --git a/cmd/arcrun-app/app.go b/cmd/arcrun-app/app.go index 041c048..5ad0564 100644 --- a/cmd/arcrun-app/app.go +++ b/cmd/arcrun-app/app.go @@ -75,9 +75,17 @@ type directConfig struct { // syncStatus 對映 collector 寫的 status.json(只取 UI 要的欄位)。 type syncStatus struct { - LastSync string `json:"last_sync,omitempty"` - ExtractedOK int `json:"extracted_ok"` - ExtractFailed int `json:"extract_failed"` + LastSync string `json:"last_sync,omitempty"` + ExtractedOK int `json:"extracted_ok"` + ExtractFailed int `json:"extract_failed"` + // 🔴 2026-08-06:collector 早就把「哪個檔失敗、為什麼」寫進 status.json 了 + // (sync_status.go 的 Failures),但 App 一直只讀計數 ⇒ 畫面只會說「⚠ 3 份失敗」, + // 使用者與遠端的我都不知道是哪一份、什麼原因。**今天第四次同款病** + // (前三次:exit status 2 蓋掉真話/非文件檔不點名/誤判沒連線)。 + Failures []struct { + Path string `json:"path"` + Error string `json:"error"` + } `json:"failures"` ExtractorOK bool `json:"extractor_ok"` ExtractorError string `json:"extractor_error,omitempty"` // 「上次真的有做事」那一輪(2026-08-05)——ExtractedOK 是本輪計數、會被下一輪歸零, @@ -228,8 +236,9 @@ type UIState struct { Skipped *UISkipped `json:"skipped"` // 讀不了的檔(沒有就是 null,前端不畫) // EngineTrouble=同步引擎有問題(沒在跑/一直啟動失敗)⇒ 前端才長出「回報問題」卡。 // 沒事時不顯示,避免把「哪裡看 log」變成常駐噪音。 - EngineTrouble bool `json:"engineTrouble"` - LogFolder string `json:"logFolder"` + EngineTrouble bool `json:"engineTrouble"` + Failures *UIFailures `json:"failures"` // 沒有就是 null,前端不畫 + LogFolder string `json:"logFolder"` } // UISkipped=首頁那張「這些檔案現在還處理不了」的卡。 @@ -249,6 +258,47 @@ type UISkipped struct { Other string `json:"other"` // 非文件檔的一行說明(沒有就空字串) } +// UIFailures=首頁那張「有幾份沒送上去」的卡。 +// +// 🔴 存在理由(leo 2026-08-06 實測):畫面寫「⚠ 3 份失敗」但**不說是哪一份、為什麼** +// ⇒ leo 只能回報「新的兩個檔案確實沒推到雲端」,我只能猜。 +// 而原因**本來就在 status.json 裡**,只是沒人拿出來用。 +type UIFailures struct { + Title string `json:"title"` + Note string `json:"note"` + Items []UIFailItem `json:"items"` + More int `json:"more"` +} + +type UIFailItem struct { + Name string `json:"name"` + Reason string `json:"reason"` +} + +// maxFailShown=最多列幾份(多了會洗版;總數仍照實講)。 +const maxFailShown = 8 + +func buildFailures(s syncStatus) *UIFailures { + if len(s.Failures) == 0 { + return nil + } + u := &UIFailures{ + Title: fmt.Sprintf("有 %d 份沒有送進知識庫", len(s.Failures)), + Note: "下面是失敗的檔案與原因。這些檔案會自動重試,你不用重丟;如果一直失敗,把這段回報給我們。", + } + for i, f := range s.Failures { + if i >= maxFailShown { + u.More = len(s.Failures) - maxFailShown + break + } + u.Items = append(u.Items, UIFailItem{ + Name: filepath.Base(f.Path), + Reason: f.Error, + }) + } + return u +} + // buildSkipped 把 status.json 的三個欄位翻成首頁看得懂的一張卡。 // 完全沒有東西被略過時回 nil ⇒ 前端不畫這張卡(沒事就別佔畫面)。 func buildSkipped(s syncStatus) *UISkipped { @@ -377,6 +427,7 @@ func (a *App) GetState() UIState { st.Syncing, st.StatusBig, st.StatusSub = describeStatus(sync) st.Steps = buildSteps(sync, st.Syncing) st.Skipped = buildSkipped(sync) + st.Failures = buildFailures(sync) // 引擎有問題才把「回報問題」卡叫出來(含記錄檔路徑)。 // 沒事時不顯示——否則「哪裡看 log」會變成常駐噪音,真出事時反而沒人看。 st.EngineTrouble = !collectorAlive() diff --git a/cmd/arcrun-app/frontend/src/main.js b/cmd/arcrun-app/frontend/src/main.js index 36d6da5..a5448c0 100644 --- a/cmd/arcrun-app/frontend/src/main.js +++ b/cmd/arcrun-app/frontend/src/main.js @@ -72,6 +72,8 @@ function pageHome(s) { `).join('')} + ${cardTrouble(s)} + ${cardFailures(s.failures)} ${cardSkipped(s.skipped)}

總計

@@ -89,6 +91,42 @@ function pageHome(s) { // 使用者只能得到「我丟了檔,然後什麼都沒發生」這個結論。 // 這張卡就是那句話該出現的地方——**首頁**,他每次打開 App 一定會看到。 // 沒有東西被略過時後端回 null ⇒ 這裡回空字串,畫面保持乾淨(沒事不佔版面)。 +// 引擎有問題時才長出來:一鍵打開紀錄檔資料夾。 +// leo 2026-08-06:「不能用一個 debug mode?」——log 一直都在寫,缺的是入口。 +function cardTrouble(s) { + if (!s.engineTrouble) return ''; + return ` +
+

需要回報這個問題?

+
+ 詳細的錯誤紀錄已經自動存在你電腦裡,不必開啟任何設定。
+ 把 collector.logapp.log 傳給我們就能查。 +
+
${esc(s.logFolder || '')}
+
+
`; +} + +// 失敗的檔案:列出**檔名與原因**。 +// leo 2026-08-06 實測:畫面只寫「⚠ 3 份失敗」,他只能回報「沒推到雲端」, +// 而原因本來就在 status.json 裡 —— 數字不能代替原因。 +function cardFailures(f) { + if (!f || !f.items || !f.items.length) return ''; + return ` +
+

${esc(f.title)}

+
${esc(f.note)}
+
+ ${f.items.map((it) => ` +
+ ${esc(it.name)} + ${esc(it.reason)} +
`).join('')} +
+ ${f.more > 0 ? `
…還有 ${f.more} 份
` : ''} +
`; +} + function cardSkipped(k) { if (!k) return ''; return ` @@ -214,6 +252,7 @@ function wire() { const on = (id, fn) => { const e = $(id); if (e) e.onclick = fn; }; on('uDocs', () => go.OpenURL('https://rag.arcrun.dev/docs/')); on('hLogs', () => go.OpenLogFolder()); + on('hLogs', () => go.OpenLogFolder()); on('hAcct', showConnect); on('obConnect', showConnect); on('obInstall', () => go.OpenURL('https://install.arcrun.dev/')); on('aiSave', saveAI);