release: v2.2.4 [2026-05-30 13:03:07]

### 新功能
- **Function Call 填表**:
  - FC 首次请求时对 DeepSeek 系模型自动附加 `thinking: { type: "disabled" }`,避免思考模式与 tool_choice 冲突
  - 操作列表为空时在日志面板输出原始响应 JSON,便于区分"AI 判断无需变更"、"格式校验全部不通过"和"JSON 解析失败"三种情况
### 修复
- **剧情优化**:移除剧情优化页面遗留的 Jqyh 直连配置字段(URL / Key / Model),统一走 API 连接配置功能分配槽位
- **表格**:
  - 补全 `batch-filling-threshold` 批处理阈值的持久化绑定(页面刷新后不再还原为默认值 30)
  - 修复分步填表并发锁与 async/await 时序问题
  - 修复外层多余 `try...finally` 导致的插件加载报错
- **Rerank**:
  - 修复选择连接配置后报"API Key 未配置"的问题(`apiMode` 现从设置读取而非硬编码 `custom`)
  - 补全 `hly-rerank-api-mode` 加载绑定及默认值
- **翰林院 RAG**:补全 `priorityRetrieval.sources` 各来源条目的缺失键,修复设置面板回填 TypeError
- **二次填表**:
  - 修复 `secondary-filler.js` 把哈希/重试次数写入非持久化的 `msg.metadata` 字段(ST 标准位是 `msg.extra`),导致刷新后去重与重试计数失效
  - 修复扫描深度重复计入 `bufferSize`(`contextLimit + buffer + batch + redundancy` → `contextLimit + batch + redundancy`),避免越过预期窗口
  - SWIPED 事件改走扫描路径,不再用 `targetMessage` bypass 强填最末条,`保留缓冲区(bufferSize)` 设置在滑动场景下正确生效(手动"回退重填"按钮仍保留 bypass,意图明确)
  - 修复 FC(Function Call)路径下成功填表与"AI 判断无需修改"两种结果均未写回 `amily2_process_hash` 与 `saveChat()` 的问题——之前导致 FC 模式去重完全失效,最旧的未处理楼层会被每次扫描重复发给 AI;现统一回写路径为 `markTargetsProcessed`
  - FC 空操作时同步输出原始响应 JSON 到控制台(与批量回填日志面板保持一致),便于区分"无需变更"/"格式校验失败"/"JSON 解析失败"
This commit is contained in:
Jenkins CI
2026-05-30 13:03:07 +08:00
parent e66544f774
commit 59c4adc1c0
6 changed files with 30 additions and 11 deletions

View File

@@ -39,10 +39,9 @@ async function requestSecondaryContinuation(baseMessages, partialResponse) {
return `${partialResponse || ''}${continued}`;
}
async function commitSecondaryFillResult(rawContent, targetMessages) {
await updateTableFromText(rawContent);
async function markTargetsProcessed(targetMessages, { skipTableSave = false } = {}) {
if (!targetMessages || targetMessages.length === 0) return;
const memoryState = getMemoryState();
const lastProcessedMsg = targetMessages[targetMessages.length - 1].msg;
for (const target of targetMessages) {
@@ -50,14 +49,22 @@ async function commitSecondaryFillResult(rawContent, targetMessages) {
target.msg.extra.amily2_process_hash = target.hash;
}
if (saveStateToMessage(memoryState, lastProcessedMsg)) {
renderTables();
updateOrInsertTableInChat();
if (!skipTableSave) {
const memoryState = getMemoryState();
if (saveStateToMessage(memoryState, lastProcessedMsg)) {
renderTables();
updateOrInsertTableInChat();
}
}
await saveChat();
}
async function commitSecondaryFillResult(rawContent, targetMessages) {
await updateTableFromText(rawContent);
await markTargetsProcessed(targetMessages);
}
async function getWorldBookContext() {
const settings = extension_settings[extensionName] || {};
@@ -369,10 +376,20 @@ export async function fillWithSecondaryApi(latestMessage, forceRun = false, opts
}
const ops = parseToolCallArgs(argsString);
if (ops.length === 0) {
console.warn('[Amily2-副API] Function Call 返回操作列表为空,无需变更。');
let parseHint = '';
try {
const rawParsed = JSON.parse(argsString);
const rawOpsLen = rawParsed?.operations?.length ?? 0;
if (rawOpsLen > 0) parseHint = `(响应含 ${rawOpsLen} 条操作,但全部未通过格式校验)`;
} catch {
parseHint = '(响应 JSON 解析失败)';
}
console.warn(`[Amily2-副API] Function Call 返回操作列表为空${parseHint},原始响应:\n${argsString}`);
toastr.info('AI 判断此范围无需修改。', 'Amily2-分步填表');
await markTargetsProcessed(targetMessages, { skipTableSave: true });
} else {
await updateTableFromOps(ops);
await markTargetsProcessed(targetMessages);
toastr.success('分步填表Function Call执行完毕。', 'Amily2-分步填表');
}
} else {