mirror of
https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology.git
synced 2026-05-15 22:30:38 +08:00
feat: 重构配置工作区
This commit is contained in:
20
README.md
20
README.md
@@ -111,10 +111,10 @@ git clone https://github.com/pjm0616/ST-Bionic-Memory-Ecology.git st-bme
|
||||
|
||||
## ⚡ 快速上手
|
||||
|
||||
1. **启用插件** — 右侧面板找到 "ST-BME 图谱记忆" 区块,勾选 "启用记忆图谱"
|
||||
2. **配置 Embedding** — 选择向量模式(下面会说),有了向量搜索召回效果才好
|
||||
3. **开始聊天** — 正常跟角色对话,插件会自动在后台提取和召回
|
||||
4. **打开面板** — 左上角 ≡ 菜单 →「🧠 记忆图谱」查看图谱
|
||||
1. **打开面板** — 左上角 ≡ 菜单 →「🧠 记忆图谱」
|
||||
2. **启用插件** — 进入面板的「配置 → 功能开关」,打开 ST-BME 自动记忆
|
||||
3. **配置 Embedding** — 进入「配置 → API 配置」,选择向量模式并填好模型
|
||||
4. **开始聊天** — 正常跟角色对话,插件会自动在后台提取和召回
|
||||
|
||||
> **最少配置:** 只勾选"启用"就能跑起来。默认会复用你当前的聊天模型做提取。
|
||||
|
||||
@@ -195,7 +195,7 @@ git clone https://github.com/pjm0616/ST-Bionic-Memory-Ecology.git st-bme
|
||||
|
||||
## 🖥️ 操控面板
|
||||
|
||||
从左上角 ≡ 菜单点「🧠 记忆图谱」打开面板,或在右侧设置里点「打开操控面板」。
|
||||
从左上角 ≡ 菜单点「🧠 记忆图谱」打开面板。
|
||||
|
||||
### 总览 Tab
|
||||
- 统计数据(活跃节点、边、归档数、碎片率)
|
||||
@@ -222,7 +222,14 @@ git clone https://github.com/pjm0616/ST-Bionic-Memory-Ecology.git st-bme
|
||||
- 强制进化 — 让新记忆影响旧记忆
|
||||
|
||||
### 配置 Tab
|
||||
在面板内可以直接修改记忆 LLM 和 Embedding 配置,无需退出面板。
|
||||
配置页现在是一个完整的工作区,分成 5 个子页:
|
||||
- API 配置
|
||||
- 功能开关
|
||||
- 详细参数
|
||||
- 系统提示词
|
||||
- 面板外观
|
||||
|
||||
桌面端会显示左侧竖向子导航,右侧显示宽版配置表单;移动端则改成顶部横向子页切换。
|
||||
|
||||
### 图谱可视化
|
||||
桌面端右侧大区域显示力导向图谱,节点可拖拽、缩放、点击查看详情。支持 4 套配色主题切换。
|
||||
@@ -289,7 +296,6 @@ ST-BME/
|
||||
├── graph-renderer.js # Canvas 力导向图谱渲染器
|
||||
├── panel.js # 操控面板交互逻辑
|
||||
├── panel.html # 面板 HTML 模板
|
||||
├── settings.html # 右侧设置面板
|
||||
├── style.css # 全部样式
|
||||
├── manifest.json # SillyTavern 扩展清单
|
||||
└── tests/ # 测试脚本
|
||||
|
||||
248
index.js
248
index.js
@@ -1568,254 +1568,6 @@ async function onReembedDirect() {
|
||||
await onRebuildVectorIndex();
|
||||
}
|
||||
|
||||
// ==================== 设置 UI ====================
|
||||
|
||||
function bindSettingsUI() {
|
||||
const settings = getSettings();
|
||||
|
||||
// 开关
|
||||
$("#st_bme_enabled")
|
||||
.prop("checked", settings.enabled)
|
||||
.on("change", function () {
|
||||
settings.enabled = $(this).prop("checked");
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
// 提取频率
|
||||
$("#st_bme_extract_every")
|
||||
.val(settings.extractEvery)
|
||||
.on("input", function () {
|
||||
settings.extractEvery = clampInt($(this).val(), 1, 1, 50);
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
$("#st_bme_extract_context_turns")
|
||||
.val(settings.extractContextTurns)
|
||||
.on("input", function () {
|
||||
settings.extractContextTurns = clampInt($(this).val(), 2, 0, 20);
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
// 召回开关
|
||||
$("#st_bme_recall_enabled")
|
||||
.prop("checked", settings.recallEnabled)
|
||||
.on("change", function () {
|
||||
settings.recallEnabled = $(this).prop("checked");
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
// LLM 精确召回
|
||||
$("#st_bme_recall_llm")
|
||||
.prop("checked", settings.recallEnableLLM)
|
||||
.on("change", function () {
|
||||
settings.recallEnableLLM = $(this).prop("checked");
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$("#st_bme_recall_top_k")
|
||||
.val(settings.recallTopK)
|
||||
.on("input", function () {
|
||||
settings.recallTopK = clampInt($(this).val(), 15, 1, 100);
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
$("#st_bme_recall_max_nodes")
|
||||
.val(settings.recallMaxNodes)
|
||||
.on("input", function () {
|
||||
settings.recallMaxNodes = clampInt($(this).val(), 8, 1, 50);
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
// 注入深度
|
||||
$("#st_bme_inject_depth")
|
||||
.val(settings.injectDepth)
|
||||
.on("input", function () {
|
||||
settings.injectDepth = clampInt($(this).val(), 4, 0, 9999);
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
// 评分权重
|
||||
$("#st_bme_graph_weight")
|
||||
.val(settings.graphWeight)
|
||||
.on("input", function () {
|
||||
settings.graphWeight = clampFloat($(this).val(), 0.6, 0, 1);
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
$("#st_bme_vector_weight")
|
||||
.val(settings.vectorWeight)
|
||||
.on("input", function () {
|
||||
settings.vectorWeight = clampFloat($(this).val(), 0.3, 0, 1);
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
$("#st_bme_importance_weight")
|
||||
.val(settings.importanceWeight)
|
||||
.on("input", function () {
|
||||
settings.importanceWeight = clampFloat($(this).val(), 0.1, 0, 1);
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
// Embedding API
|
||||
$("#st_bme_embed_url")
|
||||
.val(settings.embeddingApiUrl)
|
||||
.on("input", function () {
|
||||
settings.embeddingApiUrl = $(this).val().trim();
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
$("#st_bme_embed_key")
|
||||
.val(settings.embeddingApiKey)
|
||||
.on("input", function () {
|
||||
settings.embeddingApiKey = $(this).val().trim();
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
$("#st_bme_embed_model")
|
||||
.val(settings.embeddingModel)
|
||||
.on("input", function () {
|
||||
settings.embeddingModel = $(this).val().trim();
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
// 操作按钮
|
||||
$("#st_bme_btn_view_graph").on("click", onViewGraph);
|
||||
$("#st_bme_btn_rebuild").on("click", onRebuild);
|
||||
$("#st_bme_btn_compress").on("click", onManualCompress);
|
||||
$("#st_bme_btn_export").on("click", onExportGraph);
|
||||
$("#st_bme_btn_import").on("click", onImportGraph);
|
||||
$("#st_bme_btn_view_injection").on("click", onViewLastInjection);
|
||||
$("#st_bme_btn_test_embed").on("click", onTestEmbedding);
|
||||
|
||||
// ====== v2 增强设置 UI 绑定 ======
|
||||
|
||||
// P0: 记忆进化
|
||||
$("#st_bme_evolution")
|
||||
.prop("checked", settings.enableEvolution)
|
||||
.on("change", function () {
|
||||
settings.enableEvolution = $(this).prop("checked");
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
$("#st_bme_evo_neighbors")
|
||||
.val(settings.evoNeighborCount)
|
||||
.on("input", function () {
|
||||
settings.evoNeighborCount = clampInt($(this).val(), 5, 1, 20);
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
$("#st_bme_evo_consolidate_every")
|
||||
.val(settings.evoConsolidateEvery)
|
||||
.on("input", function () {
|
||||
settings.evoConsolidateEvery = clampInt($(this).val(), 50, 1, 500);
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
// P0: 精确对照
|
||||
$("#st_bme_precise_conflict")
|
||||
.prop("checked", settings.enablePreciseConflict)
|
||||
.on("change", function () {
|
||||
settings.enablePreciseConflict = $(this).prop("checked");
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
$("#st_bme_conflict_threshold")
|
||||
.val(settings.conflictThreshold)
|
||||
.on("input", function () {
|
||||
settings.conflictThreshold = clampFloat($(this).val(), 0.85, 0.5, 0.99);
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
// P0: 全局概要
|
||||
$("#st_bme_synopsis")
|
||||
.prop("checked", settings.enableSynopsis)
|
||||
.on("change", function () {
|
||||
settings.enableSynopsis = $(this).prop("checked");
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
$("#st_bme_synopsis_every")
|
||||
.val(settings.synopsisEveryN)
|
||||
.on("input", function () {
|
||||
settings.synopsisEveryN = clampInt($(this).val(), 5, 1, 100);
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
// P1: 认知边界
|
||||
$("#st_bme_visibility")
|
||||
.prop("checked", settings.enableVisibility ?? false)
|
||||
.on("change", function () {
|
||||
settings.enableVisibility = $(this).prop("checked");
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
// P1: 交叉检索
|
||||
$("#st_bme_cross_recall")
|
||||
.prop("checked", settings.enableCrossRecall ?? false)
|
||||
.on("change", function () {
|
||||
settings.enableCrossRecall = $(this).prop("checked");
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
// P2: 惊奇度分割
|
||||
$("#st_bme_smart_trigger")
|
||||
.prop("checked", settings.enableSmartTrigger)
|
||||
.on("change", function () {
|
||||
settings.enableSmartTrigger = $(this).prop("checked");
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
$("#st_bme_trigger_patterns")
|
||||
.val(settings.triggerPatterns || "")
|
||||
.on("input", function () {
|
||||
settings.triggerPatterns = $(this).val();
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
$("#st_bme_smart_trigger_threshold")
|
||||
.val(settings.smartTriggerThreshold)
|
||||
.on("input", function () {
|
||||
settings.smartTriggerThreshold = clampInt($(this).val(), 2, 1, 10);
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
// P2: 主动遗忘
|
||||
$("#st_bme_sleep_cycle")
|
||||
.prop("checked", settings.enableSleepCycle)
|
||||
.on("change", function () {
|
||||
settings.enableSleepCycle = $(this).prop("checked");
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
$("#st_bme_forget_threshold")
|
||||
.val(settings.forgetThreshold)
|
||||
.on("input", function () {
|
||||
settings.forgetThreshold = clampFloat($(this).val(), 0.5, 0.1, 1);
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
$("#st_bme_sleep_every")
|
||||
.val(settings.sleepEveryN)
|
||||
.on("input", function () {
|
||||
settings.sleepEveryN = clampInt($(this).val(), 10, 1, 200);
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
// P2: 概率触发
|
||||
$("#st_bme_prob_recall")
|
||||
.prop("checked", settings.enableProbRecall)
|
||||
.on("change", function () {
|
||||
settings.enableProbRecall = $(this).prop("checked");
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
$("#st_bme_prob_chance")
|
||||
.val(settings.probRecallChance)
|
||||
.on("input", function () {
|
||||
settings.probRecallChance = clampFloat($(this).val(), 0.15, 0.01, 0.5);
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
// P2: 反思条目
|
||||
$("#st_bme_reflection")
|
||||
.prop("checked", settings.enableReflection)
|
||||
.on("change", function () {
|
||||
settings.enableReflection = $(this).prop("checked");
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
$("#st_bme_reflect_every")
|
||||
.val(settings.reflectEveryN)
|
||||
.on("input", function () {
|
||||
settings.reflectEveryN = clampInt($(this).val(), 10, 1, 200);
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
}
|
||||
|
||||
// ==================== 初始化 ====================
|
||||
|
||||
(async function init() {
|
||||
|
||||
1101
panel.html
1101
panel.html
File diff suppressed because it is too large
Load Diff
420
panel.js
420
panel.js
@@ -108,6 +108,8 @@ let panelEl = null;
|
||||
let overlayEl = null;
|
||||
let graphRenderer = null;
|
||||
let mobileGraphRenderer = null;
|
||||
let currentTabId = "dashboard";
|
||||
let currentConfigSectionId = "api";
|
||||
|
||||
|
||||
// 由 index.js 注入的引用
|
||||
@@ -167,6 +169,10 @@ export async function initPanel({
|
||||
_bindGraphControls();
|
||||
_bindActions();
|
||||
_bindConfigControls();
|
||||
currentTabId =
|
||||
panelEl?.querySelector(".bme-tab-btn.active")?.dataset.tab || "dashboard";
|
||||
_applyWorkspaceMode();
|
||||
_syncConfigSectionState();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -192,10 +198,11 @@ export function openPanel() {
|
||||
mobileGraphRenderer.onNodeSelect = (node) => _showNodeDetail(node);
|
||||
}
|
||||
|
||||
_refreshDashboard();
|
||||
const activeTabId =
|
||||
panelEl?.querySelector(".bme-tab-btn.active")?.dataset.tab || currentTabId;
|
||||
_switchTab(activeTabId);
|
||||
_refreshGraph();
|
||||
_buildLegend();
|
||||
_refreshConfigTab();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -213,6 +220,7 @@ export function updatePanelTheme(themeName) {
|
||||
graphRenderer?.setTheme(themeName);
|
||||
mobileGraphRenderer?.setTheme(themeName);
|
||||
_buildLegend();
|
||||
_highlightThemeChoice(themeName);
|
||||
}
|
||||
|
||||
// ==================== Tab 切换 ====================
|
||||
@@ -227,15 +235,18 @@ function _bindTabs() {
|
||||
}
|
||||
|
||||
function _switchTab(tabId) {
|
||||
currentTabId = tabId || "dashboard";
|
||||
panelEl?.querySelectorAll(".bme-tab-btn").forEach((btn) => {
|
||||
btn.classList.toggle("active", btn.dataset.tab === tabId);
|
||||
btn.classList.toggle("active", btn.dataset.tab === currentTabId);
|
||||
});
|
||||
|
||||
panelEl?.querySelectorAll(".bme-tab-pane").forEach((pane) => {
|
||||
pane.classList.toggle("active", pane.id === `bme-pane-${tabId}`);
|
||||
pane.classList.toggle("active", pane.id === `bme-pane-${currentTabId}`);
|
||||
});
|
||||
|
||||
switch (tabId) {
|
||||
_applyWorkspaceMode();
|
||||
|
||||
switch (currentTabId) {
|
||||
case "dashboard":
|
||||
_refreshDashboard();
|
||||
break;
|
||||
@@ -253,6 +264,33 @@ function _switchTab(tabId) {
|
||||
}
|
||||
}
|
||||
|
||||
function _applyWorkspaceMode() {
|
||||
if (!panelEl) return;
|
||||
const isConfig = currentTabId === "config";
|
||||
panelEl.classList.toggle("config-mode", isConfig);
|
||||
}
|
||||
|
||||
function _switchConfigSection(sectionId) {
|
||||
currentConfigSectionId = sectionId || "api";
|
||||
_syncConfigSectionState();
|
||||
}
|
||||
|
||||
function _syncConfigSectionState() {
|
||||
if (!panelEl) return;
|
||||
panelEl.querySelectorAll(".bme-config-nav-btn").forEach((btn) => {
|
||||
btn.classList.toggle(
|
||||
"active",
|
||||
btn.dataset.configSection === currentConfigSectionId,
|
||||
);
|
||||
});
|
||||
panelEl.querySelectorAll(".bme-config-section").forEach((section) => {
|
||||
section.classList.toggle(
|
||||
"active",
|
||||
section.dataset.configSection === currentConfigSectionId,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// ==================== 总览 Tab ====================
|
||||
|
||||
function _refreshDashboard() {
|
||||
@@ -624,18 +662,87 @@ function _refreshConfigTab() {
|
||||
|
||||
_setCheckboxValue("bme-setting-enabled", settings.enabled ?? false);
|
||||
_setCheckboxValue("bme-setting-recall-enabled", settings.recallEnabled ?? true);
|
||||
_setCheckboxValue("bme-setting-recall-llm", settings.recallEnableLLM ?? true);
|
||||
_setCheckboxValue("bme-setting-evolution-enabled", settings.enableEvolution ?? true);
|
||||
_setCheckboxValue(
|
||||
"bme-setting-precise-conflict-enabled",
|
||||
settings.enablePreciseConflict ?? true,
|
||||
);
|
||||
_setCheckboxValue("bme-setting-synopsis-enabled", settings.enableSynopsis ?? true);
|
||||
_setCheckboxValue(
|
||||
"bme-setting-visibility-enabled",
|
||||
settings.enableVisibility ?? false,
|
||||
);
|
||||
_setCheckboxValue(
|
||||
"bme-setting-cross-recall-enabled",
|
||||
settings.enableCrossRecall ?? false,
|
||||
);
|
||||
_setCheckboxValue(
|
||||
"bme-setting-smart-trigger-enabled",
|
||||
settings.enableSmartTrigger ?? false,
|
||||
);
|
||||
_setCheckboxValue(
|
||||
"bme-setting-sleep-cycle-enabled",
|
||||
settings.enableSleepCycle ?? false,
|
||||
);
|
||||
_setCheckboxValue(
|
||||
"bme-setting-prob-recall-enabled",
|
||||
settings.enableProbRecall ?? false,
|
||||
);
|
||||
_setCheckboxValue(
|
||||
"bme-setting-reflection-enabled",
|
||||
settings.enableReflection ?? false,
|
||||
);
|
||||
|
||||
_setInputValue("bme-setting-extract-every", settings.extractEvery ?? 1);
|
||||
_setInputValue(
|
||||
"bme-setting-extract-context-turns",
|
||||
settings.extractContextTurns ?? 2,
|
||||
);
|
||||
_setInputValue("bme-setting-recall-top-k", settings.recallTopK ?? 15);
|
||||
_setInputValue("bme-setting-recall-max-nodes", settings.recallMaxNodes ?? 8);
|
||||
_setInputValue("bme-setting-inject-depth", settings.injectDepth ?? 4);
|
||||
_setInputValue("bme-setting-graph-weight", settings.graphWeight ?? 0.6);
|
||||
_setInputValue("bme-setting-vector-weight", settings.vectorWeight ?? 0.3);
|
||||
_setInputValue(
|
||||
"bme-setting-importance-weight",
|
||||
settings.importanceWeight ?? 0.1,
|
||||
);
|
||||
_setInputValue(
|
||||
"bme-setting-evo-neighbor-count",
|
||||
settings.evoNeighborCount ?? 5,
|
||||
);
|
||||
_setInputValue(
|
||||
"bme-setting-evo-consolidate-every",
|
||||
settings.evoConsolidateEvery ?? 50,
|
||||
);
|
||||
_setInputValue(
|
||||
"bme-setting-conflict-threshold",
|
||||
settings.conflictThreshold ?? 0.85,
|
||||
);
|
||||
_setInputValue("bme-setting-synopsis-every", settings.synopsisEveryN ?? 5);
|
||||
_setInputValue(
|
||||
"bme-setting-trigger-patterns",
|
||||
settings.triggerPatterns || "",
|
||||
);
|
||||
_setInputValue(
|
||||
"bme-setting-smart-trigger-threshold",
|
||||
settings.smartTriggerThreshold ?? 2,
|
||||
);
|
||||
_setInputValue(
|
||||
"bme-setting-forget-threshold",
|
||||
settings.forgetThreshold ?? 0.5,
|
||||
);
|
||||
_setInputValue("bme-setting-sleep-every", settings.sleepEveryN ?? 10);
|
||||
_setInputValue(
|
||||
"bme-setting-prob-recall-chance",
|
||||
settings.probRecallChance ?? 0.15,
|
||||
);
|
||||
_setInputValue("bme-setting-reflect-every", settings.reflectEveryN ?? 10);
|
||||
|
||||
_setInputValue("bme-setting-llm-url", settings.llmApiUrl || "");
|
||||
_setInputValue("bme-setting-llm-key", settings.llmApiKey || "");
|
||||
_setInputValue("bme-setting-llm-model", settings.llmModel || "");
|
||||
_setCheckboxValue("bme-setting-recall-llm", settings.recallEnableLLM ?? true);
|
||||
_setInputValue("bme-setting-recall-max-nodes", settings.recallMaxNodes ?? 8);
|
||||
|
||||
_setInputValue("bme-setting-embed-url", settings.embeddingApiUrl || "");
|
||||
_setInputValue("bme-setting-embed-key", settings.embeddingApiKey || "");
|
||||
@@ -671,96 +778,221 @@ function _refreshConfigTab() {
|
||||
_setInputValue("bme-setting-compress-prompt", settings.compressPrompt || DEFAULT_PROMPTS.compress);
|
||||
_setInputValue("bme-setting-synopsis-prompt", settings.synopsisPrompt || DEFAULT_PROMPTS.synopsis);
|
||||
_setInputValue("bme-setting-reflection-prompt", settings.reflectionPrompt || DEFAULT_PROMPTS.reflection);
|
||||
// 主题下拉菜单高亮
|
||||
_highlightThemeOption(settings.panelTheme || "crimson");
|
||||
|
||||
_refreshGuardedConfigStates(settings);
|
||||
_refreshPromptCardStates(settings);
|
||||
_highlightThemeChoice(settings.panelTheme || "crimson");
|
||||
_syncConfigSectionState();
|
||||
}
|
||||
|
||||
function _bindConfigControls() {
|
||||
if (!panelEl || panelEl.dataset.bmeConfigBound === "true") return;
|
||||
|
||||
bindCheckbox("bme-setting-enabled", (checked) =>
|
||||
_updateSettings?.({ enabled: checked }),
|
||||
panelEl.querySelectorAll(".bme-config-nav-btn").forEach((btn) => {
|
||||
if (btn.dataset.bmeBound === "true") return;
|
||||
btn.addEventListener("click", () => {
|
||||
_switchConfigSection(btn.dataset.configSection || "api");
|
||||
});
|
||||
btn.dataset.bmeBound = "true";
|
||||
});
|
||||
|
||||
bindCheckbox("bme-setting-enabled", (checked) => {
|
||||
_patchSettings({ enabled: checked });
|
||||
_refreshGuardedConfigStates();
|
||||
});
|
||||
bindCheckbox("bme-setting-recall-enabled", (checked) => {
|
||||
_patchSettings({ recallEnabled: checked });
|
||||
_refreshGuardedConfigStates();
|
||||
});
|
||||
bindCheckbox("bme-setting-recall-llm", (checked) => {
|
||||
_patchSettings({ recallEnableLLM: checked });
|
||||
_refreshGuardedConfigStates();
|
||||
});
|
||||
bindCheckbox("bme-setting-evolution-enabled", (checked) => {
|
||||
_patchSettings({ enableEvolution: checked });
|
||||
_refreshGuardedConfigStates();
|
||||
});
|
||||
bindCheckbox("bme-setting-precise-conflict-enabled", (checked) => {
|
||||
_patchSettings({ enablePreciseConflict: checked });
|
||||
_refreshGuardedConfigStates();
|
||||
});
|
||||
bindCheckbox("bme-setting-synopsis-enabled", (checked) => {
|
||||
_patchSettings({ enableSynopsis: checked });
|
||||
_refreshGuardedConfigStates();
|
||||
});
|
||||
bindCheckbox("bme-setting-visibility-enabled", (checked) =>
|
||||
_patchSettings({ enableVisibility: checked }),
|
||||
);
|
||||
bindCheckbox("bme-setting-recall-enabled", (checked) =>
|
||||
_updateSettings?.({ recallEnabled: checked }),
|
||||
bindCheckbox("bme-setting-cross-recall-enabled", (checked) =>
|
||||
_patchSettings({ enableCrossRecall: checked }),
|
||||
);
|
||||
bindCheckbox("bme-setting-smart-trigger-enabled", (checked) => {
|
||||
_patchSettings({ enableSmartTrigger: checked });
|
||||
_refreshGuardedConfigStates();
|
||||
});
|
||||
bindCheckbox("bme-setting-sleep-cycle-enabled", (checked) => {
|
||||
_patchSettings({ enableSleepCycle: checked });
|
||||
_refreshGuardedConfigStates();
|
||||
});
|
||||
bindCheckbox("bme-setting-prob-recall-enabled", (checked) => {
|
||||
_patchSettings({ enableProbRecall: checked });
|
||||
_refreshGuardedConfigStates();
|
||||
});
|
||||
bindCheckbox("bme-setting-reflection-enabled", (checked) => {
|
||||
_patchSettings({ enableReflection: checked });
|
||||
_refreshGuardedConfigStates();
|
||||
});
|
||||
|
||||
bindNumber("bme-setting-extract-every", 1, 1, 50, (value) =>
|
||||
_updateSettings?.({ extractEvery: value }),
|
||||
_patchSettings({ extractEvery: value }),
|
||||
);
|
||||
bindNumber("bme-setting-extract-context-turns", 2, 0, 20, (value) =>
|
||||
_updateSettings?.({ extractContextTurns: value }),
|
||||
_patchSettings({ extractContextTurns: value }),
|
||||
);
|
||||
bindNumber("bme-setting-recall-top-k", 15, 1, 100, (value) =>
|
||||
_patchSettings({ recallTopK: value }),
|
||||
);
|
||||
bindNumber("bme-setting-recall-max-nodes", 8, 1, 50, (value) =>
|
||||
_patchSettings({ recallMaxNodes: value }),
|
||||
);
|
||||
bindNumber("bme-setting-inject-depth", 4, 0, 9999, (value) =>
|
||||
_updateSettings?.({ injectDepth: value }),
|
||||
_patchSettings({ injectDepth: value }),
|
||||
);
|
||||
bindFloat("bme-setting-graph-weight", 0.6, 0, 1, (value) =>
|
||||
_patchSettings({ graphWeight: value }),
|
||||
);
|
||||
bindFloat("bme-setting-vector-weight", 0.3, 0, 1, (value) =>
|
||||
_patchSettings({ vectorWeight: value }),
|
||||
);
|
||||
bindFloat("bme-setting-importance-weight", 0.1, 0, 1, (value) =>
|
||||
_patchSettings({ importanceWeight: value }),
|
||||
);
|
||||
bindNumber("bme-setting-evo-neighbor-count", 5, 1, 20, (value) =>
|
||||
_patchSettings({ evoNeighborCount: value }),
|
||||
);
|
||||
bindNumber("bme-setting-evo-consolidate-every", 50, 1, 500, (value) =>
|
||||
_patchSettings({ evoConsolidateEvery: value }),
|
||||
);
|
||||
bindFloat("bme-setting-conflict-threshold", 0.85, 0.5, 0.99, (value) =>
|
||||
_patchSettings({ conflictThreshold: value }),
|
||||
);
|
||||
bindNumber("bme-setting-synopsis-every", 5, 1, 100, (value) =>
|
||||
_patchSettings({ synopsisEveryN: value }),
|
||||
);
|
||||
bindText("bme-setting-trigger-patterns", (value) =>
|
||||
_patchSettings({ triggerPatterns: value }),
|
||||
);
|
||||
bindNumber("bme-setting-smart-trigger-threshold", 2, 1, 10, (value) =>
|
||||
_patchSettings({ smartTriggerThreshold: value }),
|
||||
);
|
||||
bindFloat("bme-setting-forget-threshold", 0.5, 0.1, 1, (value) =>
|
||||
_patchSettings({ forgetThreshold: value }),
|
||||
);
|
||||
bindNumber("bme-setting-sleep-every", 10, 1, 200, (value) =>
|
||||
_patchSettings({ sleepEveryN: value }),
|
||||
);
|
||||
bindFloat("bme-setting-prob-recall-chance", 0.15, 0.01, 0.5, (value) =>
|
||||
_patchSettings({ probRecallChance: value }),
|
||||
);
|
||||
bindNumber("bme-setting-reflect-every", 10, 1, 200, (value) =>
|
||||
_patchSettings({ reflectEveryN: value }),
|
||||
);
|
||||
|
||||
bindText("bme-setting-llm-url", (value) =>
|
||||
_updateSettings?.({ llmApiUrl: value.trim() }),
|
||||
_patchSettings({ llmApiUrl: value.trim() }),
|
||||
);
|
||||
bindText("bme-setting-llm-key", (value) =>
|
||||
_updateSettings?.({ llmApiKey: value.trim() }),
|
||||
_patchSettings({ llmApiKey: value.trim() }),
|
||||
);
|
||||
bindText("bme-setting-llm-model", (value) =>
|
||||
_updateSettings?.({ llmModel: value.trim() }),
|
||||
);
|
||||
bindCheckbox("bme-setting-recall-llm", (checked) =>
|
||||
_updateSettings?.({ recallEnableLLM: checked }),
|
||||
);
|
||||
bindNumber("bme-setting-recall-max-nodes", 8, 1, 50, (value) =>
|
||||
_updateSettings?.({ recallMaxNodes: value }),
|
||||
_patchSettings({ llmModel: value.trim() }),
|
||||
);
|
||||
|
||||
bindText("bme-setting-embed-url", (value) =>
|
||||
_updateSettings?.({ embeddingApiUrl: value.trim() }),
|
||||
_patchSettings({ embeddingApiUrl: value.trim() }),
|
||||
);
|
||||
bindText("bme-setting-embed-key", (value) =>
|
||||
_updateSettings?.({ embeddingApiKey: value.trim() }),
|
||||
_patchSettings({ embeddingApiKey: value.trim() }),
|
||||
);
|
||||
bindText("bme-setting-embed-model", (value) =>
|
||||
_updateSettings?.({ embeddingModel: value.trim() }),
|
||||
_patchSettings({ embeddingModel: value.trim() }),
|
||||
);
|
||||
bindText("bme-setting-embed-mode", (value) => {
|
||||
_updateSettings?.({ embeddingTransportMode: value });
|
||||
_patchSettings({ embeddingTransportMode: value });
|
||||
_toggleEmbedFields(value);
|
||||
});
|
||||
bindText("bme-setting-embed-backend-source", (value) => {
|
||||
const patch = { embeddingBackendSource: value };
|
||||
const settings = _getSettings?.() || {};
|
||||
const patch = { embeddingBackendSource: value };
|
||||
const suggestedModel = getSuggestedBackendModel(value);
|
||||
if (!settings.embeddingBackendModel || settings.embeddingBackendModel === getSuggestedBackendModel(settings.embeddingBackendSource || "openai")) {
|
||||
if (
|
||||
!settings.embeddingBackendModel ||
|
||||
settings.embeddingBackendModel ===
|
||||
getSuggestedBackendModel(settings.embeddingBackendSource || "openai")
|
||||
) {
|
||||
patch.embeddingBackendModel = suggestedModel;
|
||||
}
|
||||
_updateSettings?.(patch);
|
||||
_setInputValue("bme-setting-embed-backend-model", patch.embeddingBackendModel || settings.embeddingBackendModel || "");
|
||||
_patchSettings(patch);
|
||||
_setInputValue(
|
||||
"bme-setting-embed-backend-model",
|
||||
patch.embeddingBackendModel || settings.embeddingBackendModel || "",
|
||||
);
|
||||
});
|
||||
bindText("bme-setting-embed-backend-model", (value) =>
|
||||
_updateSettings?.({ embeddingBackendModel: value.trim() }),
|
||||
_patchSettings({ embeddingBackendModel: value.trim() }),
|
||||
);
|
||||
bindText("bme-setting-embed-backend-url", (value) =>
|
||||
_updateSettings?.({ embeddingBackendApiUrl: value.trim() }),
|
||||
_patchSettings({ embeddingBackendApiUrl: value.trim() }),
|
||||
);
|
||||
bindCheckbox("bme-setting-embed-auto-suffix", (checked) =>
|
||||
_updateSettings?.({ embeddingAutoSuffix: checked }),
|
||||
_patchSettings({ embeddingAutoSuffix: checked }),
|
||||
);
|
||||
bindText("bme-setting-extract-prompt", (value) =>
|
||||
_updateSettings?.({ extractPrompt: value }),
|
||||
|
||||
bindPromptText(
|
||||
"bme-setting-extract-prompt",
|
||||
"extractPrompt",
|
||||
"extract",
|
||||
);
|
||||
bindText("bme-setting-recall-prompt", (value) =>
|
||||
_updateSettings?.({ recallPrompt: value }),
|
||||
bindPromptText(
|
||||
"bme-setting-recall-prompt",
|
||||
"recallPrompt",
|
||||
"recall",
|
||||
);
|
||||
bindText("bme-setting-evolution-prompt", (value) =>
|
||||
_updateSettings?.({ evolutionPrompt: value }),
|
||||
bindPromptText(
|
||||
"bme-setting-evolution-prompt",
|
||||
"evolutionPrompt",
|
||||
"evolution",
|
||||
);
|
||||
bindText("bme-setting-compress-prompt", (value) =>
|
||||
_updateSettings?.({ compressPrompt: value }),
|
||||
bindPromptText(
|
||||
"bme-setting-compress-prompt",
|
||||
"compressPrompt",
|
||||
"compress",
|
||||
);
|
||||
bindText("bme-setting-synopsis-prompt", (value) =>
|
||||
_updateSettings?.({ synopsisPrompt: value }),
|
||||
bindPromptText(
|
||||
"bme-setting-synopsis-prompt",
|
||||
"synopsisPrompt",
|
||||
"synopsis",
|
||||
);
|
||||
bindText("bme-setting-reflection-prompt", (value) =>
|
||||
_updateSettings?.({ reflectionPrompt: value }),
|
||||
bindPromptText(
|
||||
"bme-setting-reflection-prompt",
|
||||
"reflectionPrompt",
|
||||
"reflection",
|
||||
);
|
||||
// 主题下拉菜单
|
||||
|
||||
panelEl.querySelectorAll(".bme-prompt-reset").forEach((button) => {
|
||||
if (button.dataset.bmeBound === "true") return;
|
||||
button.addEventListener("click", () => {
|
||||
const settingKey = button.dataset.settingKey;
|
||||
const promptKey = button.dataset.defaultPrompt;
|
||||
const targetId = button.dataset.targetId;
|
||||
if (!settingKey || !promptKey || !targetId) return;
|
||||
_patchSettings({ [settingKey]: "" }, { refreshPrompts: true });
|
||||
_setInputValue(targetId, DEFAULT_PROMPTS[promptKey] || "");
|
||||
_refreshPromptCardStates();
|
||||
});
|
||||
button.dataset.bmeBound = "true";
|
||||
});
|
||||
|
||||
const pickerBtn = document.getElementById("bme-theme-picker-btn");
|
||||
const dropdown = document.getElementById("bme-theme-dropdown");
|
||||
if (pickerBtn && dropdown) {
|
||||
@@ -772,18 +1004,26 @@ function _bindConfigControls() {
|
||||
opt.addEventListener("click", () => {
|
||||
const theme = opt.dataset.theme;
|
||||
if (!theme) return;
|
||||
_updateSettings?.({ panelTheme: theme });
|
||||
_highlightThemeOption(theme);
|
||||
_patchSettings({ panelTheme: theme }, { refreshTheme: true });
|
||||
dropdown.classList.remove("open");
|
||||
});
|
||||
});
|
||||
// 点击外部关闭
|
||||
document.addEventListener("click", () => {
|
||||
dropdown.classList.remove("open");
|
||||
});
|
||||
dropdown.addEventListener("click", (e) => e.stopPropagation());
|
||||
}
|
||||
|
||||
panelEl.querySelectorAll(".bme-theme-card").forEach((card) => {
|
||||
if (card.dataset.bmeBound === "true") return;
|
||||
card.addEventListener("click", () => {
|
||||
const theme = card.dataset.theme;
|
||||
if (!theme) return;
|
||||
_patchSettings({ panelTheme: theme }, { refreshTheme: true });
|
||||
});
|
||||
card.dataset.bmeBound = "true";
|
||||
});
|
||||
|
||||
document.getElementById("bme-test-llm")?.addEventListener("click", async () => {
|
||||
await _actionHandlers.testMemoryLLM?.();
|
||||
});
|
||||
@@ -821,6 +1061,34 @@ function bindNumber(id, fallback, min, max, onChange) {
|
||||
element.dataset.bmeBound = "true";
|
||||
}
|
||||
|
||||
function bindFloat(id, fallback, min, max, onChange) {
|
||||
const element = document.getElementById(id);
|
||||
if (!element || element.dataset.bmeBound === "true") return;
|
||||
element.addEventListener("input", () => {
|
||||
let value = Number.parseFloat(element.value);
|
||||
if (!Number.isFinite(value)) value = fallback;
|
||||
value = Math.min(max, Math.max(min, value));
|
||||
onChange(value);
|
||||
});
|
||||
element.dataset.bmeBound = "true";
|
||||
}
|
||||
|
||||
function bindPromptText(id, settingKey, promptKey) {
|
||||
const element = document.getElementById(id);
|
||||
if (!element || element.dataset.bmeBound === "true") return;
|
||||
const update = () => {
|
||||
_patchSettings({ [settingKey]: element.value }, { refreshPrompts: true });
|
||||
};
|
||||
element.addEventListener("input", update);
|
||||
element.addEventListener("change", update);
|
||||
element.addEventListener("blur", () => {
|
||||
if (!String(element.value || "").trim()) {
|
||||
_setInputValue(id, DEFAULT_PROMPTS[promptKey] || "");
|
||||
}
|
||||
});
|
||||
element.dataset.bmeBound = "true";
|
||||
}
|
||||
|
||||
// ==================== 工具函数 ====================
|
||||
|
||||
function _setText(id, text) {
|
||||
@@ -828,11 +1096,57 @@ function _setText(id, text) {
|
||||
if (el) el.textContent = String(text);
|
||||
}
|
||||
|
||||
function _highlightThemeOption(themeName) {
|
||||
function _patchSettings(patch = {}, options = {}) {
|
||||
const settings = _updateSettings?.(patch) || _getSettings?.() || {};
|
||||
if (options.refreshGuards) _refreshGuardedConfigStates(settings);
|
||||
if (options.refreshPrompts) _refreshPromptCardStates(settings);
|
||||
if (options.refreshTheme) _highlightThemeChoice(settings.panelTheme || "crimson");
|
||||
return settings;
|
||||
}
|
||||
|
||||
function _highlightThemeChoice(themeName) {
|
||||
if (!panelEl) return;
|
||||
panelEl.querySelectorAll(".bme-theme-option").forEach((opt) => {
|
||||
opt.classList.toggle("active", opt.dataset.theme === themeName);
|
||||
});
|
||||
panelEl.querySelectorAll(".bme-theme-card").forEach((card) => {
|
||||
card.classList.toggle("active", card.dataset.theme === themeName);
|
||||
});
|
||||
}
|
||||
|
||||
function _refreshGuardedConfigStates(settings = _getSettings?.() || {}) {
|
||||
if (!panelEl) return;
|
||||
panelEl.querySelectorAll(".bme-guarded-card").forEach((card) => {
|
||||
const guardKeys = String(card.dataset.guardSettings || "")
|
||||
.split(",")
|
||||
.map((key) => key.trim())
|
||||
.filter(Boolean);
|
||||
const enabled = guardKeys.every((key) => Boolean(settings[key]));
|
||||
card.classList.toggle("is-disabled", !enabled);
|
||||
const note = card.querySelector(".bme-config-guard-note");
|
||||
note?.classList.toggle("visible", !enabled);
|
||||
card.querySelectorAll("input, select, textarea, button").forEach((element) => {
|
||||
element.disabled = !enabled;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function _refreshPromptCardStates(settings = _getSettings?.() || {}) {
|
||||
if (!panelEl) return;
|
||||
panelEl.querySelectorAll(".bme-prompt-card").forEach((card) => {
|
||||
const settingKey = card.dataset.settingKey;
|
||||
const statusEl = card.querySelector(".bme-prompt-status");
|
||||
const resetButton = card.querySelector(".bme-prompt-reset");
|
||||
const isCustom = Boolean(String(settings?.[settingKey] || "").trim());
|
||||
card.classList.toggle("is-custom", isCustom);
|
||||
if (statusEl) {
|
||||
statusEl.textContent = isCustom ? "已自定义" : "默认";
|
||||
statusEl.classList.toggle("is-custom", isCustom);
|
||||
}
|
||||
if (resetButton) {
|
||||
resetButton.disabled = !isCustom;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function _toggleEmbedFields(mode) {
|
||||
|
||||
450
settings.html
450
settings.html
@@ -1,450 +0,0 @@
|
||||
<div class="st-bme-settings">
|
||||
<div class="inline-drawer">
|
||||
<div class="inline-drawer-toggle inline-drawer-header">
|
||||
<b>ST-BME 图谱记忆</b>
|
||||
<div
|
||||
class="inline-drawer-icon fa-solid fa-circle-chevron-down down"
|
||||
></div>
|
||||
</div>
|
||||
<div class="inline-drawer-content">
|
||||
<!-- 基础设置 -->
|
||||
<div class="st-bme-section">
|
||||
<div class="st-bme-row">
|
||||
<label class="checkbox_label" for="st_bme_enabled">
|
||||
<input type="checkbox" id="st_bme_enabled" />
|
||||
<span>启用记忆图谱</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="st-bme-row">
|
||||
<label for="st_bme_extract_every">每 N 条回复提取</label>
|
||||
<input
|
||||
type="number"
|
||||
id="st_bme_extract_every"
|
||||
class="text_pole"
|
||||
min="1"
|
||||
max="50"
|
||||
value="1"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="st-bme-row">
|
||||
<label for="st_bme_extract_context_turns">提取上下文轮数</label>
|
||||
<input
|
||||
type="number"
|
||||
id="st_bme_extract_context_turns"
|
||||
class="text_pole"
|
||||
min="0"
|
||||
max="20"
|
||||
value="2"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="st-bme-hr" />
|
||||
|
||||
<!-- 召回设置 -->
|
||||
<div class="st-bme-section">
|
||||
<h4 class="st-bme-section-title">召回设置</h4>
|
||||
|
||||
<div class="st-bme-row">
|
||||
<label class="checkbox_label" for="st_bme_recall_enabled">
|
||||
<input type="checkbox" id="st_bme_recall_enabled" />
|
||||
<span>启用记忆召回注入</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="st-bme-row">
|
||||
<label class="checkbox_label" for="st_bme_recall_llm">
|
||||
<input type="checkbox" id="st_bme_recall_llm" />
|
||||
<span>启用 LLM 精确召回</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="st-bme-row">
|
||||
<label for="st_bme_recall_top_k">召回候选上限</label>
|
||||
<input
|
||||
type="number"
|
||||
id="st_bme_recall_top_k"
|
||||
class="text_pole"
|
||||
min="1"
|
||||
max="100"
|
||||
value="15"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="st-bme-row">
|
||||
<label for="st_bme_recall_max_nodes">LLM 精确召回上限</label>
|
||||
<input
|
||||
type="number"
|
||||
id="st_bme_recall_max_nodes"
|
||||
class="text_pole"
|
||||
min="1"
|
||||
max="50"
|
||||
value="8"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="st-bme-row">
|
||||
<label for="st_bme_inject_depth">注入深度</label>
|
||||
<input
|
||||
type="number"
|
||||
id="st_bme_inject_depth"
|
||||
class="text_pole"
|
||||
min="0"
|
||||
max="9999"
|
||||
value="4"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="st-bme-hr" />
|
||||
|
||||
<!-- 评分权重 -->
|
||||
<div class="st-bme-section">
|
||||
<h4 class="st-bme-section-title">混合评分权重</h4>
|
||||
|
||||
<div class="st-bme-row">
|
||||
<label for="st_bme_graph_weight">图扩散权重</label>
|
||||
<input
|
||||
type="number"
|
||||
id="st_bme_graph_weight"
|
||||
class="text_pole"
|
||||
min="0"
|
||||
max="1"
|
||||
step="0.1"
|
||||
value="0.6"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="st-bme-row">
|
||||
<label for="st_bme_vector_weight">向量权重</label>
|
||||
<input
|
||||
type="number"
|
||||
id="st_bme_vector_weight"
|
||||
class="text_pole"
|
||||
min="0"
|
||||
max="1"
|
||||
step="0.1"
|
||||
value="0.3"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="st-bme-row">
|
||||
<label for="st_bme_importance_weight">重要性权重</label>
|
||||
<input
|
||||
type="number"
|
||||
id="st_bme_importance_weight"
|
||||
class="text_pole"
|
||||
min="0"
|
||||
max="1"
|
||||
step="0.1"
|
||||
value="0.1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="st-bme-hr" />
|
||||
|
||||
<!-- v2: 增强功能 -->
|
||||
<div class="st-bme-section">
|
||||
<h4 class="st-bme-section-title">
|
||||
<i class="fa-solid fa-flask"></i> v2 增强功能
|
||||
</h4>
|
||||
|
||||
<!-- P0 核心 -->
|
||||
<div class="st-bme-subsection">
|
||||
<span class="st-bme-badge st-bme-badge-p0">P0</span>
|
||||
|
||||
<div class="st-bme-row">
|
||||
<label class="checkbox_label" for="st_bme_evolution">
|
||||
<input type="checkbox" id="st_bme_evolution" />
|
||||
<span>记忆进化 <small class="st-bme-hint">A-MEM</small></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="st-bme-row st-bme-indent">
|
||||
<label for="st_bme_evo_neighbors">近邻数量</label>
|
||||
<input
|
||||
type="number"
|
||||
id="st_bme_evo_neighbors"
|
||||
class="text_pole"
|
||||
min="1"
|
||||
max="10"
|
||||
value="5"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="st-bme-row st-bme-indent">
|
||||
<label for="st_bme_evo_consolidate_every">整理频率</label>
|
||||
<input
|
||||
type="number"
|
||||
id="st_bme_evo_consolidate_every"
|
||||
class="text_pole"
|
||||
min="1"
|
||||
max="500"
|
||||
value="50"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="st-bme-row">
|
||||
<label class="checkbox_label" for="st_bme_precise_conflict">
|
||||
<input type="checkbox" id="st_bme_precise_conflict" />
|
||||
<span>精确对照 <small class="st-bme-hint">Mem0</small></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="st-bme-row st-bme-indent">
|
||||
<label for="st_bme_conflict_threshold">对照阈值</label>
|
||||
<input
|
||||
type="number"
|
||||
id="st_bme_conflict_threshold"
|
||||
class="text_pole"
|
||||
min="0.5"
|
||||
max="0.99"
|
||||
step="0.05"
|
||||
value="0.85"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="st-bme-row">
|
||||
<label class="checkbox_label" for="st_bme_synopsis">
|
||||
<input type="checkbox" id="st_bme_synopsis" />
|
||||
<span>全局概要 <small class="st-bme-hint">MemoRAG</small></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="st-bme-row st-bme-indent">
|
||||
<label for="st_bme_synopsis_every">每 N 次提取更新</label>
|
||||
<input
|
||||
type="number"
|
||||
id="st_bme_synopsis_every"
|
||||
class="text_pole"
|
||||
min="1"
|
||||
max="20"
|
||||
value="5"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- P1 推荐 -->
|
||||
<div class="st-bme-subsection">
|
||||
<span class="st-bme-badge st-bme-badge-p1">P1</span>
|
||||
|
||||
<div class="st-bme-row">
|
||||
<label class="checkbox_label" for="st_bme_visibility">
|
||||
<input type="checkbox" id="st_bme_visibility" />
|
||||
<span>认知边界 <small class="st-bme-hint">RoleRAG</small></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="st-bme-row">
|
||||
<label class="checkbox_label" for="st_bme_cross_recall">
|
||||
<input type="checkbox" id="st_bme_cross_recall" />
|
||||
<span>交叉检索 <small class="st-bme-hint">AriGraph</small></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- P2 可选 -->
|
||||
<div class="st-bme-subsection">
|
||||
<span class="st-bme-badge st-bme-badge-p2">P2</span>
|
||||
|
||||
<div class="st-bme-row">
|
||||
<label class="checkbox_label" for="st_bme_smart_trigger">
|
||||
<input type="checkbox" id="st_bme_smart_trigger" />
|
||||
<span>惊奇度分割 <small class="st-bme-hint">EM-LLM</small></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="st-bme-row st-bme-indent">
|
||||
<label for="st_bme_trigger_patterns">自定义触发模式</label>
|
||||
<input
|
||||
type="text"
|
||||
id="st_bme_trigger_patterns"
|
||||
class="text_pole"
|
||||
placeholder="突然,真相,秘密,背叛 或 正则"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="st-bme-row st-bme-indent">
|
||||
<label for="st_bme_smart_trigger_threshold">触发阈值</label>
|
||||
<input
|
||||
type="number"
|
||||
id="st_bme_smart_trigger_threshold"
|
||||
class="text_pole"
|
||||
min="1"
|
||||
max="10"
|
||||
value="2"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="st-bme-row">
|
||||
<label class="checkbox_label" for="st_bme_sleep_cycle">
|
||||
<input type="checkbox" id="st_bme_sleep_cycle" />
|
||||
<span>主动遗忘 <small class="st-bme-hint">SleepGate</small></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="st-bme-row st-bme-indent">
|
||||
<label for="st_bme_forget_threshold">遗忘阈值</label>
|
||||
<input
|
||||
type="number"
|
||||
id="st_bme_forget_threshold"
|
||||
class="text_pole"
|
||||
min="0.1"
|
||||
max="1.0"
|
||||
step="0.1"
|
||||
value="0.5"
|
||||
/>
|
||||
</div>
|
||||
<div class="st-bme-row st-bme-indent">
|
||||
<label for="st_bme_sleep_every">每 N 次提取遗忘</label>
|
||||
<input
|
||||
type="number"
|
||||
id="st_bme_sleep_every"
|
||||
class="text_pole"
|
||||
min="1"
|
||||
max="200"
|
||||
value="10"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="st-bme-row">
|
||||
<label class="checkbox_label" for="st_bme_prob_recall">
|
||||
<input type="checkbox" id="st_bme_prob_recall" />
|
||||
<span>概率触发回忆</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="st-bme-row st-bme-indent">
|
||||
<label for="st_bme_prob_chance">触发概率</label>
|
||||
<input
|
||||
type="number"
|
||||
id="st_bme_prob_chance"
|
||||
class="text_pole"
|
||||
min="0.01"
|
||||
max="0.5"
|
||||
step="0.05"
|
||||
value="0.15"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="st-bme-row">
|
||||
<label class="checkbox_label" for="st_bme_reflection">
|
||||
<input type="checkbox" id="st_bme_reflection" />
|
||||
<span>反思条目 <small class="st-bme-hint">Reflexion</small></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="st-bme-row st-bme-indent">
|
||||
<label for="st_bme_reflect_every">每 N 次提取反思</label>
|
||||
<input
|
||||
type="number"
|
||||
id="st_bme_reflect_every"
|
||||
class="text_pole"
|
||||
min="3"
|
||||
max="30"
|
||||
value="10"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="st-bme-hr" />
|
||||
|
||||
<!-- Embedding API -->
|
||||
<div class="st-bme-section">
|
||||
<h4 class="st-bme-section-title">Embedding API</h4>
|
||||
|
||||
<div class="st-bme-row">
|
||||
<label for="st_bme_embed_url">API 地址</label>
|
||||
<input
|
||||
type="text"
|
||||
id="st_bme_embed_url"
|
||||
class="text_pole"
|
||||
placeholder="https://api.openai.com/v1"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="st-bme-row">
|
||||
<label for="st_bme_embed_key">API Key</label>
|
||||
<input
|
||||
type="password"
|
||||
id="st_bme_embed_key"
|
||||
class="text_pole"
|
||||
placeholder="sk-..."
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="st-bme-row">
|
||||
<label for="st_bme_embed_model">模型</label>
|
||||
<input
|
||||
type="text"
|
||||
id="st_bme_embed_model"
|
||||
class="text_pole"
|
||||
placeholder="text-embedding-3-small"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="st-bme-row">
|
||||
<button id="st_bme_btn_test_embed" class="menu_button">
|
||||
<i class="fa-solid fa-plug"></i> 测试连接
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="st-bme-hr" />
|
||||
|
||||
<!-- 操控面板 -->
|
||||
<div class="st-bme-section">
|
||||
<h4 class="st-bme-section-title">
|
||||
<i class="fa-solid fa-display"></i> 操控面板
|
||||
</h4>
|
||||
|
||||
<div class="st-bme-row">
|
||||
<label for="st_bme_panel_theme">面板主题</label>
|
||||
<select id="st_bme_panel_theme" class="text_pole">
|
||||
<option value="crimson">🔴 Crimson Synth</option>
|
||||
<option value="cyan">🔵 Neon Cyan</option>
|
||||
<option value="amber">🟡 Amber Console</option>
|
||||
<option value="violet">🟣 Violet Haze</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="st-bme-btn-group">
|
||||
<button id="st_bme_btn_open_panel" class="menu_button">
|
||||
<i class="fa-solid fa-brain"></i> 打开操控面板
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="st-bme-hr" />
|
||||
|
||||
<!-- 操作 -->
|
||||
<div class="st-bme-section">
|
||||
<h4 class="st-bme-section-title">操作</h4>
|
||||
|
||||
<div class="st-bme-btn-group">
|
||||
<button id="st_bme_btn_view_graph" class="menu_button">
|
||||
<i class="fa-solid fa-diagram-project"></i> 查看图谱
|
||||
</button>
|
||||
<button id="st_bme_btn_view_injection" class="menu_button">
|
||||
<i class="fa-solid fa-syringe"></i> 查看注入
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="st-bme-btn-group">
|
||||
<button id="st_bme_btn_rebuild" class="menu_button">
|
||||
<i class="fa-solid fa-rotate"></i> 重建图谱
|
||||
</button>
|
||||
<button id="st_bme_btn_compress" class="menu_button">
|
||||
<i class="fa-solid fa-compress"></i> 手动压缩
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="st-bme-btn-group">
|
||||
<button id="st_bme_btn_export" class="menu_button">
|
||||
<i class="fa-solid fa-download"></i> 导出
|
||||
</button>
|
||||
<button id="st_bme_btn_import" class="menu_button">
|
||||
<i class="fa-solid fa-upload"></i> 导入
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
655
style.css
655
style.css
@@ -1,132 +1,5 @@
|
||||
/* ST-BME 样式 */
|
||||
|
||||
.st-bme-settings {
|
||||
--bme-accent: #e94560;
|
||||
--bme-accent-dim: rgba(233, 69, 96, 0.15);
|
||||
--bme-surface: rgba(255, 255, 255, 0.03);
|
||||
--bme-border: rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
.st-bme-section {
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.st-bme-section-title {
|
||||
font-size: 12px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
color: var(--bme-accent);
|
||||
margin: 0 0 8px 0;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.st-bme-section-title i {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.st-bme-hr {
|
||||
border: none;
|
||||
border-top: 1px solid var(--bme-border);
|
||||
margin: 4px 0;
|
||||
}
|
||||
|
||||
.st-bme-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.st-bme-row label {
|
||||
font-size: 12px;
|
||||
flex-shrink: 0;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.st-bme-row .text_pole {
|
||||
max-width: 180px;
|
||||
}
|
||||
|
||||
.st-bme-row .checkbox_label {
|
||||
justify-content: flex-start;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.st-bme-row.st-bme-indent {
|
||||
padding-left: 24px;
|
||||
}
|
||||
|
||||
.st-bme-btn-group {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
margin: 4px 0;
|
||||
}
|
||||
|
||||
.st-bme-btn-group .menu_button {
|
||||
flex: 1;
|
||||
font-size: 12px;
|
||||
padding: 6px 10px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid var(--bme-border);
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.st-bme-btn-group .menu_button:hover {
|
||||
border-color: var(--bme-accent);
|
||||
background: var(--bme-accent-dim);
|
||||
}
|
||||
|
||||
.st-bme-btn-group .menu_button i {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
/* v2: 子分区 */
|
||||
.st-bme-subsection {
|
||||
position: relative;
|
||||
padding: 6px 0 6px 4px;
|
||||
margin: 4px 0;
|
||||
border-left: 2px solid var(--bme-border);
|
||||
}
|
||||
|
||||
/* v2: 优先级 badge */
|
||||
.st-bme-badge {
|
||||
display: inline-block;
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.5px;
|
||||
padding: 1px 6px;
|
||||
border-radius: 3px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.st-bme-badge-p0 {
|
||||
background: rgba(233, 69, 96, 0.25);
|
||||
color: #e94560;
|
||||
border: 1px solid rgba(233, 69, 96, 0.4);
|
||||
}
|
||||
|
||||
.st-bme-badge-p1 {
|
||||
background: rgba(255, 193, 7, 0.2);
|
||||
color: #ffc107;
|
||||
border: 1px solid rgba(255, 193, 7, 0.35);
|
||||
}
|
||||
|
||||
.st-bme-badge-p2 {
|
||||
background: rgba(76, 175, 80, 0.15);
|
||||
color: #66bb6a;
|
||||
border: 1px solid rgba(76, 175, 80, 0.3);
|
||||
}
|
||||
|
||||
/* v2: 技术来源提示 */
|
||||
.st-bme-hint {
|
||||
font-size: 10px;
|
||||
color: rgba(255, 255, 255, 0.35);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* ==================== 操控面板 ==================== */
|
||||
|
||||
/* --- Overlay --- */
|
||||
#st-bme-panel-overlay {
|
||||
position: fixed;
|
||||
@@ -404,6 +277,89 @@
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.bme-config-sidebar {
|
||||
display: none;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
padding: 18px 12px 16px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.bme-config-sidebar-header {
|
||||
padding: 0 2px;
|
||||
}
|
||||
|
||||
.bme-config-sidebar-kicker,
|
||||
.bme-config-workspace-kicker,
|
||||
.bme-config-section-kicker {
|
||||
font-size: 10px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.9px;
|
||||
color: var(--bme-primary);
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.bme-config-sidebar-title {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
color: var(--bme-on-surface);
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.bme-config-sidebar-help,
|
||||
.bme-config-workspace-desc,
|
||||
.bme-config-section-desc,
|
||||
.bme-config-card-subtitle {
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
color: var(--bme-on-surface-dim);
|
||||
}
|
||||
|
||||
.bme-config-nav {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.bme-config-nav-desktop {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.bme-config-nav-mobile {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.bme-config-nav-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
border: 1px solid var(--bme-border);
|
||||
background: var(--bme-surface-low);
|
||||
color: var(--bme-on-surface-dim);
|
||||
border-radius: 10px;
|
||||
padding: 10px 12px;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.15s, background 0.15s, color 0.15s, transform 0.15s;
|
||||
font-size: 12px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.bme-config-nav-btn:hover {
|
||||
border-color: var(--bme-primary);
|
||||
color: var(--bme-on-surface);
|
||||
background: var(--bme-surface-high);
|
||||
}
|
||||
|
||||
.bme-config-nav-btn.active {
|
||||
border-color: var(--bme-primary);
|
||||
color: var(--bme-primary);
|
||||
background: var(--bme-primary-dim);
|
||||
}
|
||||
|
||||
.bme-config-nav-btn i {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.bme-tab-pane {
|
||||
display: none;
|
||||
}
|
||||
@@ -517,6 +473,41 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.bme-graph-workspace {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.bme-config-workspace {
|
||||
display: none;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
background:
|
||||
radial-gradient(circle at top right, rgba(233, 69, 96, 0.1), transparent 32%),
|
||||
linear-gradient(180deg, rgba(255, 255, 255, 0.02), transparent 20%),
|
||||
var(--bme-surface-lowest, #0e0e11);
|
||||
}
|
||||
|
||||
#st-bme-panel.config-mode .bme-tab-content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#st-bme-panel.config-mode .bme-config-sidebar {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#st-bme-panel.config-mode .bme-graph-workspace {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#st-bme-panel.config-mode .bme-config-workspace {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.bme-graph-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -792,13 +783,82 @@
|
||||
background: rgba(255, 82, 82, 0.1);
|
||||
}
|
||||
|
||||
/* --- Config Tab --- */
|
||||
.bme-config-card {
|
||||
background: var(--bme-surface-low);
|
||||
border: 1px solid var(--bme-border);
|
||||
border-radius: 8px;
|
||||
padding: 12px;
|
||||
margin-bottom: 10px;
|
||||
/* --- Config Workspace --- */
|
||||
.bme-config-workspace-header {
|
||||
padding: 20px 22px 10px;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.04);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.bme-config-workspace-title,
|
||||
.bme-config-section-title {
|
||||
margin: 0;
|
||||
color: var(--bme-on-surface);
|
||||
}
|
||||
|
||||
.bme-config-workspace-title {
|
||||
font-size: 24px;
|
||||
line-height: 1.2;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.bme-config-sections {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 18px 22px 22px;
|
||||
}
|
||||
|
||||
.bme-config-section {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.bme-config-section.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.bme-config-section-head {
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
.bme-config-section-title {
|
||||
font-size: 20px;
|
||||
line-height: 1.25;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.bme-config-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.bme-config-grid-2 {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.bme-config-card,
|
||||
.bme-prompt-card {
|
||||
background: rgba(255, 255, 255, 0.025);
|
||||
border: 1px solid rgba(255, 255, 255, 0.06);
|
||||
border-radius: 14px;
|
||||
padding: 16px;
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.02);
|
||||
}
|
||||
|
||||
.bme-config-card-head,
|
||||
.bme-prompt-card-head {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.bme-config-card-title {
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
color: var(--bme-on-surface);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.bme-config-help {
|
||||
@@ -812,7 +872,11 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
margin-bottom: 10px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.bme-config-row:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.bme-config-row.inline {
|
||||
@@ -821,21 +885,21 @@
|
||||
}
|
||||
|
||||
.bme-config-row label {
|
||||
font-size: 11px;
|
||||
font-size: 12px;
|
||||
color: var(--bme-on-surface);
|
||||
}
|
||||
|
||||
.bme-config-input,
|
||||
.bme-config-textarea {
|
||||
width: 100%;
|
||||
background: var(--bme-surface-lowest);
|
||||
border: 1px solid var(--bme-border);
|
||||
border-radius: 6px;
|
||||
padding: 8px 10px;
|
||||
background: rgba(0, 0, 0, 0.22);
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
border-radius: 10px;
|
||||
padding: 10px 12px;
|
||||
color: var(--bme-on-surface);
|
||||
font-size: 12px;
|
||||
outline: none;
|
||||
transition: border-color 0.15s, box-shadow 0.15s;
|
||||
transition: border-color 0.15s, box-shadow 0.15s, background 0.15s;
|
||||
}
|
||||
|
||||
.bme-config-input:focus,
|
||||
@@ -844,49 +908,215 @@
|
||||
box-shadow: 0 0 0 2px var(--bme-primary-dim);
|
||||
}
|
||||
|
||||
.bme-config-input:disabled,
|
||||
.bme-config-textarea:disabled {
|
||||
background: rgba(255, 255, 255, 0.035);
|
||||
color: rgba(255, 255, 255, 0.45);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.bme-config-textarea {
|
||||
min-height: 140px;
|
||||
min-height: 180px;
|
||||
resize: vertical;
|
||||
line-height: 1.5;
|
||||
line-height: 1.55;
|
||||
font-family: 'Cascadia Code', 'Fira Code', monospace;
|
||||
}
|
||||
|
||||
.bme-prompt-group {
|
||||
margin-top: 8px;
|
||||
border: 1px solid var(--bme-border);
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.bme-prompt-group summary {
|
||||
padding: 8px 12px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: var(--bme-on-surface);
|
||||
background: var(--bme-surface-lowest);
|
||||
user-select: none;
|
||||
transition: background 0.15s;
|
||||
}
|
||||
|
||||
.bme-prompt-group summary:hover {
|
||||
background: var(--bme-surface-low);
|
||||
}
|
||||
|
||||
.bme-prompt-group[open] summary {
|
||||
border-bottom: 1px solid var(--bme-border);
|
||||
}
|
||||
|
||||
.bme-prompt-group .bme-config-textarea {
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
min-height: 120px;
|
||||
}
|
||||
|
||||
.bme-config-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.bme-config-guard-note {
|
||||
display: none;
|
||||
align-self: center;
|
||||
font-size: 11px;
|
||||
color: var(--bme-accent3, #ffc107);
|
||||
background: rgba(255, 193, 7, 0.12);
|
||||
border: 1px solid rgba(255, 193, 7, 0.18);
|
||||
border-radius: 999px;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
.bme-config-guard-note.visible {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.bme-guarded-card.is-disabled {
|
||||
opacity: 0.72;
|
||||
}
|
||||
|
||||
.bme-config-placeholder {
|
||||
background: var(--bme-surface-low);
|
||||
border: 1px dashed var(--bme-border);
|
||||
border-radius: 12px;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.bme-config-placeholder-title {
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
color: var(--bme-on-surface);
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.bme-config-placeholder-help {
|
||||
font-size: 11px;
|
||||
color: var(--bme-on-surface-dim);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.bme-toggle-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.bme-toggle-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
padding: 12px;
|
||||
border-radius: 12px;
|
||||
background: rgba(255, 255, 255, 0.02);
|
||||
border: 1px solid rgba(255, 255, 255, 0.05);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.bme-toggle-item:hover {
|
||||
border-color: rgba(255, 255, 255, 0.12);
|
||||
background: rgba(255, 255, 255, 0.035);
|
||||
}
|
||||
|
||||
.bme-toggle-copy {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.bme-toggle-title {
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
color: var(--bme-on-surface);
|
||||
}
|
||||
|
||||
.bme-toggle-desc {
|
||||
font-size: 11px;
|
||||
line-height: 1.45;
|
||||
color: var(--bme-on-surface-dim);
|
||||
}
|
||||
|
||||
.bme-toggle-item input {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin-top: 2px;
|
||||
flex-shrink: 0;
|
||||
accent-color: var(--bme-primary);
|
||||
}
|
||||
|
||||
.bme-prompt-card-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.bme-prompt-status {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 64px;
|
||||
padding: 4px 10px;
|
||||
border-radius: 999px;
|
||||
background: rgba(255, 255, 255, 0.06);
|
||||
color: var(--bme-on-surface-dim);
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.bme-prompt-status.is-custom {
|
||||
background: var(--bme-primary-dim);
|
||||
color: var(--bme-primary);
|
||||
}
|
||||
|
||||
.bme-prompt-reset:disabled {
|
||||
opacity: 0.45;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.bme-theme-card-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.bme-theme-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
width: 100%;
|
||||
padding: 14px;
|
||||
border-radius: 14px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.07);
|
||||
background: rgba(255, 255, 255, 0.025);
|
||||
color: var(--bme-on-surface);
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.15s, background 0.15s, transform 0.15s;
|
||||
}
|
||||
|
||||
.bme-theme-card:hover {
|
||||
border-color: var(--bme-primary);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.bme-theme-card.active {
|
||||
border-color: var(--bme-primary);
|
||||
background: var(--bme-primary-dim);
|
||||
}
|
||||
|
||||
.bme-theme-card-swatch {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
flex-shrink: 0;
|
||||
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.14);
|
||||
}
|
||||
|
||||
.bme-theme-card-copy {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.bme-theme-card-title {
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.bme-theme-card-desc {
|
||||
font-size: 11px;
|
||||
line-height: 1.45;
|
||||
color: var(--bme-on-surface-dim);
|
||||
}
|
||||
|
||||
.bme-theme-card.active .bme-theme-card-desc {
|
||||
color: var(--bme-primary-text, var(--bme-on-surface));
|
||||
}
|
||||
|
||||
.bme-theme-card-check {
|
||||
opacity: 0;
|
||||
color: var(--bme-primary);
|
||||
}
|
||||
|
||||
.bme-theme-card.active .bme-theme-card-check {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* --- Mobile Bottom Tab Bar --- */
|
||||
@@ -972,18 +1202,24 @@
|
||||
|
||||
/* --- Scrollbar --- */
|
||||
.bme-tab-content::-webkit-scrollbar,
|
||||
.bme-config-sidebar::-webkit-scrollbar,
|
||||
.bme-config-sections::-webkit-scrollbar,
|
||||
.bme-injection-preview::-webkit-scrollbar,
|
||||
.bme-node-detail::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
.bme-tab-content::-webkit-scrollbar-track,
|
||||
.bme-config-sidebar::-webkit-scrollbar-track,
|
||||
.bme-config-sections::-webkit-scrollbar-track,
|
||||
.bme-injection-preview::-webkit-scrollbar-track,
|
||||
.bme-node-detail::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.bme-tab-content::-webkit-scrollbar-thumb,
|
||||
.bme-config-sidebar::-webkit-scrollbar-thumb,
|
||||
.bme-config-sections::-webkit-scrollbar-thumb,
|
||||
.bme-injection-preview::-webkit-scrollbar-thumb,
|
||||
.bme-node-detail::-webkit-scrollbar-thumb {
|
||||
background: var(--bme-surface-highest);
|
||||
@@ -1011,7 +1247,6 @@
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 手机端:sidebar 全宽显示,成为主内容区 */
|
||||
.bme-panel-sidebar {
|
||||
width: 100%;
|
||||
min-width: unset;
|
||||
@@ -1019,27 +1254,81 @@
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
/* 隐藏 sidebar 顶部 tab 列表,改用底部 tab bar */
|
||||
.bme-panel-sidebar > .bme-tab-list {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 手机端 tab content 撑满剩余空间 */
|
||||
.bme-tab-content {
|
||||
padding: 12px 14px;
|
||||
}
|
||||
|
||||
/* 手机端:隐藏桌面端图谱区(大图谱) */
|
||||
.bme-panel-main {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 手机端底部 Tab Bar 显示 */
|
||||
.bme-panel-tabbar {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/* 总览 Tab: 统计卡横向滚动 */
|
||||
.bme-resize-handle,
|
||||
.bme-config-sidebar {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.bme-config-nav-mobile {
|
||||
display: flex;
|
||||
overflow-x: auto;
|
||||
padding: 0 14px 6px;
|
||||
margin-bottom: 4px;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.bme-config-nav-mobile .bme-config-nav-btn {
|
||||
flex: 0 0 auto;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.bme-config-nav-mobile::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.bme-config-workspace-header {
|
||||
padding: 18px 14px 10px;
|
||||
}
|
||||
|
||||
.bme-config-workspace-title {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.bme-config-sections {
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
.bme-config-grid-2,
|
||||
.bme-theme-card-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.bme-config-card-head,
|
||||
.bme-prompt-card-head {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.bme-prompt-card-actions {
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#st-bme-panel.config-mode .bme-panel-sidebar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#st-bme-panel.config-mode .bme-panel-main {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.bme-stats-grid {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
@@ -1053,7 +1342,6 @@
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* 搜索栏改为纵向堆叠 */
|
||||
.bme-search-bar {
|
||||
flex-direction: column;
|
||||
}
|
||||
@@ -1062,7 +1350,6 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* 操作按钮放大触控区域 */
|
||||
.bme-action-btn {
|
||||
padding: 18px 8px;
|
||||
font-size: 12px;
|
||||
@@ -1072,7 +1359,6 @@
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
/* 节点详情:手机端全宽覆盖 */
|
||||
.bme-node-detail {
|
||||
width: 100%;
|
||||
}
|
||||
@@ -1081,7 +1367,6 @@
|
||||
font-size: 9px;
|
||||
}
|
||||
|
||||
/* 手机端图谱预览(嵌在总览 Tab 内) */
|
||||
.bme-mobile-graph-preview {
|
||||
display: block;
|
||||
height: 200px;
|
||||
|
||||
Reference in New Issue
Block a user