mirror of
https://github.com/Wx-2025/ST-Amily2-Chat-Optimisation.git
synced 2026-06-07 12:05:51 +00:00
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+)
This commit is contained in:
@@ -161,9 +161,151 @@ export function showSummaryModal(summaryText, callbacks) {
|
||||
regenerateButton.on('click', () => {
|
||||
if (onRegenerate) {
|
||||
dialogElement[0].close();
|
||||
onRegenerate(dialogElement);
|
||||
onRegenerate(dialogElement);
|
||||
}
|
||||
});
|
||||
|
||||
dialogElement.find('.popup-controls').prepend(regenerateButton);
|
||||
}
|
||||
|
||||
|
||||
export function showTableFillReviewModal(rawResponse, callbacks = {}) {
|
||||
const {
|
||||
title = '填表响应检查',
|
||||
subtitle = 'AI未返回有效的 <Amily2Edit> 指令块。您可以在下方查看/编辑原始响应,并选择后续处理方式。',
|
||||
onApply,
|
||||
onContinue,
|
||||
onRetry,
|
||||
onCancel,
|
||||
} = callbacks;
|
||||
|
||||
const modalHtml = `
|
||||
<div class="amily2-fill-review-modal">
|
||||
<div class="notes" style="margin-bottom: 10px; color: #ffb74d; line-height: 1.6;">
|
||||
<i class="fas fa-exclamation-triangle"></i> ${escapeHtml(subtitle)}
|
||||
</div>
|
||||
<textarea class="text_pole amily2-fill-review-text"
|
||||
style="width: 100%; height: 45vh; resize: vertical; font-family: var(--monoFontFamily, monospace); font-size: 12px; white-space: pre; overflow-wrap: normal; overflow-x: auto;"
|
||||
>${escapeHtml(rawResponse || '')}</textarea>
|
||||
<div class="notes" style="margin-top: 8px; font-size: 0.85em; opacity: 0.8; line-height: 1.6;">
|
||||
<div><b>继续补全</b>:让 AI 基于当前文本继续生成剩余内容,结果会追加到文本框后。</div>
|
||||
<div><b>重新填表</b>:舍弃当前响应并重新向 AI 请求同一批次的填表。</div>
|
||||
<div><b>手动应用</b>:将文本框中的当前内容直接作为最终结果写入表格(跳过格式校验)。</div>
|
||||
<div><b>取消</b>:放弃本次填表,任务暂停。</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const dialogElement = showHtmlModal(title, modalHtml, {
|
||||
okText: '手动应用',
|
||||
cancelText: '取消',
|
||||
showCancel: true,
|
||||
onOk: (dialog) => {
|
||||
const editedText = dialog.find('.amily2-fill-review-text').val();
|
||||
if (onApply) {
|
||||
onApply(editedText);
|
||||
}
|
||||
},
|
||||
onCancel: () => {
|
||||
if (onCancel) {
|
||||
onCancel();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const textarea = dialogElement.find('.amily2-fill-review-text');
|
||||
|
||||
if (typeof onContinue === 'function') {
|
||||
const continueButton = $('<button class="menu_button interactable" style="margin-right: auto;"><i class="fas fa-forward"></i> 继续补全</button>');
|
||||
continueButton.on('click', async () => {
|
||||
const currentText = textarea.val();
|
||||
textarea.prop('disabled', true);
|
||||
continueButton.prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i> 正在请求补全...');
|
||||
try {
|
||||
const continued = await onContinue(currentText);
|
||||
if (typeof continued === 'string' && continued.length > 0) {
|
||||
textarea.val(continued);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[Amily2 填表检查] 补全请求失败:', err);
|
||||
if (window.toastr) toastr.error(`补全失败: ${err.message || err}`, '继续补全');
|
||||
} finally {
|
||||
textarea.prop('disabled', false);
|
||||
continueButton.prop('disabled', false).html('<i class="fas fa-forward"></i> 继续补全');
|
||||
}
|
||||
});
|
||||
dialogElement.find('.popup-controls').prepend(continueButton);
|
||||
}
|
||||
|
||||
if (typeof onRetry === 'function') {
|
||||
const retryButton = $('<button class="menu_button secondary interactable"><i class="fas fa-redo"></i> 重新填表</button>');
|
||||
retryButton.on('click', () => {
|
||||
dialogElement[0].close();
|
||||
dialogElement.remove();
|
||||
onRetry();
|
||||
});
|
||||
const okBtn = dialogElement.find('.popup-button-ok');
|
||||
if (okBtn.length) {
|
||||
retryButton.insertBefore(okBtn);
|
||||
} else {
|
||||
dialogElement.find('.popup-controls').append(retryButton);
|
||||
}
|
||||
}
|
||||
|
||||
return dialogElement;
|
||||
}
|
||||
|
||||
const CWB_WARNING_COUNTDOWN = 10;
|
||||
|
||||
/**
|
||||
* 角色世界书入口警告弹窗,强制倒计时后才可继续。
|
||||
* @param {Function} onProceed - 用户点击"继续使用"时的回调
|
||||
* @param {Function} onClose - 用户点击"关闭退出"时的回调(含弹窗关闭前直接离开)
|
||||
*/
|
||||
export function showCwbWarningModal(onProceed, onClose) {
|
||||
const dialogHtml = `
|
||||
<dialog class="popup wide_dialogue_popup">
|
||||
<div class="popup-body">
|
||||
<h3 style="margin-top:0; color:#e8a838; border-bottom:1px solid rgba(255,255,255,0.2); padding-bottom:10px;">
|
||||
<i class="fas fa-exclamation-triangle" style="color:#e8a838;"></i> 注意 — 角色世界书功能维护状态
|
||||
</h3>
|
||||
<div style="line-height:1.8; padding:12px 4px; color:var(--SmartThemeBodyColor);">
|
||||
该功能长期未进行维护且其实现可被表格及其他功能替代,若非必须一般不建议使用,如确认希望使用,请明确该功能无法获得有效技术支持。
|
||||
</div>
|
||||
<div class="popup-controls" style="gap:8px;">
|
||||
<button class="cwb-warning-close menu_button secondary interactable">关闭退出</button>
|
||||
<button class="cwb-warning-proceed menu_button menu_button_primary interactable" disabled>
|
||||
继续使用(<span class="cwb-countdown">${CWB_WARNING_COUNTDOWN}</span>)
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>`;
|
||||
|
||||
const $dialog = $(dialogHtml).appendTo('body');
|
||||
|
||||
const close = (cb) => {
|
||||
clearInterval(timer);
|
||||
$dialog[0].close();
|
||||
$dialog.remove();
|
||||
cb?.();
|
||||
};
|
||||
|
||||
$dialog.find('.cwb-warning-close').on('click', () => close(onClose));
|
||||
|
||||
$dialog.find('.cwb-warning-proceed').on('click', function () {
|
||||
if (!this.disabled) close(onProceed);
|
||||
});
|
||||
|
||||
let remaining = CWB_WARNING_COUNTDOWN;
|
||||
const timer = setInterval(() => {
|
||||
remaining -= 1;
|
||||
$dialog.find('.cwb-countdown').text(remaining);
|
||||
if (remaining <= 0) {
|
||||
clearInterval(timer);
|
||||
const $btn = $dialog.find('.cwb-warning-proceed');
|
||||
$btn.prop('disabled', false).html('继续使用');
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
$dialog[0].showModal();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user