@jsonstudio/llms 0.6.3275 → 0.6.3379

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.
Files changed (48) hide show
  1. package/dist/conversion/bridge-message-utils.d.ts +4 -4
  2. package/dist/conversion/bridge-message-utils.js +28 -538
  3. package/dist/conversion/compat/profiles/responses-crs.json +15 -0
  4. package/dist/conversion/hub/operation-table/semantic-mappers/chat-mapper.js +16 -5
  5. package/dist/conversion/hub/pipeline/stages/resp_process/resp_process_stage1_tool_governance/index.js +1 -6
  6. package/dist/conversion/hub/response/response-runtime.js +14 -6
  7. package/dist/conversion/responses/responses-openai-bridge/response-payload.js +11 -11
  8. package/dist/conversion/shared/anthropic-message-utils.js +2 -12
  9. package/dist/conversion/shared/chat-request-filters.js +2 -61
  10. package/dist/conversion/shared/reasoning-mapping.js +3 -0
  11. package/dist/conversion/shared/reasoning-normalizer.d.ts +1 -0
  12. package/dist/conversion/shared/reasoning-normalizer.js +35 -388
  13. package/dist/conversion/shared/reasoning-tool-normalizer.js +8 -15
  14. package/dist/conversion/shared/reasoning-utils.js +13 -35
  15. package/dist/conversion/shared/responses-tool-utils.d.ts +1 -1
  16. package/dist/conversion/shared/responses-tool-utils.js +63 -65
  17. package/dist/conversion/shared/streaming-text-extractor.d.ts +0 -5
  18. package/dist/conversion/shared/streaming-text-extractor.js +18 -111
  19. package/dist/conversion/shared/text-markup-normalizer/normalize.d.ts +1 -1
  20. package/dist/conversion/shared/text-markup-normalizer/normalize.js +3 -91
  21. package/dist/conversion/shared/thought-signature-validator.js +19 -133
  22. package/dist/conversion/shared/tool-argument-repairer.js +16 -19
  23. package/dist/conversion/shared/tool-call-id-manager.d.ts +1 -5
  24. package/dist/conversion/shared/tool-call-id-manager.js +74 -98
  25. package/dist/conversion/shared/tool-harvester.js +19 -382
  26. package/dist/conversion/shared/tool-mapping.d.ts +2 -3
  27. package/dist/conversion/shared/tool-mapping.js +28 -184
  28. package/dist/conversion/shared/tooling.js +20 -151
  29. package/dist/filters/special/response-tool-arguments-stringify.js +9 -1
  30. package/dist/guidance/index.js +2 -2
  31. package/dist/native/router_hotpath_napi.node +0 -0
  32. package/dist/router/virtual-router/engine-legacy/helpers.js +1 -1
  33. package/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics.d.ts +39 -0
  34. package/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics.js +196 -0
  35. package/dist/router/virtual-router/engine-selection/native-hub-pipeline-req-inbound-semantics.d.ts +1 -0
  36. package/dist/router/virtual-router/engine-selection/native-hub-pipeline-req-inbound-semantics.js +27 -0
  37. package/dist/router/virtual-router/engine-selection/native-router-hotpath-loader.js +34 -0
  38. package/dist/router/virtual-router/engine-selection/native-shared-conversion-semantics.d.ts +65 -1
  39. package/dist/router/virtual-router/engine-selection/native-shared-conversion-semantics.js +836 -35
  40. package/dist/router/virtual-router/engine.js +3 -2
  41. package/dist/router/virtual-router/routing-instructions/parse.js +30 -3
  42. package/dist/sse/sse-to-json/builders/anthropic-response-builder.js +28 -3
  43. package/dist/sse/types/anthropic-types.d.ts +3 -1
  44. package/dist/tools/apply-patch/args-normalizer/extract-patch.js +2 -2
  45. package/dist/tools/apply-patch/patch-text/looks-like-patch.js +3 -6
  46. package/dist/tools/apply-patch/patch-text/normalize.js +14 -3
  47. package/dist/tools/tool-registry.js +12 -0
  48. package/package.json +6 -1
@@ -4,13 +4,15 @@
4
4
  * 提供严格的 thoughtSignature 验证功能,用于 Claude/Gemini thinking 块的签名验证。
5
5
  * 参考 gcli2api 的实现,确保与上游 API 的兼容性。
6
6
  */
7
- import { sanitizeReasoningTaggedTextWithNative } from '../../router/virtual-router/engine-selection/native-shared-conversion-semantics.js';
8
- const DEFAULT_OPTIONS = {
9
- // Antigravity-Manager alignment: treat short signatures as noise.
10
- minLength: 50,
11
- allowEmptyThinkingWithSignature: true,
12
- convertToTextOnFailure: true
13
- };
7
+ import { filterInvalidThinkingBlocksWithNative, hasValidThoughtSignatureWithNative, removeTrailingUnsignedThinkingBlocksWithNative, sanitizeThinkingBlockWithNative } from '../../router/virtual-router/engine-selection/native-shared-conversion-semantics.js';
8
+ function assertThoughtSignatureValidatorNativeAvailable() {
9
+ if (typeof hasValidThoughtSignatureWithNative !== 'function' ||
10
+ typeof sanitizeThinkingBlockWithNative !== 'function' ||
11
+ typeof filterInvalidThinkingBlocksWithNative !== 'function' ||
12
+ typeof removeTrailingUnsignedThinkingBlocksWithNative !== 'function') {
13
+ throw new Error('[thought-signature-validator] native bindings unavailable');
14
+ }
15
+ }
14
16
  /**
15
17
  * 检查 thinking 块是否有有效的 thoughtSignature
16
18
  *
@@ -19,26 +21,8 @@ const DEFAULT_OPTIONS = {
19
21
  * @returns 是否有效
20
22
  */
21
23
  export function hasValidThoughtSignature(block, options) {
22
- if (!block || typeof block !== 'object') {
23
- return true; // 非 thinking 块默认有效
24
- }
25
- const obj = block;
26
- const blockType = obj.type;
27
- if (blockType !== 'thinking' && blockType !== 'reasoning' && blockType !== 'redacted_thinking') {
28
- return true; // 非 thinking 块默认有效
29
- }
30
- const opts = { ...DEFAULT_OPTIONS, ...options };
31
- const thinking = sanitizeReasoningTaggedTextWithNative(String(obj.thinking || obj.text || ''));
32
- const signature = coerceThoughtSignature(obj.thoughtSignature || obj.signature);
33
- // 空 thinking + 任意签名 = 有效 (trailing signature case)
34
- if (!thinking.trim() && signature !== undefined && opts.allowEmptyThinkingWithSignature) {
35
- return true;
36
- }
37
- // 有内容 + 足够长度的 signature = 有效
38
- if (signature && signature.length >= opts.minLength) {
39
- return true;
40
- }
41
- return false;
24
+ assertThoughtSignatureValidatorNativeAvailable();
25
+ return hasValidThoughtSignatureWithNative(block, options);
42
26
  }
43
27
  /**
44
28
  * 清理 thinking 块,移除额外字段,保留有效签名
@@ -47,23 +31,8 @@ export function hasValidThoughtSignature(block, options) {
47
31
  * @returns 清理后的块
48
32
  */
49
33
  export function sanitizeThinkingBlock(block) {
50
- if (!block || typeof block !== 'object') {
51
- return block;
52
- }
53
- const obj = block;
54
- const blockType = obj.type;
55
- if (blockType !== 'thinking' && blockType !== 'reasoning' && blockType !== 'redacted_thinking') {
56
- return obj;
57
- }
58
- const sanitized = {
59
- type: blockType,
60
- thinking: sanitizeReasoningTaggedTextWithNative(String(obj.thinking || obj.text || ''))
61
- };
62
- const signature = coerceThoughtSignature(obj.thoughtSignature || obj.signature);
63
- if (signature) {
64
- sanitized.thoughtSignature = signature;
65
- }
66
- return sanitized;
34
+ assertThoughtSignatureValidatorNativeAvailable();
35
+ return sanitizeThinkingBlockWithNative(block);
67
36
  }
68
37
  /**
69
38
  * 过滤消息中的无效 thinking 块
@@ -72,58 +41,9 @@ export function sanitizeThinkingBlock(block) {
72
41
  * @param options - 验证选项
73
42
  */
74
43
  export function filterInvalidThinkingBlocks(messages, options) {
75
- const opts = { ...DEFAULT_OPTIONS, ...options };
76
- let totalFiltered = 0;
77
- for (const msg of messages) {
78
- if (!msg || typeof msg !== 'object')
79
- continue;
80
- const msgObj = msg;
81
- const role = msgObj.role;
82
- // 只处理 assistant 和 model 消息
83
- if (role !== 'assistant' && role !== 'model')
84
- continue;
85
- const content = msgObj.content;
86
- if (!Array.isArray(content))
87
- continue;
88
- const originalLen = content.length;
89
- const newBlocks = [];
90
- for (const block of content) {
91
- if (!block || typeof block !== 'object') {
92
- newBlocks.push(block);
93
- continue;
94
- }
95
- const blockType = block.type;
96
- if (blockType !== 'thinking' && blockType !== 'reasoning' && blockType !== 'redacted_thinking') {
97
- newBlocks.push(block);
98
- continue;
99
- }
100
- // 检查 thinking 块的有效性
101
- if (hasValidThoughtSignature(block, opts)) {
102
- // 有效签名,清理后保留
103
- newBlocks.push(sanitizeThinkingBlock(block));
104
- }
105
- else {
106
- // 无效签名
107
- const thinkingText = String(block.thinking || block.text || '');
108
- if (thinkingText.trim() && opts.convertToTextOnFailure) {
109
- // 有内容,转换为文本
110
- newBlocks.push({ type: 'text', text: thinkingText });
111
- }
112
- // 否则丢弃(空 thinking + 无效签名)
113
- }
114
- }
115
- msgObj.content = newBlocks;
116
- const filteredCount = originalLen - newBlocks.length;
117
- totalFiltered += filteredCount;
118
- // 如果过滤后为空,添加一个空文本块以保持消息有效
119
- if (!newBlocks.length) {
120
- msgObj.content = [{ type: 'text', text: '' }];
121
- }
122
- }
123
- if (totalFiltered > 0) {
124
- // 可以在这里添加日志记录
125
- console.debug(`[ThoughtSignatureValidator] Filtered ${totalFiltered} invalid thinking block(s)`);
126
- }
44
+ assertThoughtSignatureValidatorNativeAvailable();
45
+ const normalized = filterInvalidThinkingBlocksWithNative(messages, options);
46
+ messages.splice(0, messages.length, ...normalized);
127
47
  }
128
48
  /**
129
49
  * 移除末尾未签名的 thinking 块
@@ -132,41 +52,7 @@ export function filterInvalidThinkingBlocks(messages, options) {
132
52
  * @param options - 验证选项
133
53
  */
134
54
  export function removeTrailingUnsignedThinkingBlocks(blocks, options) {
135
- if (!Array.isArray(blocks) || !blocks.length)
136
- return;
137
- const opts = { ...DEFAULT_OPTIONS, ...options };
138
- let end_index = blocks.length;
139
- // 从末尾向前查找第一个有效签名的 thinking 块
140
- for (let i = blocks.length - 1; i >= 0; i--) {
141
- const block = blocks[i];
142
- if (!block || typeof block !== 'object')
143
- continue;
144
- const blockType = block.type;
145
- if (blockType === 'thinking' || blockType === 'reasoning' || blockType === 'redacted_thinking') {
146
- if (!hasValidThoughtSignature(block, opts)) {
147
- end_index = i;
148
- }
149
- else {
150
- break; // 遇到有效签名的 thinking 块,停止
151
- }
152
- }
153
- else {
154
- break; // 遇到非 thinking 块,停止
155
- }
156
- }
157
- // 移除末尾未签名的 thinking 块
158
- if (end_index < blocks.length) {
159
- const removed = blocks.length - end_index;
160
- blocks.splice(end_index);
161
- console.debug(`[ThoughtSignatureValidator] Removed ${removed} trailing unsigned thinking block(s)`);
162
- }
163
- }
164
- /**
165
- * 提取并强制转换 thoughtSignature
166
- */
167
- function coerceThoughtSignature(value) {
168
- if (typeof value === 'string' && value.trim().length) {
169
- return value.trim();
170
- }
171
- return undefined;
55
+ assertThoughtSignatureValidatorNativeAvailable();
56
+ const normalized = removeTrailingUnsignedThinkingBlocksWithNative(blocks, options);
57
+ blocks.splice(0, blocks.length, ...normalized);
172
58
  }
@@ -7,27 +7,24 @@
7
7
  * This module provides a deterministic, best-effort repair surface that returns a JSON string
8
8
  * or `{}` and never throws.
9
9
  */
10
- import { repairArgumentsToStringWithNative } from '../../router/virtual-router/engine-selection/native-shared-conversion-semantics.js';
10
+ import { repairArgumentsToStringWithNative, repairToolCallsWithNative, validateToolArgumentsWithNative } from '../../router/virtual-router/engine-selection/native-shared-conversion-semantics.js';
11
11
  export class ToolArgumentRepairer {
12
12
  repairToString(args) {
13
+ if (typeof repairArgumentsToStringWithNative !== 'function') {
14
+ throw new Error('[tool-argument-repairer] native bindings unavailable');
15
+ }
13
16
  return repairArgumentsToStringWithNative(args);
14
17
  }
15
18
  validateAndRepair(toolName, args) {
16
- const repaired = this.repairToString(args);
17
- try {
18
- JSON.parse(repaired);
19
- return {
20
- repaired,
21
- success: true
22
- };
23
- }
24
- catch (error) {
25
- return {
26
- repaired,
27
- success: false,
28
- error: error instanceof Error ? error.message : String(error)
29
- };
19
+ if (typeof validateToolArgumentsWithNative !== 'function') {
20
+ throw new Error('[tool-argument-repairer] native bindings unavailable');
30
21
  }
22
+ const output = validateToolArgumentsWithNative(toolName, args);
23
+ return {
24
+ repaired: output.repaired,
25
+ success: output.success,
26
+ ...(output.error ? { error: output.error } : {})
27
+ };
31
28
  }
32
29
  /**
33
30
  * 批量修复工具参数
@@ -36,10 +33,10 @@ export class ToolArgumentRepairer {
36
33
  * @returns 修复后的工具调用列表
37
34
  */
38
35
  repairToolCalls(toolCalls) {
39
- return toolCalls.map((call) => ({
40
- name: call.name,
41
- arguments: this.repairToString(call.arguments)
42
- }));
36
+ if (typeof repairToolCallsWithNative !== 'function') {
37
+ throw new Error('[tool-argument-repairer] native bindings unavailable');
38
+ }
39
+ return repairToolCallsWithNative(toolCalls);
43
40
  }
44
41
  }
45
42
  /**
@@ -29,7 +29,7 @@ export interface ToolCallIdManagerOptions {
29
29
  */
30
30
  export declare class ToolCallIdManager {
31
31
  private options;
32
- private counter;
32
+ private state;
33
33
  constructor(options?: ToolCallIdManagerOptions);
34
34
  /**
35
35
  * 生成新的工具调用 ID
@@ -77,10 +77,6 @@ export declare class ToolCallIdManager {
77
77
  * 更新配置
78
78
  */
79
79
  updateOptions(options: Partial<ToolCallIdManagerOptions>): void;
80
- /**
81
- * 生成 UUID(用于 preserve 风格)
82
- */
83
- private generateUUID;
84
80
  }
85
81
  /**
86
82
  * 规范化工具调用 ID 值
@@ -4,30 +4,42 @@
4
4
  * 提供统一的工具调用 ID 生成、规范化和风格管理功能。
5
5
  * 支持 'fc' (function call) 和 'preserve' 两种风格。
6
6
  */
7
- import { normalizeFunctionCallIdWithNative } from '../../router/virtual-router/engine-selection/native-shared-conversion-semantics.js';
7
+ import { createToolCallIdTransformerWithNative, enforceToolCallIdStyleWithNative, extractToolCallIdWithNative, normalizeIdValueWithNative, transformToolCallIdWithNative } from '../../router/virtual-router/engine-selection/native-shared-conversion-semantics.js';
8
8
  const DEFAULT_OPTIONS = {
9
9
  style: 'fc',
10
10
  prefix: 'fc_',
11
11
  idLength: 8
12
12
  };
13
+ function assertToolCallIdManagerNativeAvailable() {
14
+ if (typeof normalizeIdValueWithNative !== 'function' ||
15
+ typeof extractToolCallIdWithNative !== 'function' ||
16
+ typeof createToolCallIdTransformerWithNative !== 'function' ||
17
+ typeof transformToolCallIdWithNative !== 'function' ||
18
+ typeof enforceToolCallIdStyleWithNative !== 'function') {
19
+ throw new Error('[tool-call-id-manager] native bindings unavailable');
20
+ }
21
+ }
13
22
  /**
14
23
  * 工具调用 ID 管理器
15
24
  */
16
25
  export class ToolCallIdManager {
17
26
  options;
18
- counter = 0;
27
+ state;
19
28
  constructor(options) {
29
+ assertToolCallIdManagerNativeAvailable();
20
30
  this.options = { ...DEFAULT_OPTIONS, ...options };
31
+ this.state = createToolCallIdTransformerWithNative(this.options.style);
21
32
  }
22
33
  /**
23
34
  * 生成新的工具调用 ID
24
35
  */
25
36
  generateId() {
37
+ assertToolCallIdManagerNativeAvailable();
26
38
  if (this.options.style === 'fc') {
27
- return `${this.options.prefix}${this.counter++}`;
39
+ const next = transformToolCallIdWithNative(this.state, '').id;
40
+ return next;
28
41
  }
29
- // preserve 风格:使用 UUID
30
- return this.generateUUID();
42
+ return normalizeIdValueWithNative(undefined, true);
31
43
  }
32
44
  /**
33
45
  * 规范化工具调用 ID
@@ -36,21 +48,15 @@ export class ToolCallIdManager {
36
48
  * @returns 规范化后的 ID
37
49
  */
38
50
  normalizeId(id) {
39
- if (!id) {
40
- return this.generateId();
41
- }
42
- const trimmed = id.trim();
43
- if (!trimmed) {
44
- return this.generateId();
45
- }
51
+ assertToolCallIdManagerNativeAvailable();
52
+ const raw = typeof id === 'string' ? id : '';
46
53
  if (this.options.style === 'fc') {
47
- return normalizeFunctionCallIdWithNative({
48
- callId: trimmed,
49
- fallback: this.generateId()
50
- });
54
+ const output = transformToolCallIdWithNative(this.state, raw);
55
+ this.state = output.state;
56
+ return output.id;
51
57
  }
52
- // preserve 风格:保留原始 ID
53
- return trimmed;
58
+ const trimmed = raw.trim();
59
+ return trimmed ? trimmed : normalizeIdValueWithNative(undefined, true);
54
60
  }
55
61
  /**
56
62
  * 规范化工具调用 ID(带别名注册)
@@ -60,22 +66,20 @@ export class ToolCallIdManager {
60
66
  * @returns 规范化后的 ID
61
67
  */
62
68
  normalizeIdWithAlias(id, aliasMap) {
63
- if (!id) {
64
- return this.generateId();
65
- }
66
- const trimmed = id.trim();
67
- if (!trimmed) {
68
- return this.generateId();
69
+ assertToolCallIdManagerNativeAvailable();
70
+ const raw = typeof id === 'string' ? id : '';
71
+ if (this.options.style !== 'preserve') {
72
+ return this.normalizeId(raw);
69
73
  }
70
- if (this.options.style === 'fc') {
71
- return this.normalizeId(id);
72
- }
73
- // preserve 风格:检查是否已有别名
74
- if (aliasMap && aliasMap.has(trimmed)) {
74
+ const trimmed = raw.trim();
75
+ if (trimmed && aliasMap && aliasMap.has(trimmed)) {
75
76
  return aliasMap.get(trimmed);
76
77
  }
77
- // 没有别名,保留原始 ID
78
- return trimmed;
78
+ const value = trimmed || normalizeIdValueWithNative(undefined, true);
79
+ if (trimmed && aliasMap) {
80
+ aliasMap.set(trimmed, value);
81
+ }
82
+ return value;
79
83
  }
80
84
  /**
81
85
  * 批量规范化工具调用 ID
@@ -84,7 +88,7 @@ export class ToolCallIdManager {
84
88
  * @returns 规范化后的 ID 列表
85
89
  */
86
90
  normalizeIds(ids) {
87
- return ids.map(id => this.normalizeId(id));
91
+ return ids.map((id) => this.normalizeId(id));
88
92
  }
89
93
  /**
90
94
  * 检查 ID 是否为有效的 fc_ 风格
@@ -106,7 +110,7 @@ export class ToolCallIdManager {
106
110
  * 重置计数器
107
111
  */
108
112
  resetCounter() {
109
- this.counter = 0;
113
+ this.state = createToolCallIdTransformerWithNative(this.options.style);
110
114
  }
111
115
  /**
112
116
  * 获取当前配置
@@ -119,17 +123,7 @@ export class ToolCallIdManager {
119
123
  */
120
124
  updateOptions(options) {
121
125
  this.options = { ...this.options, ...options };
122
- }
123
- /**
124
- * 生成 UUID(用于 preserve 风格)
125
- */
126
- generateUUID() {
127
- // 简单的 UUID 生成(生产环境建议使用 crypto.randomUUID())
128
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
129
- const r = Math.random() * 16 | 0;
130
- const v = c === 'x' ? r : (r & 0x3 | 0x8);
131
- return v.toString(16);
132
- });
126
+ this.state = createToolCallIdTransformerWithNative(this.options.style);
133
127
  }
134
128
  }
135
129
  /**
@@ -140,16 +134,8 @@ export class ToolCallIdManager {
140
134
  * @returns 规范化后的 ID 字符串
141
135
  */
142
136
  export function normalizeIdValue(value, forceGenerate = false) {
143
- if (forceGenerate) {
144
- const manager = new ToolCallIdManager();
145
- return manager.generateId();
146
- }
147
- if (typeof value === 'string' && value.trim()) {
148
- return value.trim();
149
- }
150
- // 生成默认 ID
151
- const manager = new ToolCallIdManager();
152
- return manager.generateId();
137
+ assertToolCallIdManagerNativeAvailable();
138
+ return normalizeIdValueWithNative(value, forceGenerate);
153
139
  }
154
140
  /**
155
141
  * 从对象中提取工具调用 ID
@@ -158,16 +144,8 @@ export function normalizeIdValue(value, forceGenerate = false) {
158
144
  * @returns 提取的 ID
159
145
  */
160
146
  export function extractToolCallId(obj) {
161
- if (!obj || typeof obj !== 'object') {
162
- return undefined;
163
- }
164
- const record = obj;
165
- // 按优先级查找:tool_call_id > call_id > id > tool_use_id
166
- const id = record.tool_call_id ??
167
- record.call_id ??
168
- record.id ??
169
- record.tool_use_id;
170
- return typeof id === 'string' ? id : undefined;
147
+ assertToolCallIdManagerNativeAvailable();
148
+ return extractToolCallIdWithNative(obj);
171
149
  }
172
150
  /**
173
151
  * 创建工具调用 ID 转换器(用于 Responses 格式)
@@ -176,22 +154,15 @@ export function extractToolCallId(obj) {
176
154
  * @returns 转换器函数
177
155
  */
178
156
  export function createToolCallIdTransformer(style) {
179
- const manager = new ToolCallIdManager({ style });
180
- const aliasMap = new Map();
181
- if (style === 'fc') {
182
- return (id) => manager.normalizeId(id);
183
- }
184
- if (style === 'preserve') {
185
- return (id) => {
186
- const normalized = manager.normalizeIdWithAlias(id, aliasMap);
187
- // 如果 ID 是新的,注册别名
188
- if (!aliasMap.has(id)) {
189
- aliasMap.set(id, normalized);
190
- }
191
- return normalized;
192
- };
193
- }
194
- return null;
157
+ assertToolCallIdManagerNativeAvailable();
158
+ if (style !== 'fc' && style !== 'preserve')
159
+ return null;
160
+ const state = createToolCallIdTransformerWithNative(style);
161
+ return (id) => {
162
+ const output = transformToolCallIdWithNative(state, id);
163
+ Object.assign(state, output.state);
164
+ return output.id;
165
+ };
195
166
  }
196
167
  /**
197
168
  * 在消息列表中强制应用工具调用 ID 风格
@@ -200,30 +171,35 @@ export function createToolCallIdTransformer(style) {
200
171
  * @param transformer - ID 转换器
201
172
  */
202
173
  export function enforceToolCallIdStyle(messages, transformer) {
174
+ assertToolCallIdManagerNativeAvailable();
203
175
  if (!messages || !Array.isArray(messages)) {
204
176
  return;
205
177
  }
206
- for (const message of messages) {
207
- if (!message || typeof message !== 'object')
208
- continue;
209
- const role = message.role;
210
- // 处理 assistant 消息的 tool_calls
211
- if (role === 'assistant' && Array.isArray(message.tool_calls)) {
212
- for (const call of message.tool_calls) {
213
- if (!call || typeof call !== 'object')
214
- continue;
215
- const id = extractToolCallId(call);
216
- if (id) {
217
- call.id = transformer(id);
178
+ const state = createToolCallIdTransformerWithNative('fc');
179
+ const updated = enforceToolCallIdStyleWithNative(messages, state);
180
+ const nextMessages = updated.messages;
181
+ if (transformer && typeof transformer === 'function') {
182
+ for (const message of nextMessages) {
183
+ if (!message || typeof message !== 'object')
184
+ continue;
185
+ const role = message.role;
186
+ if (role === 'assistant' && Array.isArray(message.tool_calls)) {
187
+ for (const call of message.tool_calls) {
188
+ if (!call || typeof call !== 'object')
189
+ continue;
190
+ const id = extractToolCallId(call);
191
+ if (id) {
192
+ call.id = transformer(id);
193
+ }
218
194
  }
219
195
  }
220
- }
221
- // 处理 tool 消息的 tool_call_id
222
- if (role === 'tool') {
223
- const id = extractToolCallId(message);
224
- if (id) {
225
- message.tool_call_id = transformer(id);
196
+ if (role === 'tool') {
197
+ const id = extractToolCallId(message);
198
+ if (id) {
199
+ message.tool_call_id = transformer(id);
200
+ }
226
201
  }
227
202
  }
228
203
  }
204
+ messages.splice(0, messages.length, ...nextMessages);
229
205
  }