Files
ST-Amily2-Chat-Optimisation/core/table-system/formatters/tool-call.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

92 lines
3.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @file formatters/tool-call.js — Function Call 填表格式器
*
* 职责:
* - 导出 TABLE_FILL_TOOL发给模型的 tools 定义(单工具 + operations 数组)
* - 导出 parseToolCallArgs把 tool_calls[0].function.arguments 解析为 Operation[]
*
* 与 executor.jslegacy formatter并列下游 applyOperations 不感知来源。
*
* @typedef {import('../dto/Operation.js').Operation} Operation
*/
/**
* 填表工具 schema。使用 operations 数组而非多工具并发,兼容所有支持 function calling 的提供商。
*
* data 的 key 为列索引字符串("0"、"1"...),与 executor.js legacy 格式保持一致,
* 提示词中会给出列索引与列名的对应关系。
*/
export const TABLE_FILL_TOOL = {
type: 'function',
function: {
name: 'apply_table_edits',
description: '将一批表格编辑操作应用到记忆表格中。',
parameters: {
type: 'object',
properties: {
operations: {
type: 'array',
description: '按顺序执行的操作列表。',
items: {
type: 'object',
properties: {
op: {
type: 'string',
enum: ['insertRow', 'updateRow', 'deleteRow'],
description: 'insertRow=新增行updateRow=更新已有行deleteRow=删除行'
},
tableIndex: {
type: 'integer',
description: '目标表格的 0-based 索引'
},
rowIndex: {
type: 'integer',
description: 'updateRow / deleteRow 时必填,目标行的 0-based 索引'
},
data: {
type: 'object',
description: 'insertRow / updateRow 时必填key 为列索引字符串("0"/"1"...value 为单元格内容',
additionalProperties: { type: 'string' }
}
},
required: ['op', 'tableIndex']
}
}
},
required: ['operations']
}
}
};
/**
* 解析 tool_calls[0].function.arguments 字符串为 Operation[]。
* 结构校验失败的单条操作会被静默跳过,不中断整体解析。
*
* @param {string} argsString - JSON 字符串
* @returns {Operation[]}
*/
export function parseToolCallArgs(argsString) {
let parsed;
try {
parsed = JSON.parse(argsString);
} catch {
return [];
}
const rawOps = parsed?.operations;
if (!Array.isArray(rawOps)) return [];
/** @type {Operation[]} */
const ops = [];
for (const raw of rawOps) {
if (raw.op === 'insertRow' && Number.isInteger(raw.tableIndex) && raw.data && typeof raw.data === 'object') {
ops.push({ op: 'insertRow', tableIndex: raw.tableIndex, data: raw.data });
} else if (raw.op === 'updateRow' && Number.isInteger(raw.tableIndex) && Number.isInteger(raw.rowIndex) && raw.data && typeof raw.data === 'object') {
ops.push({ op: 'updateRow', tableIndex: raw.tableIndex, rowIndex: raw.rowIndex, data: raw.data });
} else if (raw.op === 'deleteRow' && Number.isInteger(raw.tableIndex) && Number.isInteger(raw.rowIndex)) {
ops.push({ op: 'deleteRow', tableIndex: raw.tableIndex, rowIndex: raw.rowIndex });
}
}
return ops;
}