[BUG]: 修改 Prompt 後點擊「查看歷史記錄」出現「加载历史记录失败」
🐛 Bug description [Please make everyone to understand it]
在「設定 → Prompts」頁面中,使用者修改並保存 Prompts 後,立即點擊「查看歷史記錄」按鈕,前端會顯示錯誤 toast:
加载历史记录失败
此錯誤訊息無法讓使用者理解實際原因,且在 Debug 模式先前已啟用的情況下仍會發生,導致無法確認是:
- Debug 模式狀態問題
還是 - 歷史檔案讀取 / 權限 / 其他後端錯誤
目前此問題可重現,行為不符合預期。
目前行為(Actual Behavior)
-
使用者在設定頁面編輯任一 Prompt 類別內容。
-
點擊「保存」按鈕,前端呼叫
POST /api/settings/prompts。 -
保存成功(顯示「Prompts保存成功」)。
-
使用者在同一頁面點擊「查看歷史記錄」。
-
前端呼叫
GET /api/settings/prompts/history/{category}。 -
前端顯示 toast:
加载历史记录失败
-
Console 目前只看得到籠統錯誤訊息,無明確 HTTP 狀態碼與後端錯誤原因說明。
🧑💻 Step to reproduce
在目前行為發生的前提下,重現路徑如下:
- 確認系統已啟動並可透過瀏覽器進入設定頁面。
- 在「Prompts 設定」頁,選擇任一 Prompt 分類(例如:
content_generation下的某個子項)。 - 修改該 Prompt 內容。
- 點擊「保存」:
- 前端會呼叫
POST /api/settings/prompts。
- 前端會呼叫
- 不重新整理頁面,直接點擊該分類的「查看歷史記錄」按鈕:
- 前端呼叫
GET /api/settings/prompts/history/{category}。
- 前端呼叫
- 觀察:
- 預期:彈出歷史記錄 modal 並顯示歷史列表。
- 實際:顯示 toast「加载历史记录失败」且歷史列表載入失敗。
👾 Expected result
- 在 Debug 模式已啟用且歷史檔案存在 的前提下:
- 點擊「查看歷史記錄」應成功列出歷史版本清單。
- 若無法讀取歷史記錄,前端應顯示具體原因,例如:
- Debug 模式未啟用
- 該分類尚無歷史記錄
- 伺服器錯誤(含 HTTP 狀態碼與簡短說明)
而不是一律只顯示「加载历史记录失败」。
🚑 Any additional information
相關程式碼位置(目前已查閱部分)
前端:opencontext/web/static/js/settings.js
-
全域狀態
let currentPrompts = {}; -
載入 Prompts 並設定
currentPrompts// loadPromptsToCategories(...) 內部邏輯(節錄) if (promptsData.code === 0 && promptsData.data) { const rawPrompts = promptsData.data.prompts || promptsData.data; currentPrompts = rawPrompts; // 後續依照 PROMPT_CATEGORIES.path 讀取對應的 prompt }目前觀察:
currentPrompts可能包含除了純粹 prompt 文本以外的其他設定欄位(例如content_generation、模型設定等),這些欄位的來源與職責邊界尚未完全釐清。 -
保存 Prompts
async function savePrompts() { try { const response = await fetch('/api/settings/prompts', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ prompts: currentPrompts }) }); const data = await response.json(); // ... } catch (e) { // ... } }這裡會直接將整個
currentPrompts物件送往/api/settings/prompts。 -
查看歷史記錄
async function viewHistory(category) { currentCategory = category; selectedHistoryFile = null; try { const response = await fetch(`/api/settings/prompts/history/${category}`); const data = await response.json(); if (data.code === 0 && data.data) { // 渲染歷史列表 } else { showToast('加载历史记录失败', true); } } catch (error) { console.error('加载历史记录失败:', error); showToast('加载历史记录失败', true); } }目前錯誤處理只顯示統一的錯誤訊息,並未把錯誤原因(例如 debug 未啟用、權限、檔案問題)反映給使用者。
後端:opencontext/server/routes/settings.py
-
Prompts 相關 API
POST /api/settings/prompts會呼叫prompt_mgr.save_prompts(request.prompts)。GET /api/settings/prompts/history/{category}會在某處檢查 Debug 模式是否啟用:debug_config = config.get("content_generation", {}).get("debug", {}) # 若 debug_config 未啟用,會拒絕讀取歷史(實際邏輯與錯誤訊息需再確認)
上述顯示:歷史記錄的開放條件與
content_generation.debug設定有關。
後端:opencontext/config/prompt_manager.py
-
Prompts 儲存
class PromptManager: def save_prompts(self, prompts_data: dict) -> bool: # ... with open(user_prompts_path, "w", encoding="utf-8") as f: yaml.dump( prompts_data, f, Dumper=LiteralDumper, default_flow_style=False, allow_unicode=True, ) # 更新記憶中的 prompts self.prompts = self._deep_merge(self.prompts, prompts_data) return True目前行為:
整個prompts_data會原封不動寫入user_prompts_{lang}.yaml,沒有過濾非 prompt 類的鍵值。
後端:opencontext/config/config_manager.py
-
一般設定(含
content_generation.debug)儲存class ConfigManager: def save_user_settings(self, settings: dict) -> None: if "content_generation" in settings: user_settings["content_generation"] = settings["content_generation"] # 寫入 user_setting.yaml這裡說明:
content_generation.debug真正的生效來源是user_setting.yaml,由/api/settings/general管理,並非由PromptManager.save_prompts管理。
目前推論的可能問題點(尚未完全證實)
以下為基於程式架構與行為的「合理懷疑」,尚未以實際 HTTP 回應與 server logs 完全驗證,需要開發團隊協助確認。
-
前端狀態混用
currentPrompts作為全域物件,被多個函數共用(載入、保存、可能還包括 debug 相關操作)。currentPrompts可能不僅包含「純 prompts」,也包含content_generation等與 general settings 有關的欄位。
-
API 職責邊界不清
POST /api/settings/prompts在目前實作下,可能被送入含有非 prompt 類欄位的 payload。- 後端
PromptManager.save_prompts()會將整個物件寫入user_prompts_{lang}.yaml,造成「prompts 檔案中參雜 general 設定欄位」的情況。
-
Debug 設定與歷史 API 的耦合
/api/settings/prompts/history/{category}會根據config.get("content_generation").get("debug")判斷是否允許讀取歷史。- 若 debug 狀態與前端或 prompts 檔案的內容出現不一致,可能導致歷史 API 拒絕服務,進而觸發「加载历史记录失败」錯誤。
-
錯誤訊息被前端遮蔽
- 即便後端有返回明確錯誤原因,前端目前一律只顯示「加载历史记录失败」,導致實際 root cause 隱藏在 Network / logs 中。
建議修復方向(Proposal)
1. 前端:明確區分 prompts 與 general 設定
-
在
savePrompts()中,只送出「真正屬於 prompts 的資料」:-
具體作法可以是:
- 在組裝 payload 前,
deep clone一份currentPrompts,移除所有非 prompt 類的頂層 key,例如:content_generationvlm_modelembedding_model- 其他屬於 general/config 的欄位
- 在組裝 payload 前,
-
目標:確保
/api/settings/prompts的 payload 只包含「Prompts 設定」,不含 general/debug 相關配置。
-
-
在
loadPromptsToCategories()中:- 對從
/api/settings/prompts取得的資料做一次淨化(只保留與 prompt 類別相關的內容),避免currentPrompts被混入不應該存在的 general 設定。
- 對從
2. 後端:PromptManager.save_prompts 增加防禦性驗證
-
在實際寫入
user_prompts_{lang}.yaml前,過濾掉不應由 PromptManager 管理的頂層欄位,例如:content_generationvlm_modelembedding_modelcaptureprocessinglogging等
-
保留一份 log,記錄被移除的 key 以利後續追蹤:
- 例如:
Removed non-prompt configuration 'content_generation' from prompts data
- 例如:
-
這樣可以避免 prompts 檔案成為各種設定的「垃圾桶」,也降低將來 schema 演進時的風險。
3. 歷史 API:錯誤訊息與狀態碼的清楚定義
-
建議針對不同錯誤情境給固定的 code / message,例如:
- Debug 未啟用:
HTTP 400或403,code: X001,message: "Debug mode is not enabled"
- 沒有歷史記錄:
HTTP 200,code: 0,data: []
- 檔案讀取錯誤:
HTTP 500,code: X002,message: "Failed to load prompt history"
- Debug 未啟用:
-
這樣前端可以根據
data.code與HTTP status顯示更有意義的提示,而不只是統一的「加载历史记录失败」。
4. 前端錯誤提示改善(與後端錯誤碼配合)
-
在
viewHistory()中:- 讀取
response.status、data.code、data.message,對於已知錯誤情境給出具體提示,例如:- Debug 未啟用:提示「Debug 模式未啟用,請到系統設定中開啟 Debug 後再嘗試查看歷史記錄」。
- 其他錯誤:顯示簡短錯誤描述,並在 Console 中輸出完整錯誤資訊以供開發人員除錯。
- 讀取
🛠️ MineContext Version
0.1.5
💻 Platform Details
MacOS