6c9d74d588
leo 07-28 實測根因:Finder 起的 GUI app 只有最小 PATH(無 /opt/homebrew/bin) → claude 靜默找不到→整輪萃取失敗,托盤卻顯示「看守中」。leo:「我怎麼知道它有萃?」 - FindClaudeBin:LookPath 失敗後掃 4 個常見絕對路徑,找到回寫 config claude_bin - CheckExtractor 預檢+每輪寫 ~/.arcrun-rag/status.json(ok/fail 計數+失敗清單) - 托盤:引擎未就緒→「⚠ 萃取引擎未就緒:<白話原因>」;失敗>0→可點開明細;正常→「已萃 N 檔」 測試:collector+supervisor+tray 三模組 go test 全綠(總管親跑)。 (實作=子 CC;驗證+commit=總管)
52 lines
2.0 KiB
Go
52 lines
2.0 KiB
Go
// sync_status.go — 每輪同步後的彙總狀態(t91 狀態可見性)。
|
|
// 寫成 JSON 供托盤讀取,讓使用者第一眼看到萃取是否正常。
|
|
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
)
|
|
|
|
// SyncStatus 彙總每輪同步的萃取結果,持久化至 ~/.arcrun-rag/status.json。
|
|
// 托盤依此決定顯示「已萃 N 檔」、「⚠ 萃取失敗 M 檔」還是「⚠ 萃取引擎未就緒」。
|
|
type SyncStatus struct {
|
|
LastSync string `json:"last_sync,omitempty"` // RFC3339,最近一輪完成時間
|
|
ExtractedOK int `json:"extracted_ok"` // 本輪萃取成功件數(跨資料夾累計)
|
|
ExtractFailed int `json:"extract_failed"` // 本輪萃取失敗件數
|
|
Failures []ExtractFail `json:"failures,omitempty"` // 失敗清單(路徑+白話原因)
|
|
ExtractorOK bool `json:"extractor_ok"` // 萃取器本身是否就緒(預檢)
|
|
ExtractorError string `json:"extractor_error,omitempty"` // 未就緒的白話原因
|
|
}
|
|
|
|
// ExtractFail 記一筆萃取失敗(路徑+白話原因)。
|
|
type ExtractFail struct {
|
|
Path string `json:"path"`
|
|
Error string `json:"error"`
|
|
}
|
|
|
|
// StatusFilePath 回傳狀態檔路徑:與 manifest 同目錄的 status.json。
|
|
func StatusFilePath(manifestPath string) string {
|
|
return filepath.Join(filepath.Dir(manifestPath), "status.json")
|
|
}
|
|
|
|
// SaveSyncStatus 寫入(覆蓋)狀態檔。失敗只印 stderr,不擋看守本體。
|
|
func SaveSyncStatus(path string, s SyncStatus) error {
|
|
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
|
return err
|
|
}
|
|
data, _ := json.MarshalIndent(s, "", " ")
|
|
return os.WriteFile(path, data, 0o644)
|
|
}
|
|
|
|
// LoadSyncStatus 讀取狀態檔;不存在或解析失敗回零值+error(托盤自行降級)。
|
|
func LoadSyncStatus(path string) (SyncStatus, error) {
|
|
var s SyncStatus
|
|
data, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return s, err
|
|
}
|
|
err = json.Unmarshal(data, &s)
|
|
return s, err
|
|
}
|