@jsonstudio/llms 0.6.3275 → 0.6.3405
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.
- package/dist/conversion/bridge-message-utils.d.ts +4 -4
- package/dist/conversion/bridge-message-utils.js +28 -538
- package/dist/conversion/compat/actions/claude-thinking-tools.d.ts +1 -14
- package/dist/conversion/compat/actions/claude-thinking-tools.js +3 -71
- package/dist/conversion/compat/actions/lmstudio-responses-fc-ids.d.ts +0 -8
- package/dist/conversion/compat/actions/lmstudio-responses-fc-ids.js +2 -57
- package/dist/conversion/compat/actions/normalize-tool-call-ids.d.ts +0 -9
- package/dist/conversion/compat/actions/normalize-tool-call-ids.js +6 -136
- package/dist/conversion/compat/actions/request-rules.js +2 -61
- package/dist/conversion/compat/actions/response-blacklist.d.ts +0 -4
- package/dist/conversion/compat/actions/response-blacklist.js +2 -77
- package/dist/conversion/compat/actions/response-normalize.js +2 -119
- package/dist/conversion/compat/actions/response-validate.js +2 -74
- package/dist/conversion/compat/actions/strip-orphan-function-calls-tag.js +2 -150
- package/dist/conversion/compat/profiles/responses-crs.json +15 -0
- package/dist/conversion/hub/operation-table/semantic-mappers/anthropic-mapper.js +24 -1
- package/dist/conversion/hub/operation-table/semantic-mappers/chat-mapper.js +16 -5
- package/dist/conversion/hub/pipeline/hub-pipeline.js +91 -0
- package/dist/conversion/hub/pipeline/stages/resp_process/resp_process_stage1_tool_governance/index.js +1 -6
- package/dist/conversion/hub/response/response-runtime.js +14 -6
- package/dist/conversion/responses/responses-openai-bridge/response-payload.js +11 -11
- package/dist/conversion/shared/anthropic-message-utils.js +2 -12
- package/dist/conversion/shared/chat-request-filters.js +2 -61
- package/dist/conversion/shared/reasoning-mapping.js +3 -0
- package/dist/conversion/shared/reasoning-normalizer.d.ts +1 -0
- package/dist/conversion/shared/reasoning-normalizer.js +35 -388
- package/dist/conversion/shared/reasoning-tool-normalizer.js +8 -15
- package/dist/conversion/shared/reasoning-tool-parser.js +7 -8
- package/dist/conversion/shared/reasoning-utils.js +13 -35
- package/dist/conversion/shared/responses-response-utils.js +3 -48
- package/dist/conversion/shared/responses-tool-utils.d.ts +1 -1
- package/dist/conversion/shared/responses-tool-utils.js +74 -180
- package/dist/conversion/shared/streaming-text-extractor.d.ts +0 -5
- package/dist/conversion/shared/streaming-text-extractor.js +18 -111
- package/dist/conversion/shared/text-markup-normalizer/normalize.d.ts +1 -1
- package/dist/conversion/shared/text-markup-normalizer/normalize.js +3 -91
- package/dist/conversion/shared/thought-signature-validator.js +19 -133
- package/dist/conversion/shared/tool-argument-repairer.js +16 -19
- package/dist/conversion/shared/tool-call-id-manager.d.ts +1 -5
- package/dist/conversion/shared/tool-call-id-manager.js +74 -98
- package/dist/conversion/shared/tool-harvester.js +19 -382
- package/dist/conversion/shared/tool-mapping.d.ts +2 -3
- package/dist/conversion/shared/tool-mapping.js +28 -184
- package/dist/conversion/shared/tooling.js +20 -151
- package/dist/filters/special/response-tool-arguments-stringify.js +9 -1
- package/dist/guidance/index.js +2 -2
- package/dist/native/router_hotpath_napi.node +0 -0
- package/dist/router/virtual-router/bootstrap/web-search-config.js +25 -0
- package/dist/router/virtual-router/bootstrap.js +21 -16
- package/dist/router/virtual-router/engine-legacy/helpers.js +1 -1
- package/dist/router/virtual-router/engine-selection/native-compat-action-semantics.d.ts +6 -0
- package/dist/router/virtual-router/engine-selection/native-compat-action-semantics.js +171 -0
- package/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics.d.ts +39 -0
- package/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics.js +196 -0
- package/dist/router/virtual-router/engine-selection/native-hub-pipeline-req-inbound-semantics.d.ts +1 -0
- package/dist/router/virtual-router/engine-selection/native-hub-pipeline-req-inbound-semantics.js +27 -0
- package/dist/router/virtual-router/engine-selection/native-router-hotpath-loader.js +45 -0
- package/dist/router/virtual-router/engine-selection/native-shared-conversion-semantics.d.ts +70 -1
- package/dist/router/virtual-router/engine-selection/native-shared-conversion-semantics.js +993 -55
- package/dist/router/virtual-router/engine.js +3 -2
- package/dist/router/virtual-router/routing-instructions/parse.js +30 -3
- package/dist/router/virtual-router/types.d.ts +23 -0
- package/dist/servertool/handlers/web-search.js +26 -1
- package/dist/servertool/server-side-tools.js +11 -2
- package/dist/servertool/types.d.ts +4 -0
- package/dist/sse/sse-to-json/builders/anthropic-response-builder.js +28 -3
- package/dist/sse/types/anthropic-types.d.ts +3 -1
- package/dist/tools/apply-patch/args-normalizer/extract-patch.js +2 -2
- package/dist/tools/apply-patch/patch-text/looks-like-patch.js +3 -6
- package/dist/tools/apply-patch/patch-text/normalize.js +14 -3
- package/dist/tools/tool-registry.js +12 -0
- package/package.json +6 -1
|
@@ -1,409 +1,56 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { extractReasoningSegments } from './reasoning-utils.js';
|
|
3
|
-
import { expandResponsesMessageItem } from '../../sse/shared/responses-output-normalizer.js';
|
|
4
|
-
import { sanitizeReasoningTaggedTextWithNative } from '../../router/virtual-router/engine-selection/native-shared-conversion-semantics.js';
|
|
1
|
+
import { normalizeReasoningInAnthropicPayloadWithNative, normalizeReasoningInChatPayloadWithNative, normalizeReasoningInGeminiPayloadWithNative, normalizeReasoningInOpenAIPayloadWithNative, normalizeReasoningInResponsesPayloadWithNative } from '../../router/virtual-router/engine-selection/native-shared-conversion-semantics.js';
|
|
5
2
|
export const RESPONSES_INSTRUCTIONS_REASONING_FIELD = '__rcc_reasoning_instructions';
|
|
6
|
-
function
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
if (Array.isArray(payload.messages)) {
|
|
14
|
-
payload.messages = payload.messages.map(entry => normalizeChatMessageEntry(entry));
|
|
15
|
-
}
|
|
16
|
-
if (Array.isArray(payload.choices)) {
|
|
17
|
-
payload.choices.forEach(choice => {
|
|
18
|
-
normalizeChatChoice(choice);
|
|
19
|
-
});
|
|
3
|
+
function assertReasoningNormalizerNativeAvailable() {
|
|
4
|
+
if (typeof normalizeReasoningInChatPayloadWithNative !== 'function' ||
|
|
5
|
+
typeof normalizeReasoningInResponsesPayloadWithNative !== 'function' ||
|
|
6
|
+
typeof normalizeReasoningInGeminiPayloadWithNative !== 'function' ||
|
|
7
|
+
typeof normalizeReasoningInAnthropicPayloadWithNative !== 'function' ||
|
|
8
|
+
typeof normalizeReasoningInOpenAIPayloadWithNative !== 'function') {
|
|
9
|
+
throw new Error('[reasoning-normalizer] native bindings unavailable');
|
|
20
10
|
}
|
|
21
11
|
}
|
|
22
|
-
function
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
const msg = entry;
|
|
27
|
-
applyNormalizedChatContent(msg);
|
|
28
|
-
return msg;
|
|
29
|
-
}
|
|
30
|
-
function normalizeChatChoice(choice) {
|
|
31
|
-
if (!choice || typeof choice !== 'object') {
|
|
12
|
+
export function normalizeReasoningInChatPayload(payload) {
|
|
13
|
+
assertReasoningNormalizerNativeAvailable();
|
|
14
|
+
if (!payload)
|
|
32
15
|
return;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if (record.message && typeof record.message === 'object') {
|
|
37
|
-
containers.push(record.message);
|
|
38
|
-
}
|
|
39
|
-
if (record.delta && typeof record.delta === 'object') {
|
|
40
|
-
containers.push(record.delta);
|
|
41
|
-
}
|
|
42
|
-
containers.forEach(container => applyNormalizedChatContent(container));
|
|
43
|
-
}
|
|
44
|
-
function applyNormalizedChatContent(container) {
|
|
45
|
-
const existingReasoning = typeof container.reasoning_content === 'string' && container.reasoning_content.trim().length
|
|
46
|
-
? container.reasoning_content.trim()
|
|
47
|
-
: undefined;
|
|
48
|
-
const normalized = normalizeChatMessageContent(container.content);
|
|
49
|
-
const role = typeof container.role === 'string' ? container.role : undefined;
|
|
50
|
-
if (normalized.contentText !== undefined && normalized.contentText.trim().length) {
|
|
51
|
-
container.content = normalized.contentText;
|
|
52
|
-
}
|
|
53
|
-
else if (typeof container.reasoning_content === 'string' && container.reasoning_content.trim().length) {
|
|
54
|
-
container.content = container.reasoning_content.trim();
|
|
55
|
-
}
|
|
56
|
-
else if (role && role !== 'system' && role !== 'tool') {
|
|
57
|
-
container.content = '';
|
|
58
|
-
}
|
|
59
|
-
if (normalized.reasoningText && normalized.reasoningText.trim().length) {
|
|
60
|
-
container.reasoning_content = normalized.reasoningText.trim();
|
|
61
|
-
}
|
|
62
|
-
else if (existingReasoning) {
|
|
63
|
-
container.reasoning_content = existingReasoning;
|
|
64
|
-
}
|
|
65
|
-
else if ('reasoning_content' in container) {
|
|
66
|
-
delete container.reasoning_content;
|
|
16
|
+
const normalized = normalizeReasoningInChatPayloadWithNative(payload);
|
|
17
|
+
if (normalized && typeof normalized === 'object') {
|
|
18
|
+
Object.assign(payload, normalized);
|
|
67
19
|
}
|
|
68
20
|
}
|
|
69
21
|
export function normalizeReasoningInResponsesPayload(payload, options = { includeOutput: true }) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
const includeOutput = options.includeOutput !== false;
|
|
74
|
-
if (includeOutput) {
|
|
75
|
-
normalizeResponsesOutput(payload);
|
|
76
|
-
}
|
|
77
|
-
if (options.includeInput) {
|
|
78
|
-
normalizeResponsesInput(payload);
|
|
79
|
-
}
|
|
80
|
-
if (options.includeInstructions) {
|
|
81
|
-
normalizeResponsesInstructions(payload);
|
|
82
|
-
}
|
|
83
|
-
if (options.includeRequiredAction) {
|
|
84
|
-
normalizeResponsesRequiredAction(payload);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
function normalizeResponsesOutput(payload) {
|
|
88
|
-
if (!Array.isArray(payload.output)) {
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
const normalized = [];
|
|
92
|
-
payload.output.forEach((entry, index) => {
|
|
93
|
-
if (isResponsesMessageItem(entry)) {
|
|
94
|
-
const expanded = expandResponsesMessageItem(entry, {
|
|
95
|
-
requestId: typeof payload.id === 'string' ? payload.id : 'responses',
|
|
96
|
-
outputIndex: index
|
|
97
|
-
});
|
|
98
|
-
expanded.forEach((item) => {
|
|
99
|
-
normalized.push(item);
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
else {
|
|
103
|
-
normalized.push(entry);
|
|
104
|
-
}
|
|
105
|
-
});
|
|
106
|
-
payload.output = normalized;
|
|
107
|
-
}
|
|
108
|
-
function isResponsesMessageItem(entry) {
|
|
109
|
-
if (!isRecord(entry)) {
|
|
110
|
-
return false;
|
|
111
|
-
}
|
|
112
|
-
const type = typeof entry.type === 'string' ? entry.type : undefined;
|
|
113
|
-
if (type !== 'message') {
|
|
114
|
-
return false;
|
|
115
|
-
}
|
|
116
|
-
if (!Array.isArray(entry.content)) {
|
|
117
|
-
return false;
|
|
118
|
-
}
|
|
119
|
-
const status = typeof entry.status === 'string' ? entry.status : undefined;
|
|
120
|
-
const role = typeof entry.role === 'string' ? entry.role : undefined;
|
|
121
|
-
return Boolean(status && role);
|
|
122
|
-
}
|
|
123
|
-
function normalizeResponsesInput(payload) {
|
|
124
|
-
if (!Array.isArray(payload.input)) {
|
|
22
|
+
assertReasoningNormalizerNativeAvailable();
|
|
23
|
+
if (!payload)
|
|
125
24
|
return;
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
return;
|
|
130
|
-
const reasoningSegments = [];
|
|
131
|
-
if (typeof entry.content === 'string') {
|
|
132
|
-
const { cleaned, segments } = stripReasoningFromString(entry.content);
|
|
133
|
-
entry.content = cleaned;
|
|
134
|
-
reasoningSegments.push(...segments);
|
|
135
|
-
}
|
|
136
|
-
else if (Array.isArray(entry.content)) {
|
|
137
|
-
entry.content = entry.content.map((block) => normalizeResponsesContentBlock(block, reasoningSegments));
|
|
138
|
-
}
|
|
139
|
-
if (isRecord(entry.message)) {
|
|
140
|
-
normalizeResponsesMessageBlock(entry.message, reasoningSegments);
|
|
141
|
-
}
|
|
142
|
-
if (typeof entry.text === 'string') {
|
|
143
|
-
const { cleaned, segments } = stripReasoningFromString(entry.text);
|
|
144
|
-
entry.text = cleaned;
|
|
145
|
-
reasoningSegments.push(...segments);
|
|
146
|
-
}
|
|
147
|
-
if (reasoningSegments.length) {
|
|
148
|
-
entry.reasoning_content = mergeReasoningText(entry.reasoning_content, reasoningSegments);
|
|
149
|
-
}
|
|
150
|
-
else if ('reasoning_content' in entry) {
|
|
151
|
-
delete entry.reasoning_content;
|
|
152
|
-
}
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
function normalizeResponsesMessageBlock(message, collector) {
|
|
156
|
-
const localSegments = [];
|
|
157
|
-
if (Array.isArray(message.content)) {
|
|
158
|
-
message.content = message.content.map((block) => normalizeResponsesContentBlock(block, localSegments));
|
|
159
|
-
}
|
|
160
|
-
else if (typeof message.content === 'string') {
|
|
161
|
-
const { cleaned, segments } = stripReasoningFromString(message.content);
|
|
162
|
-
message.content = cleaned;
|
|
163
|
-
localSegments.push(...segments);
|
|
164
|
-
}
|
|
165
|
-
if (typeof message.text === 'string') {
|
|
166
|
-
const { cleaned, segments } = stripReasoningFromString(message.text);
|
|
167
|
-
message.text = cleaned;
|
|
168
|
-
localSegments.push(...segments);
|
|
169
|
-
}
|
|
170
|
-
if (localSegments.length) {
|
|
171
|
-
collector.push(...localSegments);
|
|
172
|
-
message.reasoning_content = mergeReasoningText(message.reasoning_content, localSegments);
|
|
173
|
-
}
|
|
174
|
-
else if ('reasoning_content' in message) {
|
|
175
|
-
delete message.reasoning_content;
|
|
25
|
+
const normalized = normalizeReasoningInResponsesPayloadWithNative(payload, options);
|
|
26
|
+
if (normalized && typeof normalized === 'object') {
|
|
27
|
+
Object.assign(payload, normalized);
|
|
176
28
|
}
|
|
177
29
|
}
|
|
178
|
-
function normalizeResponsesContentBlock(block, collector) {
|
|
179
|
-
if (typeof block === 'string') {
|
|
180
|
-
const { cleaned, segments } = stripReasoningFromString(block);
|
|
181
|
-
collector.push(...segments);
|
|
182
|
-
return cleaned;
|
|
183
|
-
}
|
|
184
|
-
if (!isRecord(block)) {
|
|
185
|
-
return block;
|
|
186
|
-
}
|
|
187
|
-
const type = typeof block.type === 'string' ? block.type.toLowerCase() : '';
|
|
188
|
-
if ((type === 'input_text' || type === 'output_text' || type === 'text' || type === 'commentary') && typeof block.text === 'string') {
|
|
189
|
-
const { cleaned, segments } = stripReasoningFromString(block.text);
|
|
190
|
-
block.text = cleaned;
|
|
191
|
-
if (segments.length) {
|
|
192
|
-
collector.push(...segments);
|
|
193
|
-
block.reasoning_content = mergeReasoningText(block.reasoning_content, segments);
|
|
194
|
-
}
|
|
195
|
-
else if ('reasoning_content' in block) {
|
|
196
|
-
delete block.reasoning_content;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
if (Array.isArray(block.content)) {
|
|
200
|
-
block.content = block.content.map((nested) => normalizeResponsesContentBlock(nested, collector));
|
|
201
|
-
}
|
|
202
|
-
else if (typeof block.content === 'string') {
|
|
203
|
-
const { cleaned, segments } = stripReasoningFromString(block.content);
|
|
204
|
-
block.content = cleaned;
|
|
205
|
-
if (segments.length) {
|
|
206
|
-
collector.push(...segments);
|
|
207
|
-
block.reasoning_content = mergeReasoningText(block.reasoning_content, segments);
|
|
208
|
-
}
|
|
209
|
-
else if ('reasoning_content' in block) {
|
|
210
|
-
delete block.reasoning_content;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
return block;
|
|
214
|
-
}
|
|
215
|
-
function normalizeResponsesInstructions(payload) {
|
|
216
|
-
if (typeof payload.instructions !== 'string') {
|
|
217
|
-
if (RESPONSES_INSTRUCTIONS_REASONING_FIELD in payload) {
|
|
218
|
-
delete payload[RESPONSES_INSTRUCTIONS_REASONING_FIELD];
|
|
219
|
-
}
|
|
220
|
-
return;
|
|
221
|
-
}
|
|
222
|
-
const { cleaned, segments } = stripReasoningFromString(payload.instructions);
|
|
223
|
-
payload.instructions = cleaned;
|
|
224
|
-
if (segments.length) {
|
|
225
|
-
payload[RESPONSES_INSTRUCTIONS_REASONING_FIELD] = segments.join('\n');
|
|
226
|
-
}
|
|
227
|
-
else if (RESPONSES_INSTRUCTIONS_REASONING_FIELD in payload) {
|
|
228
|
-
delete payload[RESPONSES_INSTRUCTIONS_REASONING_FIELD];
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
function normalizeResponsesRequiredAction(payload) {
|
|
232
|
-
if (!isRecord(payload.required_action)) {
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
const submit = payload.required_action.submit_tool_outputs;
|
|
236
|
-
if (!submit || typeof submit !== 'object') {
|
|
237
|
-
return;
|
|
238
|
-
}
|
|
239
|
-
const toolCalls = Array.isArray(submit.tool_calls)
|
|
240
|
-
? submit.tool_calls
|
|
241
|
-
: [];
|
|
242
|
-
toolCalls.forEach((call) => {
|
|
243
|
-
if (!isRecord(call))
|
|
244
|
-
return;
|
|
245
|
-
if (typeof call.instructions === 'string') {
|
|
246
|
-
const { cleaned, segments } = stripReasoningFromString(call.instructions);
|
|
247
|
-
call.instructions = cleaned;
|
|
248
|
-
if (segments.length) {
|
|
249
|
-
call.reasoning_content = mergeReasoningText(call.reasoning_content, segments);
|
|
250
|
-
}
|
|
251
|
-
else if ('reasoning_content' in call) {
|
|
252
|
-
delete call.reasoning_content;
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
});
|
|
256
|
-
}
|
|
257
|
-
function stripReasoningFromString(value) {
|
|
258
|
-
if (typeof value !== 'string') {
|
|
259
|
-
return { cleaned: typeof value === 'string' ? value : '', segments: [] };
|
|
260
|
-
}
|
|
261
|
-
const segments = [];
|
|
262
|
-
const cleaned = extractReasoningSegments(value, segments);
|
|
263
|
-
const cleanedNative = sanitizeReasoningTaggedTextWithNative(value);
|
|
264
|
-
const stableCleaned = typeof cleanedNative === 'string' ? cleanedNative : cleaned;
|
|
265
|
-
return { cleaned: stableCleaned, segments };
|
|
266
|
-
}
|
|
267
|
-
function mergeReasoningText(existing, segments) {
|
|
268
|
-
const combined = [];
|
|
269
|
-
if (typeof existing === 'string' && existing.trim().length) {
|
|
270
|
-
combined.push(existing.trim());
|
|
271
|
-
}
|
|
272
|
-
for (const segment of segments) {
|
|
273
|
-
if (typeof segment === 'string' && segment.trim().length) {
|
|
274
|
-
combined.push(segment.trim());
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
return combined.join('\n');
|
|
278
|
-
}
|
|
279
30
|
export function normalizeReasoningInGeminiPayload(payload) {
|
|
280
|
-
|
|
31
|
+
assertReasoningNormalizerNativeAvailable();
|
|
32
|
+
if (!payload)
|
|
281
33
|
return;
|
|
34
|
+
const normalized = normalizeReasoningInGeminiPayloadWithNative(payload);
|
|
35
|
+
if (normalized && typeof normalized === 'object') {
|
|
36
|
+
Object.assign(payload, normalized);
|
|
282
37
|
}
|
|
283
|
-
const contents = Array.isArray(payload.contents) ? payload.contents : [];
|
|
284
|
-
contents.forEach((content) => {
|
|
285
|
-
if (!isRecord(content))
|
|
286
|
-
return;
|
|
287
|
-
const parts = Array.isArray(content.parts) ? content.parts : [];
|
|
288
|
-
parts.forEach((part) => {
|
|
289
|
-
if (!isRecord(part) || typeof part.text !== 'string') {
|
|
290
|
-
return;
|
|
291
|
-
}
|
|
292
|
-
const reasoningSegments = [];
|
|
293
|
-
const cleaned = extractReasoningSegments(part.text, reasoningSegments);
|
|
294
|
-
part.text = cleaned;
|
|
295
|
-
if (reasoningSegments.length) {
|
|
296
|
-
part.reasoning = reasoningSegments.join('\n');
|
|
297
|
-
}
|
|
298
|
-
else if ('reasoning' in part) {
|
|
299
|
-
delete part.reasoning;
|
|
300
|
-
}
|
|
301
|
-
});
|
|
302
|
-
});
|
|
303
38
|
}
|
|
304
39
|
export function normalizeReasoningInAnthropicPayload(payload) {
|
|
305
|
-
|
|
40
|
+
assertReasoningNormalizerNativeAvailable();
|
|
41
|
+
if (!payload)
|
|
306
42
|
return;
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
const responseReasoning = [];
|
|
311
|
-
responseContent.forEach((block) => normalizeAnthropicBlock(block, responseReasoning));
|
|
312
|
-
if (responseReasoning.length) {
|
|
313
|
-
payload.reasoning_content = mergeReasoningText(payload.reasoning_content, responseReasoning);
|
|
314
|
-
}
|
|
315
|
-
else if ('reasoning_content' in payload) {
|
|
316
|
-
delete payload.reasoning_content;
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
const messages = Array.isArray(payload.messages) ? payload.messages : [];
|
|
320
|
-
messages.forEach((message) => {
|
|
321
|
-
if (!isRecord(message))
|
|
322
|
-
return;
|
|
323
|
-
normalizeAnthropicMessage(message);
|
|
324
|
-
});
|
|
325
|
-
const systemField = payload.system;
|
|
326
|
-
if (typeof systemField === 'string') {
|
|
327
|
-
const { cleaned } = stripReasoningFromString(systemField);
|
|
328
|
-
payload.system = cleaned;
|
|
329
|
-
}
|
|
330
|
-
else if (Array.isArray(systemField)) {
|
|
331
|
-
systemField.forEach((entry) => normalizeAnthropicBlock(entry, []));
|
|
332
|
-
}
|
|
333
|
-
else if (isRecord(systemField) && Array.isArray(systemField.content)) {
|
|
334
|
-
const sysBlocks = systemField.content;
|
|
335
|
-
systemField.content = sysBlocks.map((block) => {
|
|
336
|
-
normalizeAnthropicBlock(block, []);
|
|
337
|
-
return block;
|
|
338
|
-
});
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
function normalizeAnthropicMessage(message) {
|
|
342
|
-
const reasoningSegments = [];
|
|
343
|
-
if (Array.isArray(message.content)) {
|
|
344
|
-
message.content.forEach((block) => normalizeAnthropicBlock(block, reasoningSegments));
|
|
345
|
-
}
|
|
346
|
-
else if (typeof message.content === 'string') {
|
|
347
|
-
const { cleaned, segments } = stripReasoningFromString(message.content);
|
|
348
|
-
message.content = cleaned;
|
|
349
|
-
reasoningSegments.push(...segments);
|
|
350
|
-
}
|
|
351
|
-
if (reasoningSegments.length) {
|
|
352
|
-
message.reasoning_content = mergeReasoningText(message.reasoning_content, reasoningSegments);
|
|
353
|
-
}
|
|
354
|
-
else if ('reasoning_content' in message) {
|
|
355
|
-
delete message.reasoning_content;
|
|
43
|
+
const normalized = normalizeReasoningInAnthropicPayloadWithNative(payload);
|
|
44
|
+
if (normalized && typeof normalized === 'object') {
|
|
45
|
+
Object.assign(payload, normalized);
|
|
356
46
|
}
|
|
357
47
|
}
|
|
358
|
-
function
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
collector.push(...segments);
|
|
48
|
+
export function normalizeReasoningInOpenAIPayload(payload) {
|
|
49
|
+
assertReasoningNormalizerNativeAvailable();
|
|
50
|
+
if (!payload)
|
|
362
51
|
return;
|
|
52
|
+
const normalized = normalizeReasoningInOpenAIPayloadWithNative(payload);
|
|
53
|
+
if (normalized && typeof normalized === 'object') {
|
|
54
|
+
Object.assign(payload, normalized);
|
|
363
55
|
}
|
|
364
|
-
if (!isRecord(block)) {
|
|
365
|
-
return;
|
|
366
|
-
}
|
|
367
|
-
const type = typeof block.type === 'string' ? block.type.toLowerCase() : '';
|
|
368
|
-
if (type === 'text' && typeof block.text === 'string') {
|
|
369
|
-
const { cleaned, segments } = stripReasoningFromString(block.text);
|
|
370
|
-
block.text = cleaned;
|
|
371
|
-
collector.push(...segments);
|
|
372
|
-
return;
|
|
373
|
-
}
|
|
374
|
-
if (type === 'thinking' || type === 'reasoning') {
|
|
375
|
-
const flattened = flattenAnthropicText(block);
|
|
376
|
-
if (flattened.trim().length) {
|
|
377
|
-
collector.push(flattened.trim());
|
|
378
|
-
}
|
|
379
|
-
return;
|
|
380
|
-
}
|
|
381
|
-
if (Array.isArray(block.content)) {
|
|
382
|
-
block.content.forEach((nested) => normalizeAnthropicBlock(nested, collector));
|
|
383
|
-
}
|
|
384
|
-
else if (typeof block.content === 'string') {
|
|
385
|
-
const { cleaned, segments } = stripReasoningFromString(block.content);
|
|
386
|
-
block.content = cleaned;
|
|
387
|
-
collector.push(...segments);
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
function flattenAnthropicText(source) {
|
|
391
|
-
if (typeof source === 'string') {
|
|
392
|
-
return source;
|
|
393
|
-
}
|
|
394
|
-
if (Array.isArray(source)) {
|
|
395
|
-
return source.map((entry) => flattenAnthropicText(entry)).filter(Boolean).join('');
|
|
396
|
-
}
|
|
397
|
-
if (isRecord(source)) {
|
|
398
|
-
if (typeof source.text === 'string') {
|
|
399
|
-
return source.text;
|
|
400
|
-
}
|
|
401
|
-
if (typeof source.content === 'string') {
|
|
402
|
-
return source.content;
|
|
403
|
-
}
|
|
404
|
-
if (Array.isArray(source.content)) {
|
|
405
|
-
return source.content.map((entry) => flattenAnthropicText(entry)).filter(Boolean).join('');
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
return '';
|
|
409
56
|
}
|
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
import { normalizeChatResponseReasoningToolsWithNative, normalizeMessageReasoningToolsWithNative } from '../../router/virtual-router/engine-selection/native-hub-bridge-action-semantics.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
target[key] = value;
|
|
2
|
+
const MODULE_NAME = 'reasoning-tool-normalizer';
|
|
3
|
+
function assertReasoningToolNormalizerNativeAvailable() {
|
|
4
|
+
if (typeof normalizeMessageReasoningToolsWithNative !== 'function' ||
|
|
5
|
+
typeof normalizeChatResponseReasoningToolsWithNative !== 'function') {
|
|
6
|
+
throw new Error(`[${MODULE_NAME}] native bindings unavailable`);
|
|
8
7
|
}
|
|
9
8
|
}
|
|
10
9
|
export function normalizeMessageReasoningTools(message, options) {
|
|
11
|
-
|
|
12
|
-
return { toolCallsAdded: 0 };
|
|
13
|
-
}
|
|
10
|
+
assertReasoningToolNormalizerNativeAvailable();
|
|
14
11
|
const normalized = normalizeMessageReasoningToolsWithNative(message, typeof options?.idPrefix === 'string' ? options.idPrefix : undefined);
|
|
15
|
-
overwriteRecordInPlace(message, normalized.message);
|
|
16
12
|
return {
|
|
17
13
|
toolCallsAdded: normalized.toolCallsAdded,
|
|
18
14
|
...(typeof normalized.cleanedReasoning === 'string'
|
|
@@ -21,9 +17,6 @@ export function normalizeMessageReasoningTools(message, options) {
|
|
|
21
17
|
};
|
|
22
18
|
}
|
|
23
19
|
export function normalizeChatResponseReasoningTools(response, options) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
const normalized = normalizeChatResponseReasoningToolsWithNative(response, typeof options?.idPrefixBase === 'string' ? options.idPrefixBase : undefined);
|
|
28
|
-
overwriteRecordInPlace(response, normalized);
|
|
20
|
+
assertReasoningToolNormalizerNativeAvailable();
|
|
21
|
+
normalizeChatResponseReasoningToolsWithNative(response, typeof options?.idPrefixBase === 'string' ? options.idPrefixBase : undefined);
|
|
29
22
|
}
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { extractToolCallsFromReasoningTextWithNative } from '../../router/virtual-router/engine-selection/native-shared-conversion-semantics.js';
|
|
2
|
-
|
|
3
|
-
if (typeof
|
|
4
|
-
|
|
2
|
+
function assertReasoningToolParserNativeAvailable() {
|
|
3
|
+
if (typeof extractToolCallsFromReasoningTextWithNative !== 'function') {
|
|
4
|
+
throw new Error('[reasoning-tool-parser] native bindings unavailable');
|
|
5
5
|
}
|
|
6
|
+
}
|
|
7
|
+
export function extractToolCallsFromReasoningText(text, options) {
|
|
8
|
+
assertReasoningToolParserNativeAvailable();
|
|
6
9
|
const idPrefix = options?.idPrefix ?? 'reasoning';
|
|
7
|
-
|
|
8
|
-
return {
|
|
9
|
-
cleanedText: output.cleanedText,
|
|
10
|
-
toolCalls: output.toolCalls
|
|
11
|
-
};
|
|
10
|
+
return extractToolCallsFromReasoningTextWithNative(String(text ?? ''), idPrefix);
|
|
12
11
|
}
|
|
@@ -1,41 +1,19 @@
|
|
|
1
|
-
import { sanitizeReasoningTaggedTextWithNative } from '../../router/virtual-router/engine-selection/native-shared-conversion-semantics.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
/```\s*(?:think|reflection)/i.test(source);
|
|
7
|
-
const hasExplicitClose = /<\/think>/i.test(source) ||
|
|
8
|
-
/<\/reflection>/i.test(source);
|
|
9
|
-
const push = (value) => {
|
|
10
|
-
const trimmed = (value ?? '').trim();
|
|
11
|
-
if (trimmed && reasoningCollector) {
|
|
12
|
-
reasoningCollector.push(trimmed);
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
|
-
const patterns = [
|
|
16
|
-
/<think>([\s\S]*?)<\/think>/gi,
|
|
17
|
-
/<reflection>([\s\S]*?)<\/reflection>/gi,
|
|
18
|
-
/```\s*(?:think|reflection)[\s\S]*?```/gi
|
|
19
|
-
];
|
|
20
|
-
for (const pattern of patterns) {
|
|
21
|
-
working = working.replace(pattern, (_match, inner) => {
|
|
22
|
-
push(inner);
|
|
23
|
-
return '';
|
|
24
|
-
});
|
|
1
|
+
import { extractReasoningSegmentsWithNative, sanitizeReasoningTaggedTextWithNative } from '../../router/virtual-router/engine-selection/native-shared-conversion-semantics.js';
|
|
2
|
+
function assertReasoningUtilsNativeAvailable() {
|
|
3
|
+
if (typeof extractReasoningSegmentsWithNative !== 'function' ||
|
|
4
|
+
typeof sanitizeReasoningTaggedTextWithNative !== 'function') {
|
|
5
|
+
throw new Error('[reasoning-utils] native bindings unavailable');
|
|
25
6
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (reasoningCollector
|
|
31
|
-
|
|
32
|
-
if (trimmed.length) {
|
|
33
|
-
reasoningCollector.push(trimmed);
|
|
34
|
-
}
|
|
35
|
-
return '';
|
|
7
|
+
}
|
|
8
|
+
export function extractReasoningSegments(source, reasoningCollector) {
|
|
9
|
+
assertReasoningUtilsNativeAvailable();
|
|
10
|
+
const output = extractReasoningSegmentsWithNative(source ?? '');
|
|
11
|
+
if (reasoningCollector) {
|
|
12
|
+
reasoningCollector.push(...output.segments);
|
|
36
13
|
}
|
|
37
|
-
return
|
|
14
|
+
return output.text;
|
|
38
15
|
}
|
|
39
16
|
export function sanitizeReasoningTaggedText(value) {
|
|
17
|
+
assertReasoningUtilsNativeAvailable();
|
|
40
18
|
return sanitizeReasoningTaggedTextWithNative(value);
|
|
41
19
|
}
|
|
@@ -2,7 +2,7 @@ import { extractOutputSegments } from './output-content-normalizer.js';
|
|
|
2
2
|
import { createBridgeActionState, runBridgeActionPipeline } from '../bridge-actions.js';
|
|
3
3
|
import { resolveBridgePolicy, resolvePolicyActions } from '../bridge-policies.js';
|
|
4
4
|
import { registerResponsesPayloadSnapshot, registerResponsesPassthrough } from './responses-reasoning-registry.js';
|
|
5
|
-
import { normalizeFunctionCallIdWithNative, sanitizeReasoningTaggedTextWithNative } from '../../router/virtual-router/engine-selection/native-shared-conversion-semantics.js';
|
|
5
|
+
import { collectToolCallsFromResponsesWithNative, normalizeFunctionCallIdWithNative, resolveFinishReasonWithNative, sanitizeReasoningTaggedTextWithNative } from '../../router/virtual-router/engine-selection/native-shared-conversion-semantics.js';
|
|
6
6
|
import { sanitizeResponsesFunctionNameWithNative } from '../../router/virtual-router/engine-selection/native-hub-pipeline-resp-semantics.js';
|
|
7
7
|
function selectCallId(entry) {
|
|
8
8
|
const candidates = [
|
|
@@ -53,55 +53,10 @@ function normalizeToolCall(entry, fallbackPrefix) {
|
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
55
|
export function collectToolCallsFromResponses(response) {
|
|
56
|
-
|
|
57
|
-
const seenIds = new Set();
|
|
58
|
-
const pushCall = (call, source) => {
|
|
59
|
-
if (!call)
|
|
60
|
-
return;
|
|
61
|
-
const key = typeof call.id === 'string' ? call.id : `${source}_${collected.length}`;
|
|
62
|
-
if (key && seenIds.has(key))
|
|
63
|
-
return;
|
|
64
|
-
if (key)
|
|
65
|
-
seenIds.add(key);
|
|
66
|
-
collected.push(call);
|
|
67
|
-
};
|
|
68
|
-
const required = response?.required_action?.submit_tool_outputs?.tool_calls;
|
|
69
|
-
if (Array.isArray(required)) {
|
|
70
|
-
for (const call of required) {
|
|
71
|
-
pushCall(normalizeToolCall(call, 'req_call'), 'req_call');
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
const outputItems = Array.isArray(response.output) ? response.output : [];
|
|
75
|
-
for (const item of outputItems) {
|
|
76
|
-
if (!item || typeof item !== 'object')
|
|
77
|
-
continue;
|
|
78
|
-
const type = typeof item.type === 'string' ? String(item.type).toLowerCase() : '';
|
|
79
|
-
if (type !== 'function_call')
|
|
80
|
-
continue;
|
|
81
|
-
pushCall(normalizeToolCall(item, 'output_call'), 'output_call');
|
|
82
|
-
}
|
|
83
|
-
return collected;
|
|
56
|
+
return collectToolCallsFromResponsesWithNative(response);
|
|
84
57
|
}
|
|
85
58
|
export function resolveFinishReason(response, toolCalls) {
|
|
86
|
-
|
|
87
|
-
? response.metadata
|
|
88
|
-
: undefined;
|
|
89
|
-
if (meta && typeof meta.finish_reason === 'string') {
|
|
90
|
-
return meta.finish_reason;
|
|
91
|
-
}
|
|
92
|
-
if (toolCalls.length > 0) {
|
|
93
|
-
return 'tool_calls';
|
|
94
|
-
}
|
|
95
|
-
const status = typeof response.status === 'string' ? response.status.toLowerCase() : '';
|
|
96
|
-
if (status === 'requires_action')
|
|
97
|
-
return 'tool_calls';
|
|
98
|
-
if (status === 'in_progress' || status === 'streaming')
|
|
99
|
-
return 'length';
|
|
100
|
-
if (status === 'cancelled')
|
|
101
|
-
return 'cancelled';
|
|
102
|
-
if (status === 'failed')
|
|
103
|
-
return 'error';
|
|
104
|
-
return 'stop';
|
|
59
|
+
return resolveFinishReasonWithNative(response, toolCalls);
|
|
105
60
|
}
|
|
106
61
|
function unwrapResponsesResponse(payload) {
|
|
107
62
|
if (!payload || typeof payload !== 'object')
|
|
@@ -6,9 +6,9 @@ export interface CallIdTransformer {
|
|
|
6
6
|
normalizeOutputId(callId: string, raw: unknown): string;
|
|
7
7
|
}
|
|
8
8
|
export declare function createToolCallIdTransformer(style: ToolCallIdStyle): CallIdTransformer | null;
|
|
9
|
-
export declare function enforceToolCallIdStyle(input: BridgeInputItem[], transformer: CallIdTransformer): void;
|
|
10
9
|
export declare function normalizeResponsesToolCallIds(payload: Record<string, unknown> | null | undefined): void;
|
|
11
10
|
export declare function resolveToolCallIdStyle(metadata: Record<string, unknown> | undefined): ToolCallIdStyle;
|
|
12
11
|
export declare function stripInternalToolingMetadata(metadata: unknown): void;
|
|
13
12
|
export declare function sanitizeResponsesFunctionName(rawName: unknown): string | undefined;
|
|
13
|
+
export declare function enforceToolCallIdStyle(input: BridgeInputItem[], transformer: CallIdTransformer): void;
|
|
14
14
|
export {};
|