foliko 2.0.8 → 2.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -175,6 +175,63 @@ function validateAll(messages) {
175
175
  return validateMessagesPairing(messages);
176
176
  }
177
177
 
178
+ // AI SDK v6 ToolResultOutput 允许的类型(用于 ModelMessage[] 输入 schema)
179
+ const VALID_OUTPUT_TYPES = new Set(['text', 'json', 'execution-denied', 'content']);
180
+
181
+ /**
182
+ * 规范化 tool-result 的 output 字段。
183
+ * AI SDK v6 响应中允许 'error-text' / 'error-json'(表示工具执行失败),
184
+ * 但 ModelMessage 输入 schema 不接受这两类。需要在发送前 / 持久化前转换。
185
+ *
186
+ * 转换规则:
187
+ * - error-text → text
188
+ * - error-json → json
189
+ * - 任何未知 type → text(保留 value 字段)
190
+ * - output 缺失或非对象 → 包装为 text 'null'
191
+ *
192
+ * @param {Array} messages - 消息数组(会被修改)
193
+ * @returns {number} 规范化次数
194
+ */
195
+ function normalizeToolOutputs(messages) {
196
+ let fixed = 0;
197
+ for (const msg of messages) {
198
+ if (msg.role !== 'tool' || !Array.isArray(msg.content)) continue;
199
+ for (const part of msg.content) {
200
+ if (!part || part.type !== 'tool-result') continue;
201
+ const out = part.output;
202
+ // 缺 output 或 output 非对象:包装为 text
203
+ if (out === undefined || out === null || typeof out !== 'object') {
204
+ const v = out === undefined ? 'undefined' : (typeof out === 'string' ? out : JSON.stringify(out));
205
+ part.output = { type: 'text', value: String(v) };
206
+ fixed++;
207
+ continue;
208
+ }
209
+ // 已知合法 type:跳过
210
+ if (VALID_OUTPUT_TYPES.has(out.type)) continue;
211
+ // error-text → text(保留原 value 字符串)
212
+ if (out.type === 'error-text' || out.type === 'error_text') {
213
+ part.output = { type: 'text', value: typeof out.value === 'string' ? out.value : String(out.value ?? '') };
214
+ fixed++;
215
+ continue;
216
+ }
217
+ // error-json → json
218
+ if (out.type === 'error-json' || out.type === 'error_json') {
219
+ part.output = { type: 'json', value: out.value ?? null };
220
+ fixed++;
221
+ continue;
222
+ }
223
+ // 其它未知 type:降级为 text(保留 value 字符串或 JSON 序列化)
224
+ try {
225
+ part.output = { type: 'text', value: JSON.stringify(out) };
226
+ } catch {
227
+ part.output = { type: 'text', value: String(out) };
228
+ }
229
+ fixed++;
230
+ }
231
+ }
232
+ return fixed;
233
+ }
234
+
178
235
  /**
179
236
  * 过滤消息,保留配对的 tool-call → tool-result 链条
180
237
  * 用于上下文压缩后保留完整的工具调用链路
@@ -283,5 +340,6 @@ module.exports = {
283
340
  validateMessagesPairing,
284
341
  validateToolCalls,
285
342
  validateAll,
343
+ normalizeToolOutputs,
286
344
  filterPairedMessages,
287
345
  };