feat(collector): 結構先行——掃描完幾秒內就能問「資料夾裡有什麼」,不等 LLM 不等額度(InkStoneCo#43)

leo 08-15 量測:266 檔真正算的 ~20 分鐘/<$0.5,使用者卻等 ~4 天(多在等
Workers AI 每日額度);而「有哪些檔案/最近改了什麼」本地掃一遍就有答案
(1,335 檔實測 0.254s),卻因 part_of 只在雲端 parse_card(萃取之後)生成
而排同一條隊、撞同一面額度牆。

- collector/inventory.go:Scan() 後、萃取迴圈前(額度冷卻閘之外),把 manifest
  現況做成機械總覽卡(檔案清單/最近改動/目錄 part_of)POST 既有 rag_ingest_card
  ——零 LLM、零新 workflow、既有實例直接受益;自帶同頁名 upsert 防重複
- 冪等:內容 sha256 記 manifest.inventory_hash;失敗 10 分鐘退避(防 t195 同款
  每 5 秒重撞);額度失敗訊息人話化,不裸露 4006/502
- 清單 ≤200 逐檔、關聯 ≤10 條:守 Workers 免費層 50 subrequests 天花板
- 不寫本機檔案、不動使用者原稿

實測(youlin stage yuga3bse,刻意無金鑰=零萃取):總覽卡 200 送達、rag_chat
正確回答「有哪些檔案/最近改了什麼」;重掃不重複(blocks 恆 5、triplets 恆 2);
go test collector+supervisor+arcrun-app 全綠(新增 inventory_test.go 6 案)。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-15 16:39:45 +08:00
parent 35b113f147
commit f233eec9c2
9 changed files with 662 additions and 37 deletions
+13 -5
View File
@@ -182,18 +182,24 @@ func TestDirect_LargeBacklog_ProcessedInNewestFirstBatches(t *testing.T) {
t.Error("全部處理完不該再有延後交代")
}
// 全部 8 個都真的送到雲端了(沒有一個被永久漏掉)
// 全部 8 個都真的送到雲端了(沒有一個被永久漏掉);總覽卡(結構先行)另計
mu.Lock()
defer mu.Unlock()
if len(order) != 8 {
t.Fatalf("雲端總共應收到 8 次卡片,got %d: %v", len(order), order)
var contentCards []string
for _, pn := range order {
if !strings.HasPrefix(pn, "資料夾總覽") {
contentCards = append(contentCards, pn)
}
}
if len(contentCards) != 8 {
t.Fatalf("雲端總共應收到 8 次卡片,got %d: %v", len(contentCards), order)
}
}
func ingestedPaths(results []DirectResult) []string {
var out []string
for _, r := range results {
if r.Status == "ingested" {
if r.Status == "ingested" && r.Type != "inventory" { // 結構先行:總覽卡另計
out = append(out, r.Path)
}
}
@@ -228,7 +234,9 @@ func TestDirect_ResumeAfterInterruption(t *testing.T) {
var m map[string]any
_ = json.Unmarshal(body, &m)
mu.Lock()
posted = append(posted, m["path"].(string))
if p, _ := m["path"].(string); !strings.HasPrefix(p, ".arcrun-rag/") {
posted = append(posted, p) // 結構先行:總覽卡(合成路徑)另計
}
mu.Unlock()
_ = json.NewEncoder(w).Encode(map[string]any{"success": true})
}))