portal demo 化四件套:圖譜 workflow 化(#57)+AI 問答+上傳頁+搜尋濾殘影(#46 治標) #61

Merged
Leo merged 4 commits from portal-demo-suite into main 2026-07-17 06:48:04 +00:00
Owner

[總管] 四件套(各一 commit):

  1. 圖譜模式修復(#57):優先 in-process 執行 tenant graph_neighbors workflow(executeWebhookGraph 重用,零 self-fetch);無 workflow 實例 fallback 原 plugin 直連——Mira/leo21c 行為不變。
  2. AI 問答:GET /portal/data/chat in-process 跑 rag_chat+搜尋頁問答面板(答案附出處、點來源帶回搜尋框)。
  3. 上傳頁:POST /portal/data/upload server-side 寫 Gitea docs/PORTAL_UPLOAD_REPO/GITEA/TOKEN 三 bindings 齊全才啟用(未設=404+nav 隱藏,Mira 零影響);檔名消毒+2MB 上限+token 只在 server。
  4. 搜尋濾 deprecated 殘影(#46 上游修好前的 portal 端治標,可整段拔)。

驗收:tsc 綠;vitest 175/176(1 紅為 main 既有 executor 文案斷言,與本 PR 無關);新增純函式單測(filename 消毒/殘影過濾/graph 輸出映射)全綠。總管已逐檔審 diff(XSS/token 隔離/租戶字串零下發/Mira 零影響)。leo 核可 merge(2026-07-17)。

[總管] 四件套(各一 commit): 1. 圖譜模式修復(#57):優先 in-process 執行 tenant `graph_neighbors` workflow(`executeWebhookGraph` 重用,零 self-fetch);無 workflow 實例 fallback 原 plugin 直連——Mira/leo21c 行為不變。 2. AI 問答:`GET /portal/data/chat` in-process 跑 `rag_chat`+搜尋頁問答面板(答案附出處、點來源帶回搜尋框)。 3. 上傳頁:`POST /portal/data/upload` server-side 寫 Gitea `docs/`;`PORTAL_UPLOAD_REPO/GITEA/TOKEN` 三 bindings 齊全才啟用(未設=404+nav 隱藏,Mira 零影響);檔名消毒+2MB 上限+token 只在 server。 4. 搜尋濾 deprecated 殘影(#46 上游修好前的 portal 端治標,可整段拔)。 驗收:tsc 綠;vitest 175/176(1 紅為 main 既有 executor 文案斷言,與本 PR 無關);新增純函式單測(filename 消毒/殘影過濾/graph 輸出映射)全綠。總管已逐檔審 diff(XSS/token 隔離/租戶字串零下發/Mira 零影響)。leo 核可 merge(2026-07-17)。
Leo added 4 commits 2026-07-17 06:48:02 +00:00
RAG self-hosted 實例不部署 kbdb-graph-plugin,graphBase 直連必 1042。改為:
WEBHOOKS KV 有 {tenant}:wf:graph_neighbors 時直接 import executeWebhookGraph
(webhooks-named trigger/query 同一執行入口)在本進程執行——絕不 fetch 自己
hostname(self-loop);輸出映射成與 plugin 相同形狀 {neighbors, edges, count}。
沒有該 workflow → fallback 原 graphBase 直連(Mira/leo21c 行為一字不變)。
input:node=path、depth=query(預設 2)、namespace/owner=tenant。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BH7LdhuCdVUHfHXbM7N8r5
端點:requirePortalUser 閘(同 search);in-process 執行 tenant 的 rag_chat
workflow(與 graph_neighbors 同機制),input {question},回 {answer, sources,
graph_facts};workflow 不存在 → 誠實 404「此實例未安裝問答 workflow」。
前端:搜尋框下方問答列,loading→純文字 answer(pre-wrap 保留換行、esc 防
XSS)+sources 列表(mode+page,點 page 帶回搜尋框自行驗證)。設計哲學:
AI 檢索=用戶手動搜尋同一套,AI 只代查再作答,不多開任何權限。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BH7LdhuCdVUHfHXbM7N8r5
server:requirePortalUser 閘;filename 驗證(去路徑分隔、強制 .md、限 100 字);
server-side POST Gitea contents API 到 PORTAL_UPLOAD_REPO 的 docs/{filename}
——token 只在 server,前端零 repo/token 字串。409/422 → 誠實「同名文件已存在」。
新增三個 Bindings:PORTAL_UPLOAD_REPO / PORTAL_UPLOAD_GITEA / PORTAL_UPLOAD_TOKEN
(secret),任一缺 → 404「未啟用上傳」=Mira 零影響(功能不存在,現行為一字不變)。
/portal/session 補 upload_enabled 布林(server 判 bindings 齊全;顯示提示,真閘在路由層)。
前端:上傳 nav(sidenav+tabbar,一般用戶可見、未啟用時隱藏)+檔案選擇(.md/.txt
多選)+拖放區;讀檔轉 b64 逐檔 POST、逐檔狀態列;成功顯示「已收件,約 1 分鐘後
可在搜尋頁找到;AI 整理後會以 wiki 卡形式出現」。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BH7LdhuCdVUHfHXbM7N8r5
/portal/data/search 拿到 KBDB 回應後 server-side 過濾 metadata_json.status=
'deprecated' 與 content 以「(舊管線產物」開頭的 entries(metadata parse 失敗
視為保留,不誤殺),count 重算。這是 Arcrun#46 上游修好前的 portal 端治標,
上游清完資料後整段(含 filterDeprecatedEntries)可拔。
單測:sanitizeUploadFilename(路徑穿越/副檔名/長度)、filterDeprecatedEntries
(濾殘影/壞 metadata 保留)、mapGraphWorkflowOutput(#57 輸出映射);
/portal/session 補 upload_enabled=false 斷言。另修 portal-ui 一處註解字樣
(誤用產品名,撞零 Mira 斷言)。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BH7LdhuCdVUHfHXbM7N8r5
Leo merged commit db0a39fdbd into main 2026-07-17 06:48:04 +00:00
Sign in to join this conversation.