From 8537f9e5bfd9070f19851360ffa07f5ca6385487 Mon Sep 17 00:00:00 2001 From: EterUltimate <1831303476@qq.com> Date: Tue, 16 Jun 2026 23:25:32 +0800 Subject: [PATCH 1/2] fix: preserve jargon edits in embedded page --- pages/dashboard/app.js | 91 +++++++++++++++---- pages/dashboard/styles.css | 12 +++ .../core_learning/v2_learning_integration.py | 18 +++- services/database/facades/jargon_facade.py | 90 +++++++++++++++--- tests/integration/test_webui_static_assets.py | 5 + tests/unit/test_database_engine.py | 51 +++++++++++ tests/unit/test_provider_registry_rebind.py | 81 ++++++++++++++++- 7 files changed, 314 insertions(+), 34 deletions(-) diff --git a/pages/dashboard/app.js b/pages/dashboard/app.js index b2a089b9..17f6c589 100644 --- a/pages/dashboard/app.js +++ b/pages/dashboard/app.js @@ -408,6 +408,52 @@ else modal.removeAttribute("open"); } + function showConfirm(title, message, confirmText = t("actions.confirm", "确定")) { + return new Promise((resolve) => { + const modal = $("detail-modal"); + if (!modal) { + showToast(message, "error"); + resolve(false); + return; + } + + if (modal.open && typeof modal.close === "function") modal.close(); + const closeButton = $("modal-close"); + let settled = false; + const done = (result) => { + if (settled) return; + settled = true; + modal.removeEventListener("close", onClose); + closeButton?.removeEventListener("click", onCloseClick); + if (typeof modal.close === "function" && modal.open) modal.close(); + else modal.removeAttribute("open"); + resolve(result); + }; + const onClose = () => done(false); + const onCloseClick = () => done(false); + + setText("modal-title", title); + setHtml("modal-body", ` +

${escapeHtml(message)}

+
+ + +
+ `); + $("modal-body")?.querySelector("[data-confirm-cancel]")?.addEventListener("click", () => done(false), { once: true }); + $("modal-body")?.querySelector("[data-confirm-ok]")?.addEventListener("click", () => done(true), { once: true }); + modal.addEventListener("close", onClose, { once: true }); + closeButton?.addEventListener("click", onCloseClick, { once: true }); + if (typeof modal.showModal === "function") { + try { + modal.showModal(); + return; + } catch (_) {} + } + modal.setAttribute("open", ""); + }); + } + function resolvePageFromHash() { const raw = window.location.hash.replace(/^#\/?/, ""); return PAGE_META[raw] ? raw : "home"; @@ -672,25 +718,30 @@ ])); const items = ((data.list || {}).jargon_list || []); pruneSelection(state.selectedJargon, items.map((item) => item.id)); - const html = items.map((item) => ` -
- ${jargonCheckbox(item.id)} -
- ${escapeHtml(item.term || item.content || `#${item.id}`)} - ${escapeHtml(item.meaning || item.definition || t("empty.definition", "暂无释义"))} -
- ${escapeHtml(item.group_id || "global")} - ${pill(item.is_confirmed ? t("jargon.confirmed", "已确认") : t("jargon.pending", "待确认"), item.is_confirmed ? "ok" : "warn")} - ${pill(item.is_global ? t("jargon.global", "全局") : t("jargon.local", "本地"))} -
- ${button(t("actions.edit", "编辑"), `data-jargon-action="edit" data-id="${escapeAttr(item.id)}"`)} + const html = items.map((item) => { + const reviewActions = item.is_confirmed ? "" : ` ${button(t("actions.confirm", "确认"), `data-jargon-action="approve" data-id="${escapeAttr(item.id)}"`)} ${button(t("actions.reject", "驳回"), `data-jargon-action="reject" data-id="${escapeAttr(item.id)}"`)} - ${button(item.is_global ? t("actions.unsetGlobal", "取消全局") : t("actions.setGlobal", "设为全局"), `data-jargon-action="toggle_global" data-id="${escapeAttr(item.id)}"`)} - ${button(t("actions.delete", "删除"), `data-jargon-action="delete" data-id="${escapeAttr(item.id)}"`, "danger-button")} + `; + return ` +
+ ${jargonCheckbox(item.id)} +
+ ${escapeHtml(item.term || item.content || `#${item.id}`)} + ${escapeHtml(item.meaning || item.definition || t("empty.definition", "暂无释义"))} +
+ ${escapeHtml(item.group_id || "global")} + ${pill(item.is_confirmed ? t("jargon.confirmed", "已确认") : t("jargon.pending", "待确认"), item.is_confirmed ? "ok" : "warn")} + ${pill(item.is_global ? t("jargon.global", "全局") : t("jargon.local", "本地"))} +
+ ${button(t("actions.edit", "编辑"), `data-jargon-action="edit" data-id="${escapeAttr(item.id)}"`)} + ${reviewActions} + ${button(item.is_global ? t("actions.unsetGlobal", "取消全局") : t("actions.setGlobal", "设为全局"), `data-jargon-action="toggle_global" data-id="${escapeAttr(item.id)}"`)} + ${button(t("actions.delete", "删除"), `data-jargon-action="delete" data-id="${escapeAttr(item.id)}"`, "danger-button")} +
-
- `).join(""); + `; + }).join(""); setHtml("jargon-list", html || empty(t("empty.jargon", "暂无黑话数据"))); state.pageData.lastJargonItems = items; state.pageData.currentJargonData = data; @@ -1095,11 +1146,11 @@ const typeText = { persona: t("reviews.personaUpdates", "人格更新"), style: t("reviews.expressionReviews", "表达审查"), jargon: t("reviews.jargonCandidates", "黑话候选") }[kind] || t("reviews.items", "审查项"); const actionText = action === "approve" ? t("actions.pass", "通过") : action === "reject" ? t("actions.reject", "拒绝") : t("actions.delete", "删除"); const scopeText = selectedReviewIds(kind).length ? t("selection.selected", "选中") : t("selection.currentPage", "当前页"); - if (!window.confirm(t("reviews.confirmBatch", "确定批量{action}{scope} {count} 条{type}?") + if (!await showConfirm(t("reviews.batchConfirmTitle", "批量操作确认"), t("reviews.confirmBatch", "确定批量{action}{scope} {count} 条{type}?") .replace("{action}", actionText) .replace("{scope}", scopeText) .replace("{count}", fmt(ids.length, 0)) - .replace("{type}", typeText))) return; + .replace("{type}", typeText), actionText)) return; const payload = { action: action === "delete" @@ -1305,7 +1356,7 @@ return; } const actionText = action === "approve" ? t("actions.confirm", "确认") : action === "reject" ? t("actions.rejectBack", "驳回") : t("actions.delete", "删除"); - if (!window.confirm(t("jargon.confirmBatch", "确定批量{action}选中的 {count} 条黑话?").replace("{action}", actionText).replace("{count}", fmt(ids.length, 0)))) return; + if (!await showConfirm(t("jargon.batchConfirmTitle", "批量操作确认"), t("jargon.confirmBatch", "确定批量{action}选中的 {count} 条黑话?").replace("{action}", actionText).replace("{count}", fmt(ids.length, 0)), actionText)) return; const result = await apiPost("jargon/action", { action: action === "delete" ? "batch_delete" : "batch_review", @@ -1367,7 +1418,7 @@ return; } const actionText = action === "approve" ? t("actions.approve", "批准") : action === "reject" ? t("actions.reject", "拒绝") : t("actions.delete", "删除"); - if (!window.confirm(t("style.confirmBatch", "确定批量{action}选中的 {count} 条表达审查?").replace("{action}", actionText).replace("{count}", fmt(ids.length, 0)))) return; + if (!await showConfirm(t("style.batchConfirmTitle", "批量操作确认"), t("style.confirmBatch", "确定批量{action}选中的 {count} 条表达审查?").replace("{action}", actionText).replace("{count}", fmt(ids.length, 0)), actionText)) return; const result = await apiPost("style/action", { action: action === "delete" ? "batch_delete" : "batch_review", diff --git a/pages/dashboard/styles.css b/pages/dashboard/styles.css index 9d5a301e..1559c067 100644 --- a/pages/dashboard/styles.css +++ b/pages/dashboard/styles.css @@ -1186,6 +1186,18 @@ textarea { box-shadow: var(--shadow); } +.confirm-message { + margin: 0 0 16px; + line-height: 1.6; +} + +.confirm-actions { + display: flex; + justify-content: flex-end; + gap: 8px; + flex-wrap: wrap; +} + @media (max-width: 1120px) { .app-shell { grid-template-columns: 1fr; diff --git a/services/core_learning/v2_learning_integration.py b/services/core_learning/v2_learning_integration.py index 5f0a1c85..caf1f5d0 100644 --- a/services/core_learning/v2_learning_integration.py +++ b/services/core_learning/v2_learning_integration.py @@ -733,6 +733,16 @@ async def _jargon_batch(group_id: str) -> None: return for candidate in candidates[:10]: try: + existing = None + if db and hasattr(db, "get_jargon"): + existing = await db.get_jargon(group_id, candidate["term"]) + if existing and existing.get("is_complete"): + logger.debug( + f"[V2Integration] Skip completed jargon " + f"'{candidate['term']}'" + ) + continue + meaning = await llm.generate_response( f"Explain the slang/jargon term " f"'{candidate['term']}' in the context of an " @@ -744,6 +754,11 @@ async def _jargon_batch(group_id: str) -> None: and db and hasattr(db, "save_or_update_jargon") ): + observed_count = max( + int(candidate.get("frequency") or 1), + int((existing or {}).get("count") or 0), + 1, + ) await db.save_or_update_jargon( group_id, candidate["term"], @@ -751,8 +766,9 @@ async def _jargon_batch(group_id: str) -> None: "meaning": meaning, "raw_content": "[]", "is_jargon": True, - "count": 1, + "count": observed_count, "is_complete": True, + "_preserve_completed": True, }, ) except Exception as exc: diff --git a/services/database/facades/jargon_facade.py b/services/database/facades/jargon_facade.py index 26e81824..ed5487ce 100644 --- a/services/database/facades/jargon_facade.py +++ b/services/database/facades/jargon_facade.py @@ -728,20 +728,24 @@ async def _save_or_update_jargon_select_then_write( now_ts = self._coerce_jargon_timestamp() if record: + preserve_completed = ( + self._preserve_completed_jargon(jargon_data) + and bool(record.is_complete) + ) # 更新已有记录 - if 'meaning' in jargon_data: + if 'meaning' in jargon_data and not preserve_completed: record.meaning = jargon_data['meaning'] - if 'raw_content' in jargon_data: + if 'raw_content' in jargon_data and not preserve_completed: record.raw_content = truncate_for_db(jargon_data['raw_content']) - if 'is_jargon' in jargon_data: + if 'is_jargon' in jargon_data and not preserve_completed: record.is_jargon = jargon_data['is_jargon'] - if 'count' in jargon_data: + if 'count' in jargon_data and not preserve_completed: record.count = jargon_data['count'] if 'last_inference_count' in jargon_data: record.last_inference_count = jargon_data['last_inference_count'] - if 'is_complete' in jargon_data: + if 'is_complete' in jargon_data and not preserve_completed: record.is_complete = jargon_data['is_complete'] - if 'is_global' in jargon_data: + if 'is_global' in jargon_data and not preserve_completed: record.is_global = jargon_data['is_global'] record.updated_at = now_ts @@ -825,6 +829,27 @@ async def _save_or_update_jargon_sqlite( def _coerce_jargon_timestamp() -> int: return int(time.time()) + @staticmethod + def _preserve_completed_jargon(jargon_data: Dict[str, Any]) -> bool: + return bool(jargon_data.get("_preserve_completed")) + + @staticmethod + def _completed_preserving_value(new_value: Any, old_column: Any): + return case( + (Jargon.is_complete.is_(True), old_column), + else_=new_value, + ) + + @staticmethod + def _completed_preserving_count(new_value: Any): + return case( + ( + Jargon.is_complete.is_(True), + Jargon.count, + ), + else_=new_value, + ) + @staticmethod def _jargon_insert_values( chat_id: str, @@ -852,20 +877,61 @@ def _jargon_update_values( now_ts: int, ) -> Dict[str, Any]: update_values = {"updated_at": now_ts} + preserve_completed = JargonFacade._preserve_completed_jargon(jargon_data) if "meaning" in jargon_data: - update_values["meaning"] = jargon_data["meaning"] + update_values["meaning"] = ( + JargonFacade._completed_preserving_value( + jargon_data["meaning"], + Jargon.meaning, + ) + if preserve_completed + else jargon_data["meaning"] + ) if "raw_content" in jargon_data: - update_values["raw_content"] = truncate_for_db(jargon_data["raw_content"]) + raw_content = truncate_for_db(jargon_data["raw_content"]) + update_values["raw_content"] = ( + JargonFacade._completed_preserving_value( + raw_content, + Jargon.raw_content, + ) + if preserve_completed + else raw_content + ) if "is_jargon" in jargon_data: - update_values["is_jargon"] = jargon_data["is_jargon"] + update_values["is_jargon"] = ( + JargonFacade._completed_preserving_value( + jargon_data["is_jargon"], + Jargon.is_jargon, + ) + if preserve_completed + else jargon_data["is_jargon"] + ) if "count" in jargon_data: - update_values["count"] = jargon_data["count"] + update_values["count"] = ( + JargonFacade._completed_preserving_count(jargon_data["count"]) + if preserve_completed + else jargon_data["count"] + ) if "last_inference_count" in jargon_data: update_values["last_inference_count"] = jargon_data["last_inference_count"] if "is_complete" in jargon_data: - update_values["is_complete"] = jargon_data["is_complete"] + update_values["is_complete"] = ( + JargonFacade._completed_preserving_value( + jargon_data["is_complete"], + Jargon.is_complete, + ) + if preserve_completed + else jargon_data["is_complete"] + ) if "is_global" in jargon_data: - update_values["is_global"] = jargon_data["is_global"] + update_values["is_global"] = ( + JargonFacade._completed_preserving_value( + jargon_data["is_global"], + Jargon.is_global, + ) + if preserve_completed + else jargon_data["is_global"] + ) return update_values @staticmethod diff --git a/tests/integration/test_webui_static_assets.py b/tests/integration/test_webui_static_assets.py index 53d010c4..e4c090da 100644 --- a/tests/integration/test_webui_static_assets.py +++ b/tests/integration/test_webui_static_assets.py @@ -102,6 +102,10 @@ def test_embedded_plugin_page_uses_astrbot_bridge_and_module_dashboard(): assert "function handleBatchReviewAction" in script assert "batch_review_style" in script assert "batch_review_jargon" in script + assert "function showConfirm" in script + assert "window.confirm" not in script + assert "data-confirm-ok" in script + assert "data-confirm-cancel" in script assert 'review_source !== "style_learning"' in script assert "分类去向" in script assert "style_learning_reviews" in script @@ -123,6 +127,7 @@ def test_embedded_plugin_page_uses_astrbot_bridge_and_module_dashboard(): assert "graphHomePosition" in script assert "GRAPH_HOME_STRENGTH" in script assert "graphNodeMargin" in script + assert 'const reviewActions = item.is_confirmed ? ""' in script assert "manual_dependency_source" in script assert "installButton.disabled = true" in script assert "正在调用 pip 安装依赖" in script diff --git a/tests/unit/test_database_engine.py b/tests/unit/test_database_engine.py index f707128e..19ffe93f 100644 --- a/tests/unit/test_database_engine.py +++ b/tests/unit/test_database_engine.py @@ -505,6 +505,57 @@ async def save_term(index: int): await manager.stop() +@pytest.mark.asyncio +async def test_jargon_relearning_upsert_preserves_completed_manual_definition(tmp_path): + config = PluginConfig( + data_dir=str(tmp_path), + enable_web_interface=False, + db_type="sqlite", + ) + config.messages_db_path = str(tmp_path / "messages.db") + manager = SQLAlchemyDatabaseManager(config) + + try: + assert await manager.start() is True + + jargon_id = await manager.save_or_update_jargon( + "group-a", + "打爆", + { + "raw_content": "[\"manual\"]", + "meaning": "管理员手动释义", + "is_jargon": True, + "count": 8, + "is_complete": True, + "is_global": True, + }, + ) + + relearned_id = await manager.save_or_update_jargon( + "group-a", + "打爆", + { + "raw_content": "[\"auto\"]", + "meaning": "LLM 新释义", + "is_jargon": True, + "count": 1, + "is_complete": True, + "is_global": False, + "_preserve_completed": True, + }, + ) + + assert relearned_id == jargon_id + saved = await manager.get_jargon("group-a", "打爆") + assert saved["meaning"] == "管理员手动释义" + assert saved["raw_content"] == "[\"manual\"]" + assert saved["count"] == 8 + assert saved["is_complete"] is True + assert saved["is_global"] is True + finally: + await manager.stop() + + def test_database_engine_mysql_uses_aiomysql_without_pool_pre_ping(monkeypatch): captured = {} diff --git a/tests/unit/test_provider_registry_rebind.py b/tests/unit/test_provider_registry_rebind.py index 314d3dbf..91e6bbb3 100644 --- a/tests/unit/test_provider_registry_rebind.py +++ b/tests/unit/test_provider_registry_rebind.py @@ -5,7 +5,7 @@ import sys from pathlib import Path from types import SimpleNamespace -from unittest.mock import Mock +from unittest.mock import AsyncMock, Mock import pytest from astrbot.core.provider.provider import ( @@ -160,3 +160,82 @@ def _create_jargon_filter(self): assert integration._embedding_provider.provider_id == "embed-a" assert integration._rerank_provider.provider_id == "rerank-a" context.get_provider_by_id.assert_not_called() + + +@pytest.mark.asyncio +async def test_v2_jargon_batch_skips_completed_terms_and_preserves_candidate_count(plugin_modules): + class MinimalV2LearningIntegration(plugin_modules.V2LearningIntegration): + def _create_embedding_provider(self): + return None + + def _create_rerank_provider(self): + return None + + def _create_knowledge_manager(self): + return None + + def _create_memory_manager(self): + return None + + def _create_exemplar_library(self): + return None + + def _create_social_analyzer(self): + return None + + def _create_jargon_filter(self): + return SimpleNamespace( + update_from_message=Mock(), + get_jargon_candidates=Mock( + return_value=[ + {"term": "打爆", "frequency": 9}, + {"term": "上桌", "frequency": 6}, + ], + ), + ) + + db = SimpleNamespace( + get_jargon=AsyncMock( + side_effect=[ + { + "content": "打爆", + "meaning": "管理员手动释义", + "count": 9, + "is_complete": True, + }, + None, + ] + ), + save_or_update_jargon=AsyncMock(return_value=2), + ) + llm = SimpleNamespace(generate_response=AsyncMock(return_value="新释义")) + config = plugin_modules.PluginConfig( + embedding_provider_id="", + rerank_provider_id="", + knowledge_engine="legacy", + memory_engine="legacy", + ) + + integration = MinimalV2LearningIntegration( + config=config, + llm_adapter=llm, + db_manager=db, + context=SimpleNamespace(), + ) + + ok = await integration._trigger.force_tier2("jargon", "group-a") + + assert ok is True + assert llm.generate_response.await_count == 1 + db.save_or_update_jargon.assert_awaited_once_with( + "group-a", + "上桌", + { + "meaning": "新释义", + "raw_content": "[]", + "is_jargon": True, + "count": 6, + "is_complete": True, + "_preserve_completed": True, + }, + ) From a3ccdbe474fc16bdf1029d939eddc0acf97d383c Mon Sep 17 00:00:00 2001 From: EterUltimate <1831303476@qq.com> Date: Tue, 16 Jun 2026 23:35:16 +0800 Subject: [PATCH 2/2] test: address jargon review feedback --- constants.py | 3 ++ .../core_learning/v2_learning_integration.py | 3 +- services/database/facades/jargon_facade.py | 4 +- tests/integration/test_webui_static_assets.py | 40 ++++++++++++++++++- tests/unit/test_database_engine.py | 3 +- tests/unit/test_provider_registry_rebind.py | 4 +- 6 files changed, 52 insertions(+), 5 deletions(-) diff --git a/constants.py b/constants.py index 9eed08d2..1187cd74 100644 --- a/constants.py +++ b/constants.py @@ -17,6 +17,9 @@ # 传统人格更新(其他类型) UPDATE_TYPE_TRADITIONAL = "traditional" +# 内部黑话重学标记:保护已人工确认/完成的释义不被自动重学覆盖 +PRESERVE_COMPLETED_JARGON_KEY = "_preserve_completed" + # 兼容性:旧的update_type值映射 # 用于数据库中已存在的旧记录 LEGACY_UPDATE_TYPE_MAPPING = { diff --git a/services/core_learning/v2_learning_integration.py b/services/core_learning/v2_learning_integration.py index caf1f5d0..e1363686 100644 --- a/services/core_learning/v2_learning_integration.py +++ b/services/core_learning/v2_learning_integration.py @@ -36,6 +36,7 @@ from astrbot.api import logger +from ...constants import PRESERVE_COMPLETED_JARGON_KEY from ...config import PluginConfig from ...core.interfaces import MessageData from ...utils.cache_manager import get_cache_manager @@ -768,7 +769,7 @@ async def _jargon_batch(group_id: str) -> None: "is_jargon": True, "count": observed_count, "is_complete": True, - "_preserve_completed": True, + PRESERVE_COMPLETED_JARGON_KEY: True, }, ) except Exception as exc: diff --git a/services/database/facades/jargon_facade.py b/services/database/facades/jargon_facade.py index ed5487ce..a943ed9a 100644 --- a/services/database/facades/jargon_facade.py +++ b/services/database/facades/jargon_facade.py @@ -13,9 +13,11 @@ from ._base import BaseFacade try: + from ....constants import PRESERVE_COMPLETED_JARGON_KEY from ....models.orm.jargon import Jargon from ....utils.text_utils import truncate_for_db except ImportError: + from constants import PRESERVE_COMPLETED_JARGON_KEY from models.orm.jargon import Jargon from utils.text_utils import truncate_for_db @@ -831,7 +833,7 @@ def _coerce_jargon_timestamp() -> int: @staticmethod def _preserve_completed_jargon(jargon_data: Dict[str, Any]) -> bool: - return bool(jargon_data.get("_preserve_completed")) + return bool(jargon_data.get(PRESERVE_COMPLETED_JARGON_KEY)) @staticmethod def _completed_preserving_value(new_value: Any, old_column: Any): diff --git a/tests/integration/test_webui_static_assets.py b/tests/integration/test_webui_static_assets.py index e4c090da..1b5d8c2e 100644 --- a/tests/integration/test_webui_static_assets.py +++ b/tests/integration/test_webui_static_assets.py @@ -35,6 +35,37 @@ ] +def _extract_js_function_source(script: str, name: str) -> str: + match = re.search(rf"(?:async\s+)?function\s+{re.escape(name)}\s*\([^)]*\)\s*{{", script) + assert match, f"Missing JS function: {name}" + + depth = 1 + quote = None + escaped = False + index = match.end() + + while index < len(script): + char = script[index] + if quote: + if escaped: + escaped = False + elif char == "\\": + escaped = True + elif char == quote: + quote = None + elif char in {"'", '"', "`"}: + quote = char + elif char == "{": + depth += 1 + elif char == "}": + depth -= 1 + if depth == 0: + return script[match.start(): index + 1] + index += 1 + + raise AssertionError(f"Unterminated JS function: {name}") + + def test_webui_html_templates_no_external_frontend_cdn_refs(): for path in HTML_FILES: text = path.read_text(encoding="utf-8") @@ -103,7 +134,14 @@ def test_embedded_plugin_page_uses_astrbot_bridge_and_module_dashboard(): assert "batch_review_style" in script assert "batch_review_jargon" in script assert "function showConfirm" in script - assert "window.confirm" not in script + for function_name in [ + "handleBatchReviewAction", + "handleJargonBatchAction", + "handleStyleBatchAction", + ]: + function_source = _extract_js_function_source(script, function_name) + assert "showConfirm(" in function_source + assert "window.confirm" not in function_source assert "data-confirm-ok" in script assert "data-confirm-cancel" in script assert 'review_source !== "style_learning"' in script diff --git a/tests/unit/test_database_engine.py b/tests/unit/test_database_engine.py index 19ffe93f..c4ca520e 100644 --- a/tests/unit/test_database_engine.py +++ b/tests/unit/test_database_engine.py @@ -10,6 +10,7 @@ from sqlalchemy.engine import make_url from config import PluginConfig +from constants import PRESERVE_COMPLETED_JARGON_KEY from core.database.engine import DatabaseEngine from models.orm import Base from models.orm.jargon import Jargon @@ -541,7 +542,7 @@ async def test_jargon_relearning_upsert_preserves_completed_manual_definition(tm "count": 1, "is_complete": True, "is_global": False, - "_preserve_completed": True, + PRESERVE_COMPLETED_JARGON_KEY: True, }, ) diff --git a/tests/unit/test_provider_registry_rebind.py b/tests/unit/test_provider_registry_rebind.py index 91e6bbb3..17d22006 100644 --- a/tests/unit/test_provider_registry_rebind.py +++ b/tests/unit/test_provider_registry_rebind.py @@ -13,6 +13,8 @@ RerankProvider as FrameworkRerankProvider, ) +from constants import PRESERVE_COMPLETED_JARGON_KEY + PLUGIN_ROOT = Path(__file__).resolve().parents[2] @@ -236,6 +238,6 @@ def _create_jargon_filter(self): "is_jargon": True, "count": 6, "is_complete": True, - "_preserve_completed": True, + PRESERVE_COMPLETED_JARGON_KEY: True, }, )