@jsonstudio/llms 0.6.3271 → 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 (49) 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/actions/anthropic-claude-code-system-prompt.js +38 -0
  4. package/dist/conversion/compat/profiles/responses-crs.json +15 -0
  5. package/dist/conversion/hub/operation-table/semantic-mappers/chat-mapper.js +16 -5
  6. package/dist/conversion/hub/pipeline/stages/resp_process/resp_process_stage1_tool_governance/index.js +1 -6
  7. package/dist/conversion/hub/response/response-runtime.js +14 -6
  8. package/dist/conversion/responses/responses-openai-bridge/response-payload.js +11 -11
  9. package/dist/conversion/shared/anthropic-message-utils.js +2 -12
  10. package/dist/conversion/shared/chat-request-filters.js +2 -61
  11. package/dist/conversion/shared/reasoning-mapping.js +3 -0
  12. package/dist/conversion/shared/reasoning-normalizer.d.ts +1 -0
  13. package/dist/conversion/shared/reasoning-normalizer.js +35 -388
  14. package/dist/conversion/shared/reasoning-tool-normalizer.js +8 -15
  15. package/dist/conversion/shared/reasoning-utils.js +13 -35
  16. package/dist/conversion/shared/responses-tool-utils.d.ts +1 -1
  17. package/dist/conversion/shared/responses-tool-utils.js +63 -65
  18. package/dist/conversion/shared/streaming-text-extractor.d.ts +0 -5
  19. package/dist/conversion/shared/streaming-text-extractor.js +18 -111
  20. package/dist/conversion/shared/text-markup-normalizer/normalize.d.ts +1 -1
  21. package/dist/conversion/shared/text-markup-normalizer/normalize.js +3 -91
  22. package/dist/conversion/shared/thought-signature-validator.js +19 -133
  23. package/dist/conversion/shared/tool-argument-repairer.js +16 -19
  24. package/dist/conversion/shared/tool-call-id-manager.d.ts +1 -5
  25. package/dist/conversion/shared/tool-call-id-manager.js +74 -98
  26. package/dist/conversion/shared/tool-harvester.js +19 -382
  27. package/dist/conversion/shared/tool-mapping.d.ts +2 -3
  28. package/dist/conversion/shared/tool-mapping.js +28 -184
  29. package/dist/conversion/shared/tooling.js +20 -151
  30. package/dist/filters/special/response-tool-arguments-stringify.js +9 -1
  31. package/dist/guidance/index.js +2 -2
  32. package/dist/native/router_hotpath_napi.node +0 -0
  33. package/dist/router/virtual-router/engine-legacy/helpers.js +1 -1
  34. package/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics.d.ts +39 -0
  35. package/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics.js +196 -0
  36. package/dist/router/virtual-router/engine-selection/native-hub-pipeline-req-inbound-semantics.d.ts +1 -0
  37. package/dist/router/virtual-router/engine-selection/native-hub-pipeline-req-inbound-semantics.js +27 -0
  38. package/dist/router/virtual-router/engine-selection/native-router-hotpath-loader.js +34 -0
  39. package/dist/router/virtual-router/engine-selection/native-shared-conversion-semantics.d.ts +65 -1
  40. package/dist/router/virtual-router/engine-selection/native-shared-conversion-semantics.js +836 -35
  41. package/dist/router/virtual-router/engine.js +3 -2
  42. package/dist/router/virtual-router/routing-instructions/parse.js +30 -3
  43. package/dist/sse/sse-to-json/builders/anthropic-response-builder.js +28 -3
  44. package/dist/sse/types/anthropic-types.d.ts +3 -1
  45. package/dist/tools/apply-patch/args-normalizer/extract-patch.js +2 -2
  46. package/dist/tools/apply-patch/patch-text/looks-like-patch.js +3 -6
  47. package/dist/tools/apply-patch/patch-text/normalize.js +14 -3
  48. package/dist/tools/tool-registry.js +12 -0
  49. package/package.json +6 -1
@@ -1,7 +1,4 @@
1
1
  import type { BridgeInputItem } from './types/bridge-message-types.js';
2
- export declare function coerceBridgeRole(role: unknown): string;
3
- export declare function serializeToolArguments(argsStringOrObj: unknown, _functionName: string | undefined, _tools: unknown): string;
4
- export declare function serializeToolOutput(entry: BridgeInputItem): string | null;
5
2
  export interface BridgeInputBuildOptions {
6
3
  messages: Array<Record<string, unknown>>;
7
4
  tools?: Array<Record<string, unknown>> | undefined;
@@ -12,11 +9,14 @@ export interface BridgeInputBuildResult {
12
9
  latestUserInstruction?: string;
13
10
  originalSystemMessages: string[];
14
11
  }
12
+ export declare function coerceBridgeRole(role: unknown): string;
13
+ export declare function serializeToolArguments(argsStringOrObj: unknown, _functionName: string | undefined, _tools: unknown): string;
14
+ export declare function serializeToolOutput(entry: BridgeInputItem): string | null;
15
15
  export declare function convertMessagesToBridgeInput(options: BridgeInputBuildOptions): BridgeInputBuildResult;
16
16
  export interface BridgeInputToChatOptions {
17
17
  input?: BridgeInputItem[];
18
18
  tools?: Array<Record<string, unknown>>;
19
- normalizeFunctionName?: (raw: unknown) => string | undefined;
19
+ normalizeFunctionName?: ((raw: unknown) => string | undefined) | 'default' | 'responses';
20
20
  toolResultFallbackText?: string;
21
21
  }
22
22
  export declare function convertBridgeInputToChatMessages(options: BridgeInputToChatOptions): Array<Record<string, unknown>>;
@@ -1,555 +1,45 @@
1
- import { normalizeChatMessageContent } from './shared/chat-output-normalizer.js';
2
- import { normalizeFunctionCallIdWithNative as normalizeFunctionCallId, repairArgumentsToStringWithNative as repairToolArguments } from '../router/virtual-router/engine-selection/native-shared-conversion-semantics.js';
3
- import { buildBridgeHistoryWithNative } from '../router/virtual-router/engine-selection/native-hub-bridge-action-semantics.js';
4
- function ensureAssistantToolCallIdentity(call, fallbackId) {
5
- const resolved = (typeof call.id === 'string' && call.id.trim().length ? call.id.trim() : undefined) ??
6
- (typeof call.tool_call_id === 'string' && call.tool_call_id.trim().length
7
- ? call.tool_call_id.trim()
8
- : undefined) ??
9
- (typeof call.call_id === 'string' && call.call_id.trim().length
10
- ? call.call_id.trim()
11
- : undefined) ??
12
- fallbackId;
13
- call.id = resolved;
14
- call.tool_call_id = resolved;
15
- call.call_id = resolved;
16
- return resolved;
1
+ import { buildBridgeHistoryWithNative, coerceBridgeRoleWithNative, convertBridgeInputToChatMessagesWithNative, ensureMessagesArrayWithNative, serializeToolArgumentsWithNative, serializeToolOutputWithNative } from '../router/virtual-router/engine-selection/native-hub-bridge-action-semantics.js';
2
+ function assertBridgeMessageUtilsNativeAvailable() {
3
+ if (typeof buildBridgeHistoryWithNative !== 'function' ||
4
+ typeof convertBridgeInputToChatMessagesWithNative !== 'function' ||
5
+ typeof coerceBridgeRoleWithNative !== 'function' ||
6
+ typeof serializeToolArgumentsWithNative !== 'function' ||
7
+ typeof serializeToolOutputWithNative !== 'function' ||
8
+ typeof ensureMessagesArrayWithNative !== 'function') {
9
+ throw new Error('[bridge-message-utils] native bindings unavailable');
10
+ }
17
11
  }
18
12
  export function coerceBridgeRole(role) {
19
- if (typeof role === 'string') {
20
- const normalized = role.toLowerCase();
21
- if (normalized === 'system' || normalized === 'assistant' || normalized === 'user' || normalized === 'tool') {
22
- return normalized;
23
- }
24
- }
25
- return 'user';
13
+ assertBridgeMessageUtilsNativeAvailable();
14
+ return coerceBridgeRoleWithNative(role);
26
15
  }
27
16
  export function serializeToolArguments(argsStringOrObj, _functionName, _tools) {
28
- return repairToolArguments(argsStringOrObj);
17
+ assertBridgeMessageUtilsNativeAvailable();
18
+ return serializeToolArgumentsWithNative({ args: argsStringOrObj });
29
19
  }
30
20
  export function serializeToolOutput(entry) {
31
- const out = entry?.output;
32
- if (typeof out === 'string')
33
- return out;
34
- if (out && typeof out === 'object') {
35
- try {
36
- return JSON.stringify(out);
37
- }
38
- catch {
39
- return String(out);
40
- }
41
- }
42
- return null;
43
- }
44
- function collectText(value) {
45
- if (!value)
46
- return '';
47
- if (typeof value === 'string')
48
- return value;
49
- if (Array.isArray(value)) {
50
- return value.map(part => collectText(part)).join('');
51
- }
52
- if (typeof value === 'object') {
53
- const record = value;
54
- if (typeof record.text === 'string')
55
- return record.text;
56
- if (Array.isArray(record.content))
57
- return collectText(record.content);
58
- if (typeof record.content === 'string')
59
- return record.content;
60
- }
61
- return '';
62
- }
63
- function extractMediaBlocksFromContent(content) {
64
- const media = [];
65
- const visit = (value) => {
66
- if (!value)
67
- return;
68
- if (Array.isArray(value)) {
69
- for (const entry of value)
70
- visit(entry);
71
- return;
72
- }
73
- if (typeof value !== 'object') {
74
- return;
75
- }
76
- const record = value;
77
- const typeValue = typeof record.type === 'string' ? record.type.toLowerCase() : '';
78
- let kind = null;
79
- if (typeValue === 'image' || typeValue === 'image_url' || typeValue === 'input_image') {
80
- kind = 'image';
81
- }
82
- else if (typeValue === 'video' || typeValue === 'video_url' || typeValue === 'input_video') {
83
- kind = 'video';
84
- }
85
- else if (record.video_url !== undefined) {
86
- kind = 'video';
87
- }
88
- else if (record.image_url !== undefined) {
89
- kind = 'image';
90
- }
91
- if (kind) {
92
- let url = '';
93
- const mediaUrl = kind === 'video' ? record.video_url : record.image_url;
94
- if (typeof mediaUrl === 'string') {
95
- url = mediaUrl;
96
- }
97
- else if (mediaUrl && typeof mediaUrl === 'object' && typeof mediaUrl.url === 'string') {
98
- url = mediaUrl.url;
99
- }
100
- else if (typeof record.url === 'string') {
101
- url = record.url;
102
- }
103
- else if (typeof record.uri === 'string') {
104
- url = record.uri;
105
- }
106
- else if (typeof record.data === 'string') {
107
- url = record.data;
108
- }
109
- const trimmed = url.trim();
110
- if (trimmed.length) {
111
- let detail;
112
- if (mediaUrl && typeof mediaUrl === 'object' && typeof mediaUrl.detail === 'string') {
113
- detail = mediaUrl.detail.trim() || undefined;
114
- }
115
- else if (typeof record.detail === 'string') {
116
- detail = record.detail.trim() || undefined;
117
- }
118
- media.push({ kind, url: trimmed, detail });
119
- }
120
- return;
121
- }
122
- if (Array.isArray(record.content)) {
123
- visit(record.content);
124
- }
125
- };
126
- visit(content);
127
- return media;
128
- }
129
- function extractUserTextFromEntry(entry) {
130
- if (!entry || typeof entry !== 'object')
131
- return '';
132
- const directContent = entry.content ?? entry.message?.content;
133
- if (typeof directContent === 'string')
134
- return directContent.trim();
135
- if (Array.isArray(directContent)) {
136
- return directContent.map(block => collectText(block)).join('').trim();
137
- }
138
- const text = entry.text ?? entry.message?.text;
139
- if (typeof text === 'string')
140
- return text.trim();
141
- return '';
21
+ assertBridgeMessageUtilsNativeAvailable();
22
+ return serializeToolOutputWithNative({ output: entry?.output });
142
23
  }
143
24
  export function convertMessagesToBridgeInput(options) {
25
+ assertBridgeMessageUtilsNativeAvailable();
144
26
  const { messages, tools } = options;
145
27
  const native = buildBridgeHistoryWithNative({ messages, tools });
146
28
  return native;
147
29
  }
148
- function defaultNormalizeFunctionName(raw) {
149
- if (typeof raw !== 'string')
150
- return undefined;
151
- const trimmed = raw.trim();
152
- return trimmed.length ? trimmed : undefined;
153
- }
154
- function toReasoningSegments(value) {
155
- if (Array.isArray(value)) {
156
- return value.map((entry) => (typeof entry === 'string' ? entry.trim() : '')).filter((entry) => entry.length);
157
- }
158
- if (typeof value === 'string') {
159
- const trimmed = value.trim();
160
- return trimmed.length ? [trimmed] : [];
161
- }
162
- return [];
163
- }
164
- function combineReasoningSegments(primary, secondary) {
165
- const combined = [];
166
- if (Array.isArray(primary)) {
167
- combined.push(...primary.filter((entry) => typeof entry === 'string' && entry.trim().length).map((entry) => entry.trim()));
168
- }
169
- if (Array.isArray(secondary)) {
170
- combined.push(...secondary.filter((entry) => typeof entry === 'string' && entry.trim().length).map((entry) => entry.trim()));
171
- }
172
- return combined;
173
- }
174
- function pushNormalizedChatMessage(target, role, rawContent, options) {
175
- if (typeof rawContent !== 'string') {
176
- return;
177
- }
178
- const normalized = normalizeChatMessageContent(rawContent);
179
- const contentText = typeof normalized.contentText === 'string' ? normalized.contentText : '';
180
- const reasoningText = typeof normalized.reasoningText === 'string' ? normalized.reasoningText.trim() : '';
181
- const hasContent = contentText.trim().length > 0;
182
- if (!hasContent && !reasoningText) {
183
- return;
184
- }
185
- const message = {
186
- role,
187
- content: contentText
188
- };
189
- const combinedReasoning = combineReasoningSegments(reasoningText.length ? [reasoningText] : [], options?.reasoningSegments);
190
- if (combinedReasoning.length) {
191
- message.reasoning_content = combinedReasoning.join('\n');
192
- }
193
- target.push(message);
194
- }
195
- function processMessageBlocks(blocks, normalizeFunctionName, tools, toolNameById, lastToolCallId, toolResultFallbackText) {
196
- const textParts = [];
197
- const toolCalls = [];
198
- const toolMessages = [];
199
- let currentLastCall = lastToolCallId;
200
- const reasoningSegments = [];
201
- const mediaBlocks = [];
202
- for (const block of blocks) {
203
- if (!block || typeof block !== 'object')
204
- continue;
205
- const type = typeof block.type === 'string' ? block.type.toLowerCase() : '';
206
- if (type === 'input_text' || type === 'output_text' || type === 'text' || type === 'commentary') {
207
- if (typeof block.text === 'string')
208
- textParts.push(block.text);
209
- else if (typeof block.content === 'string')
210
- textParts.push(block.content);
211
- reasoningSegments.push(...toReasoningSegments(block.reasoning_content));
212
- continue;
213
- }
214
- if (type === 'message' && Array.isArray(block.content)) {
215
- const nested = processMessageBlocks(block.content, normalizeFunctionName, tools, toolNameById, currentLastCall, toolResultFallbackText);
216
- if (nested.text)
217
- textParts.push(nested.text);
218
- for (const tc of nested.toolCalls)
219
- toolCalls.push(tc);
220
- for (const tm of nested.toolMessages)
221
- toolMessages.push(tm);
222
- currentLastCall = nested.lastCallId;
223
- reasoningSegments.push(...nested.reasoningSegments);
224
- if (nested.mediaBlocks.length)
225
- mediaBlocks.push(...nested.mediaBlocks);
226
- continue;
227
- }
228
- if (type === 'input_image' || type === 'image' || type === 'image_url') {
229
- let url = '';
230
- if (typeof block.image_url === 'string') {
231
- url = block.image_url.trim();
232
- }
233
- else if (block.image_url && typeof block.image_url.url === 'string') {
234
- url = block.image_url.url.trim();
235
- }
236
- else if (typeof block.url === 'string') {
237
- url = block.url.trim();
238
- }
239
- if (url) {
240
- const detail = typeof block.detail === 'string' && block.detail.trim()
241
- ? block.detail.trim()
242
- : undefined;
243
- mediaBlocks.push({ kind: 'image', url, detail });
244
- }
245
- continue;
246
- }
247
- if (type === 'input_video' || type === 'video' || type === 'video_url') {
248
- let url = '';
249
- if (typeof block.video_url === 'string') {
250
- url = block.video_url.trim();
251
- }
252
- else if (block.video_url && typeof block.video_url.url === 'string') {
253
- url = block.video_url.url.trim();
254
- }
255
- else if (typeof block.url === 'string') {
256
- url = block.url.trim();
257
- }
258
- if (url) {
259
- const detail = typeof block.detail === 'string' && block.detail.trim()
260
- ? block.detail.trim()
261
- : undefined;
262
- mediaBlocks.push({ kind: 'video', url, detail });
263
- }
264
- continue;
265
- }
266
- if (type === 'function_call') {
267
- const rawName = typeof block.name === 'string'
268
- ? block.name
269
- : (typeof block?.function?.name === 'string'
270
- ? block.function.name
271
- : undefined);
272
- const name = normalizeFunctionName(rawName);
273
- const args = block.arguments ?? block?.function?.arguments ?? {};
274
- const parsedArgs = args;
275
- const callIdCandidate = (typeof block.id === 'string' && block.id.trim().length ? block.id.trim() : undefined) ??
276
- (typeof block.call_id === 'string' && block.call_id.trim().length ? block.call_id.trim() : undefined);
277
- const callId = callIdCandidate ??
278
- normalizeFunctionCallId({
279
- callId: callIdCandidate,
280
- fallback: `fc_call_${toolCalls.length + 1}`
281
- });
282
- if (typeof name !== 'string' || !name.trim()) {
283
- currentLastCall = null;
284
- continue;
285
- }
286
- const serialized = serializeToolArguments(parsedArgs, name, tools).trim();
287
- toolNameById.set(callId, name);
288
- toolCalls.push({ id: callId, type: 'function', function: { name, arguments: serialized } });
289
- currentLastCall = callId;
290
- continue;
291
- }
292
- if (type === 'function_call_output' || type === 'tool_result' || type === 'tool_message') {
293
- let toolCallId = block.tool_call_id ||
294
- block.call_id ||
295
- block.tool_use_id ||
296
- block.id ||
297
- currentLastCall;
298
- toolCallId = typeof toolCallId === 'string' && toolCallId.trim().length ? toolCallId.trim() : currentLastCall;
299
- const output = serializeToolOutput(block);
300
- if (toolCallId) {
301
- try {
302
- let contentStr = output != null ? String(output) : '';
303
- if (!contentStr || contentStr.trim().length === 0) {
304
- contentStr = toolResultFallbackText;
305
- }
306
- const nm = toolNameById.get(String(toolCallId));
307
- const toolMsg = { role: 'tool', tool_call_id: String(toolCallId), content: contentStr };
308
- if (typeof nm === 'string' && nm.trim().length)
309
- toolMsg.name = nm;
310
- toolMessages.push(toolMsg);
311
- }
312
- catch {
313
- const fallback = (output ?? toolResultFallbackText);
314
- const nm = toolNameById.get(String(toolCallId));
315
- const toolMsg = { role: 'tool', tool_call_id: String(toolCallId), content: String(fallback) };
316
- if (typeof nm === 'string' && nm.trim().length)
317
- toolMsg.name = nm;
318
- toolMessages.push(toolMsg);
319
- }
320
- currentLastCall = null;
321
- }
322
- continue;
323
- }
324
- }
325
- const text = textParts.length ? textParts.join('\n').trim() : null;
326
- return { text, mediaBlocks, toolCalls, toolMessages, lastCallId: currentLastCall, reasoningSegments };
327
- }
328
30
  export function convertBridgeInputToChatMessages(options) {
31
+ assertBridgeMessageUtilsNativeAvailable();
329
32
  const { input, tools, normalizeFunctionName, toolResultFallbackText } = options;
330
- const messages = [];
331
- if (!Array.isArray(input))
332
- return messages;
333
- const toolNameById = new Map();
334
- let lastToolCallId = null;
335
- const resolveFunctionName = normalizeFunctionName ?? defaultNormalizeFunctionName;
336
- const fallbackText = toolResultFallbackText ?? 'Command succeeded (no output).';
337
- for (let entryIndex = 0; entryIndex < input.length; entryIndex++) {
338
- const entry = input[entryIndex];
339
- if (!entry || typeof entry !== 'object')
340
- continue;
341
- const entryType = typeof entry.type === 'string' ? entry.type.toLowerCase() : 'message';
342
- const entryReasoningSegments = toReasoningSegments(entry.reasoning_content);
343
- let entryReasoningConsumed = false;
344
- const consumeEntryReasoning = () => {
345
- if (entryReasoningConsumed || !entryReasoningSegments.length) {
346
- return undefined;
347
- }
348
- entryReasoningConsumed = true;
349
- return entryReasoningSegments;
350
- };
351
- if (typeof entry.content === 'string') {
352
- const normalizedRole = coerceBridgeRole(entry.role || 'user');
353
- const directText = (entry.content || '').toString();
354
- pushNormalizedChatMessage(messages, normalizedRole, directText, {
355
- reasoningSegments: consumeEntryReasoning()
356
- });
357
- continue;
358
- }
359
- if (entryType === 'function_call' || entryType === 'tool_call') {
360
- const rawName = typeof entry.name === 'string'
361
- ? entry.name
362
- : (typeof entry?.function?.name === 'string' ? entry.function.name : undefined);
363
- const name = resolveFunctionName(rawName);
364
- if (typeof name !== 'string' || !name.trim()) {
365
- continue;
366
- }
367
- const args = entry.arguments ?? entry?.function?.arguments ?? {};
368
- const parsedArgs = args;
369
- const callIdRaw = typeof entry.id === 'string' ? entry.id : (typeof entry.call_id === 'string' ? entry.call_id : undefined);
370
- const callIdSource = typeof callIdRaw === 'string' && callIdRaw.trim().length ? callIdRaw.trim() : undefined;
371
- let callId = callIdSource;
372
- if (!callId) {
373
- callId = normalizeFunctionCallId({
374
- callId: callIdSource,
375
- fallback: `fc_call_${messages.length + 1}`
376
- });
377
- }
378
- const serialized = serializeToolArguments(parsedArgs, name, tools).trim();
379
- toolNameById.set(callId, name);
380
- const toolCall = {
381
- id: callId,
382
- call_id: callId,
383
- tool_call_id: callId,
384
- type: 'function',
385
- function: { name, arguments: serialized }
386
- };
387
- messages.push({
388
- role: 'assistant',
389
- content: '',
390
- tool_calls: [toolCall]
391
- });
392
- lastToolCallId = callId;
393
- continue;
394
- }
395
- if (entryType === 'function_call_output' || entryType === 'tool_result' || entryType === 'tool_message') {
396
- let toolCallId = entry.tool_call_id ||
397
- entry.call_id ||
398
- entry.tool_use_id ||
399
- entry.id ||
400
- lastToolCallId;
401
- toolCallId = typeof toolCallId === 'string' && toolCallId.trim().length ? toolCallId.trim() : (lastToolCallId ?? undefined);
402
- const output = serializeToolOutput(entry);
403
- if (toolCallId) {
404
- try {
405
- let contentStr = output != null ? String(output) : '';
406
- if (!contentStr || contentStr.trim().length === 0) {
407
- contentStr = fallbackText;
408
- }
409
- const nm = toolNameById.get(String(toolCallId));
410
- const toolMsg = {
411
- role: 'tool',
412
- tool_call_id: String(toolCallId),
413
- id: String(toolCallId),
414
- content: contentStr
415
- };
416
- if (typeof nm === 'string' && nm.trim().length)
417
- toolMsg.name = nm;
418
- messages.push(toolMsg);
419
- }
420
- catch {
421
- const fallback = (output ?? fallbackText);
422
- const nm = toolNameById.get(String(toolCallId));
423
- const toolMsg = {
424
- role: 'tool',
425
- tool_call_id: String(toolCallId),
426
- id: String(toolCallId),
427
- content: String(fallback)
428
- };
429
- if (typeof nm === 'string' && nm.trim().length)
430
- toolMsg.name = nm;
431
- messages.push(toolMsg);
432
- }
433
- lastToolCallId = null;
434
- }
435
- continue;
436
- }
437
- let handledViaExplicitMessage = false;
438
- if (entry && typeof entry.message === 'object' && Array.isArray(entry.message?.content)) {
439
- const explicit = entry.message;
440
- const nested = processMessageBlocks(Array.isArray(explicit.content) ? explicit.content : [], resolveFunctionName, tools, toolNameById, lastToolCallId, fallbackText);
441
- if (nested.toolCalls.length) {
442
- nested.toolCalls.forEach((call, idx) => ensureAssistantToolCallIdentity(call, `fc_call_${messages.length + idx + 1}`));
443
- messages.push({
444
- role: 'assistant',
445
- content: '',
446
- tool_calls: nested.toolCalls
447
- });
448
- }
449
- for (const msg of nested.toolMessages)
450
- messages.push(msg);
451
- const normalizedRole = coerceBridgeRole((explicit.role ?? entry.role) || 'user');
452
- if (nested.mediaBlocks.length) {
453
- const contentBlocks = [];
454
- if (typeof nested.text === 'string' && nested.text.trim().length) {
455
- contentBlocks.push({ type: 'text', text: nested.text });
456
- }
457
- for (const media of nested.mediaBlocks) {
458
- const mediaBlock = media.kind === 'video'
459
- ? { type: 'video_url', video_url: { url: media.url } }
460
- : { type: 'image_url', image_url: { url: media.url } };
461
- if (media.detail) {
462
- const key = media.kind === 'video' ? 'video_url' : 'image_url';
463
- mediaBlock[key].detail = media.detail;
464
- }
465
- contentBlocks.push(mediaBlock);
466
- }
467
- const msg = {
468
- role: normalizedRole,
469
- content: contentBlocks
470
- };
471
- const combinedReasoning = combineReasoningSegments(consumeEntryReasoning(), nested.reasoningSegments);
472
- if (combinedReasoning.length) {
473
- msg.reasoning_content = combinedReasoning.join('\n');
474
- }
475
- messages.push(msg);
476
- }
477
- else if (typeof nested.text === 'string') {
478
- pushNormalizedChatMessage(messages, normalizedRole, nested.text, {
479
- reasoningSegments: combineReasoningSegments(consumeEntryReasoning(), nested.reasoningSegments)
480
- });
481
- }
482
- lastToolCallId = nested.lastCallId;
483
- handledViaExplicitMessage = true;
484
- }
485
- if (!handledViaExplicitMessage) {
486
- const nested = processMessageBlocks(Array.isArray(entry.content) ? entry.content : [], resolveFunctionName, tools, toolNameById, lastToolCallId, fallbackText);
487
- if (nested.toolCalls.length) {
488
- nested.toolCalls.forEach((call, idx) => ensureAssistantToolCallIdentity(call, `fc_call_${messages.length + idx + 1}`));
489
- messages.push({
490
- role: 'assistant',
491
- content: '',
492
- tool_calls: nested.toolCalls
493
- });
494
- }
495
- for (const msg of nested.toolMessages)
496
- messages.push(msg);
497
- const normalizedRole = coerceBridgeRole(entry.role || 'user');
498
- if (nested.mediaBlocks.length) {
499
- const contentBlocks = [];
500
- if (typeof nested.text === 'string' && nested.text.trim().length) {
501
- contentBlocks.push({ type: 'text', text: nested.text });
502
- }
503
- for (const media of nested.mediaBlocks) {
504
- const mediaBlock = media.kind === 'video'
505
- ? { type: 'video_url', video_url: { url: media.url } }
506
- : { type: 'image_url', image_url: { url: media.url } };
507
- if (media.detail) {
508
- const key = media.kind === 'video' ? 'video_url' : 'image_url';
509
- mediaBlock[key].detail = media.detail;
510
- }
511
- contentBlocks.push(mediaBlock);
512
- }
513
- const msg = {
514
- role: normalizedRole,
515
- content: contentBlocks
516
- };
517
- const combinedReasoning = combineReasoningSegments(consumeEntryReasoning(), nested.reasoningSegments);
518
- if (combinedReasoning.length) {
519
- msg.reasoning_content = combinedReasoning.join('\n');
520
- }
521
- messages.push(msg);
522
- }
523
- else if (typeof nested.text === 'string') {
524
- pushNormalizedChatMessage(messages, normalizedRole, nested.text, {
525
- reasoningSegments: consumeEntryReasoning()
526
- });
527
- }
528
- lastToolCallId = nested.lastCallId;
529
- }
530
- try {
531
- const t = String(entry.type || '').toLowerCase();
532
- if ((t === 'input_text' || t === 'text' || t === 'output_text' || t === 'commentary') &&
533
- typeof entry.text === 'string') {
534
- const normalizedRole = coerceBridgeRole(entry.role || 'user');
535
- const s = entry.text;
536
- if (s && s.length) {
537
- pushNormalizedChatMessage(messages, normalizedRole, s, {
538
- reasoningSegments: consumeEntryReasoning()
539
- });
540
- }
541
- }
542
- }
543
- catch {
544
- /* ignore */
545
- }
546
- }
547
- return messages;
33
+ const output = convertBridgeInputToChatMessagesWithNative({
34
+ input: Array.isArray(input) ? input : [],
35
+ tools,
36
+ toolResultFallbackText,
37
+ normalizeFunctionName: typeof normalizeFunctionName === 'string' ? normalizeFunctionName : undefined
38
+ });
39
+ return output.messages;
548
40
  }
549
41
  export function ensureMessagesArray(state) {
550
- if (Array.isArray(state.messages))
551
- return state.messages;
552
- if (!state.messages)
553
- state.messages = [];
554
- return state.messages;
42
+ assertBridgeMessageUtilsNativeAvailable();
43
+ const output = ensureMessagesArrayWithNative({ state });
44
+ return output.messages;
555
45
  }
@@ -16,6 +16,42 @@ function readTrimmedString(value) {
16
16
  const trimmed = value.trim();
17
17
  return trimmed.length ? trimmed : undefined;
18
18
  }
19
+ function shouldInjectThinking(value) {
20
+ if (value === undefined || value === null) {
21
+ return true;
22
+ }
23
+ if (typeof value === 'boolean') {
24
+ return value !== false;
25
+ }
26
+ if (isRecord(value)) {
27
+ const type = readTrimmedString(value.type);
28
+ return !type;
29
+ }
30
+ if (typeof value === 'string') {
31
+ return value.trim().length === 0;
32
+ }
33
+ return true;
34
+ }
35
+ function resolveEffort(model) {
36
+ const modelId = readTrimmedString(model)?.toLowerCase() || '';
37
+ return modelId.startsWith('glm-5') ? 'high' : 'medium';
38
+ }
39
+ function ensureAdaptiveThinking(root) {
40
+ if (shouldInjectThinking(root.thinking)) {
41
+ root.thinking = { type: 'adaptive' };
42
+ }
43
+ }
44
+ function ensureOutputEffort(root) {
45
+ const effort = resolveEffort(root.model);
46
+ if (isRecord(root.output_config)) {
47
+ const outputConfig = root.output_config;
48
+ if (!readTrimmedString(outputConfig.effort)) {
49
+ outputConfig.effort = effort;
50
+ }
51
+ return;
52
+ }
53
+ root.output_config = { effort };
54
+ }
19
55
  function isClaudeCodeUserId(value) {
20
56
  const trimmed = readTrimmedString(value);
21
57
  if (!trimmed)
@@ -209,6 +245,8 @@ export function applyAnthropicClaudeCodeSystemPromptCompat(payload, config, adap
209
245
  .filter((b) => b.text !== systemText);
210
246
  // Normalize: force system into a single text block.
211
247
  root.system = [{ type: 'text', text: systemText }];
248
+ ensureAdaptiveThinking(root);
249
+ ensureOutputEffort(root);
212
250
  if (preserveExisting && existingBlocks.length) {
213
251
  const messages = Array.isArray(root.messages) ? root.messages : [];
214
252
  if (messages.length || root.messages !== undefined) {
@@ -0,0 +1,15 @@
1
+ {
2
+ "id": "responses:crs",
3
+ "protocol": "openai-responses",
4
+ "request": {
5
+ "mappings": [
6
+ {
7
+ "action": "remove",
8
+ "path": "temperature"
9
+ }
10
+ ]
11
+ },
12
+ "response": {
13
+ "mappings": []
14
+ }
15
+ }