Files
ST-Amily2-Chat-Optimisation/ui/rule-config-bindings.js
Jenkins CI 2c3072a3d8 release: v2.2.2 [2026-05-27 11:10:55]
### 新功能
- **Function Call 填表模式**:在填表设置中新增独立开关,启用后支持通过 OpenAI 兼容接口(DeepSeek / OpenRouter / 各类中转等)直接返回结构化操作列表,绕过 `<Amily2Edit>` 文本解析路径,填表更稳定
  - 遇到不支持 `tool_choice` 的接口时自动降级重试
  - 对思考模型注入强制调用指令,防止绕过工具直接输出文本
  - 全部走 ST 后端代理,修复 CSP 拦截直连外部 URL 的问题
- **主界面新增提示词链编辑器入口**,同时调换了记忆管理与角色世界书的按钮位置
- **规则中心**新增"自动排除用户楼层"选项
### 修复
- 提示词链按钮点击无响应(改为事件委托方式绑定)
- 拖拽组件微抖误触发(加 5px 移动阈值过滤)
- 填表检查窗若干问题修复;翰林院(批量回填)修复;防抖逻辑落地
- 角色世界书入口添加使用警告弹窗(强制 10 秒倒计时),提示该功能长期未维护
- ApiProfile `fakeStream` 字段保存丢失问题
- 正文优化默认改为关闭状态
- NGMS / NCCS API 配置槽位标签修正(NGMS→总结,NCCS→填表)
- API Profile 面板选择逻辑统一重构,修复多处旧字段覆盖新配置的问题
- 世界书控制参数兼容性修复(排除递归、插入位置、扫描深度等,适配 ST 1.17.0+)
2026-05-27 11:10:55 +08:00

155 lines
5.3 KiB
JavaScript

import { ruleProfileManager } from '../utils/config/RuleProfileManager.js';
let currentEditingId = null;
function createEmptyProfile() {
return {
id: '',
name: '',
tagExtractionEnabled: false,
tags: '',
exclusionRules: [],
excludeUserMessages: false,
};
}
function createRuleRow(rule = { start: '', end: '' }, index = 0) {
return `
<div class="amily2-rule-row" data-index="${index}">
<input type="text" class="text_pole amily2-rule-start" value="${escapeHtml(rule.start || '')}" placeholder="起始标记">
<input type="text" class="text_pole amily2-rule-end" value="${escapeHtml(rule.end || '')}" placeholder="结束标记">
<button type="button" class="menu_button danger small_button amily2-rule-remove">
<i class="fas fa-trash-alt"></i>
</button>
</div>
`;
}
function escapeHtml(text) {
return String(text ?? '')
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;');
}
function renderRules(container, exclusionRules = []) {
const list = container.find('#amily2_rule_profile_rules');
if (!exclusionRules.length) {
list.html('<p class="notes">当前没有排除规则。</p>');
return;
}
list.html(exclusionRules.map((rule, index) => createRuleRow(rule, index)).join(''));
}
function collectProfile(container) {
const exclusionRules = [];
container.find('.amily2-rule-row').each(function () {
const start = $(this).find('.amily2-rule-start').val().trim();
const end = $(this).find('.amily2-rule-end').val().trim();
if (start) {
exclusionRules.push({ start, end });
}
});
return {
id: currentEditingId || '',
name: container.find('#amily2_rule_profile_name').val().trim(),
tagExtractionEnabled: container.find('#amily2_rule_profile_tag_toggle').is(':checked'),
tags: container.find('#amily2_rule_profile_tags').val(),
exclusionRules,
excludeUserMessages: container.find('#amily2_rule_profile_exclude_user').is(':checked'),
};
}
function renderProfileList(container) {
const list = container.find('#amily2_rule_profile_list');
const profiles = ruleProfileManager.listProfiles();
if (!profiles.length) {
list.html('<p class="notes">还没有规则配置。</p>');
return;
}
list.html(profiles.map(profile => `
<button type="button" class="menu_button wide_button amily2-rule-profile-item" data-id="${profile.id}">
<span>${escapeHtml(profile.name || profile.id)}</span>
</button>
`).join(''));
}
function fillEditor(container, profile) {
const current = profile || createEmptyProfile();
currentEditingId = current.id || null;
container.find('#amily2_rule_profile_name').val(current.name || '');
container.find('#amily2_rule_profile_tag_toggle').prop('checked', !!current.tagExtractionEnabled);
container.find('#amily2_rule_profile_tags').val(current.tags || '');
container.find('#amily2_rule_profile_tags_wrap').toggle(!!current.tagExtractionEnabled);
container.find('#amily2_rule_profile_exclude_user').prop('checked', !!current.excludeUserMessages);
renderRules(container, current.exclusionRules || []);
}
export function bindRuleConfigPanel(container) {
const $c = $(container);
renderProfileList($c);
fillEditor($c, createEmptyProfile());
$c.off('.ruleConfig');
$c.on('click.ruleConfig', '#amily2_rule_profile_new', () => {
fillEditor($c, createEmptyProfile());
});
$c.on('click.ruleConfig', '.amily2-rule-profile-item', function () {
const profile = ruleProfileManager.getProfile($(this).data('id'));
if (profile) {
fillEditor($c, profile);
}
});
$c.on('change.ruleConfig', '#amily2_rule_profile_tag_toggle', function () {
$c.find('#amily2_rule_profile_tags_wrap').toggle(this.checked);
});
$c.on('click.ruleConfig', '#amily2_rule_profile_add_rule', () => {
const rules = collectProfile($c).exclusionRules;
rules.push({ start: '', end: '' });
renderRules($c, rules);
});
$c.on('click.ruleConfig', '.amily2-rule-remove', function () {
$(this).closest('.amily2-rule-row').remove();
if ($c.find('.amily2-rule-row').length === 0) {
renderRules($c, []);
}
});
$c.on('click.ruleConfig', '#amily2_rule_profile_save', () => {
const profile = collectProfile($c);
if (!profile.name) {
toastr.warning('请先填写规则配置名称。');
return;
}
const saved = ruleProfileManager.saveProfile(profile);
fillEditor($c, saved);
renderProfileList($c);
toastr.success('规则配置已保存。');
});
$c.on('click.ruleConfig', '#amily2_rule_profile_delete', () => {
if (!currentEditingId) {
return;
}
if (!confirm('删除当前规则配置?引用它的位置会回退到旧配置。')) {
return;
}
ruleProfileManager.deleteProfile(currentEditingId);
fillEditor($c, createEmptyProfile());
renderProfileList($c);
toastr.success('规则配置已删除。');
});
}