@jsonstudio/llms 0.4.4 → 0.4.5

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 (159) hide show
  1. package/dist/conversion/codec-registry.js +11 -1
  2. package/dist/conversion/codecs/anthropic-openai-codec.d.ts +13 -0
  3. package/dist/conversion/codecs/anthropic-openai-codec.js +18 -473
  4. package/dist/conversion/codecs/gemini-openai-codec.js +91 -48
  5. package/dist/conversion/codecs/responses-openai-codec.js +9 -2
  6. package/dist/conversion/hub/format-adapters/anthropic-format-adapter.js +3 -0
  7. package/dist/conversion/hub/format-adapters/chat-format-adapter.js +3 -0
  8. package/dist/conversion/hub/format-adapters/gemini-format-adapter.js +3 -0
  9. package/dist/conversion/hub/format-adapters/responses-format-adapter.d.ts +19 -0
  10. package/dist/conversion/hub/format-adapters/responses-format-adapter.js +9 -0
  11. package/dist/conversion/hub/node-support.js +3 -1
  12. package/dist/conversion/hub/pipeline/hub-pipeline.js +37 -32
  13. package/dist/conversion/hub/response/provider-response.js +1 -1
  14. package/dist/conversion/hub/response/response-mappers.js +1 -1
  15. package/dist/conversion/hub/response/response-runtime.js +109 -10
  16. package/dist/conversion/hub/semantic-mappers/anthropic-mapper.js +70 -156
  17. package/dist/conversion/hub/semantic-mappers/chat-mapper.js +63 -52
  18. package/dist/conversion/hub/semantic-mappers/gemini-mapper.js +76 -143
  19. package/dist/conversion/hub/semantic-mappers/responses-mapper.js +40 -160
  20. package/dist/conversion/hub/standardized-bridge.js +3 -0
  21. package/dist/conversion/hub/tool-governance/rules.js +2 -2
  22. package/dist/conversion/index.d.ts +5 -0
  23. package/dist/conversion/index.js +5 -0
  24. package/dist/conversion/pipeline/codecs/v2/anthropic-openai-pipeline.d.ts +12 -0
  25. package/dist/conversion/pipeline/codecs/v2/anthropic-openai-pipeline.js +100 -0
  26. package/dist/conversion/pipeline/codecs/v2/openai-openai-pipeline.d.ts +15 -0
  27. package/dist/conversion/pipeline/codecs/v2/openai-openai-pipeline.js +174 -0
  28. package/dist/conversion/pipeline/codecs/v2/responses-openai-pipeline.d.ts +14 -0
  29. package/dist/conversion/pipeline/codecs/v2/responses-openai-pipeline.js +166 -0
  30. package/dist/conversion/pipeline/codecs/v2/shared/openai-chat-helpers.d.ts +13 -0
  31. package/dist/conversion/pipeline/codecs/v2/shared/openai-chat-helpers.js +66 -0
  32. package/dist/conversion/pipeline/hooks/adapter-context.d.ts +7 -0
  33. package/dist/conversion/pipeline/hooks/adapter-context.js +18 -0
  34. package/dist/conversion/pipeline/hooks/protocol-hooks.d.ts +67 -0
  35. package/dist/conversion/pipeline/hooks/protocol-hooks.js +1 -0
  36. package/dist/conversion/pipeline/index.d.ts +35 -0
  37. package/dist/conversion/pipeline/index.js +103 -0
  38. package/dist/conversion/pipeline/meta/meta-bag.d.ts +20 -0
  39. package/dist/conversion/pipeline/meta/meta-bag.js +81 -0
  40. package/dist/conversion/pipeline/schema/canonical-chat.d.ts +18 -0
  41. package/dist/conversion/pipeline/schema/canonical-chat.js +1 -0
  42. package/dist/conversion/pipeline/schema/index.d.ts +1 -0
  43. package/dist/conversion/pipeline/schema/index.js +1 -0
  44. package/dist/conversion/responses/responses-openai-bridge.d.ts +48 -0
  45. package/dist/conversion/responses/responses-openai-bridge.js +157 -1146
  46. package/dist/conversion/shared/anthropic-message-utils.d.ts +12 -0
  47. package/dist/conversion/shared/anthropic-message-utils.js +587 -0
  48. package/dist/conversion/shared/bridge-actions.d.ts +39 -0
  49. package/dist/conversion/shared/bridge-actions.js +709 -0
  50. package/dist/conversion/shared/bridge-conversation-store.d.ts +41 -0
  51. package/dist/conversion/shared/bridge-conversation-store.js +279 -0
  52. package/dist/conversion/shared/bridge-id-utils.d.ts +7 -0
  53. package/dist/conversion/shared/bridge-id-utils.js +42 -0
  54. package/dist/conversion/shared/bridge-instructions.d.ts +1 -0
  55. package/dist/conversion/shared/bridge-instructions.js +113 -0
  56. package/dist/conversion/shared/bridge-message-types.d.ts +39 -0
  57. package/dist/conversion/shared/bridge-message-types.js +1 -0
  58. package/dist/conversion/shared/bridge-message-utils.d.ts +22 -0
  59. package/dist/conversion/shared/bridge-message-utils.js +473 -0
  60. package/dist/conversion/shared/bridge-metadata.d.ts +1 -0
  61. package/dist/conversion/shared/bridge-metadata.js +1 -0
  62. package/dist/conversion/shared/bridge-policies.d.ts +18 -0
  63. package/dist/conversion/shared/bridge-policies.js +276 -0
  64. package/dist/conversion/shared/bridge-request-adapter.d.ts +28 -0
  65. package/dist/conversion/shared/bridge-request-adapter.js +430 -0
  66. package/dist/conversion/shared/chat-output-normalizer.d.ts +4 -0
  67. package/dist/conversion/shared/chat-output-normalizer.js +56 -0
  68. package/dist/conversion/shared/chat-request-filters.js +24 -1
  69. package/dist/conversion/shared/gemini-tool-utils.d.ts +5 -0
  70. package/dist/conversion/shared/gemini-tool-utils.js +130 -0
  71. package/dist/conversion/shared/metadata-passthrough.d.ts +11 -0
  72. package/dist/conversion/shared/metadata-passthrough.js +57 -0
  73. package/dist/conversion/shared/output-content-normalizer.d.ts +12 -0
  74. package/dist/conversion/shared/output-content-normalizer.js +119 -0
  75. package/dist/conversion/shared/reasoning-normalizer.d.ts +21 -0
  76. package/dist/conversion/shared/reasoning-normalizer.js +368 -0
  77. package/dist/conversion/shared/reasoning-tool-normalizer.d.ts +12 -0
  78. package/dist/conversion/shared/reasoning-tool-normalizer.js +132 -0
  79. package/dist/conversion/shared/reasoning-tool-parser.d.ts +10 -0
  80. package/dist/conversion/shared/reasoning-tool-parser.js +95 -0
  81. package/dist/conversion/shared/reasoning-utils.d.ts +2 -0
  82. package/dist/conversion/shared/reasoning-utils.js +42 -0
  83. package/dist/conversion/shared/responses-conversation-store.js +5 -11
  84. package/dist/conversion/shared/responses-message-utils.d.ts +15 -0
  85. package/dist/conversion/shared/responses-message-utils.js +206 -0
  86. package/dist/conversion/shared/responses-output-builder.d.ts +15 -0
  87. package/dist/conversion/shared/responses-output-builder.js +179 -0
  88. package/dist/conversion/shared/responses-output-utils.d.ts +7 -0
  89. package/dist/conversion/shared/responses-output-utils.js +108 -0
  90. package/dist/conversion/shared/responses-request-adapter.d.ts +28 -0
  91. package/dist/conversion/shared/responses-request-adapter.js +9 -40
  92. package/dist/conversion/shared/responses-response-utils.d.ts +3 -0
  93. package/dist/conversion/shared/responses-response-utils.js +209 -0
  94. package/dist/conversion/shared/responses-tool-utils.d.ts +12 -0
  95. package/dist/conversion/shared/responses-tool-utils.js +90 -0
  96. package/dist/conversion/shared/responses-types.d.ts +33 -0
  97. package/dist/conversion/shared/responses-types.js +1 -0
  98. package/dist/conversion/shared/tool-call-utils.d.ts +11 -0
  99. package/dist/conversion/shared/tool-call-utils.js +56 -0
  100. package/dist/conversion/shared/tool-mapping.d.ts +19 -0
  101. package/dist/conversion/shared/tool-mapping.js +124 -0
  102. package/dist/conversion/shared/tool-normalizers.d.ts +4 -0
  103. package/dist/conversion/shared/tool-normalizers.js +84 -0
  104. package/dist/router/virtual-router/bootstrap.js +18 -3
  105. package/dist/router/virtual-router/provider-registry.js +4 -2
  106. package/dist/router/virtual-router/types.d.ts +212 -0
  107. package/dist/sse/index.d.ts +38 -2
  108. package/dist/sse/index.js +27 -0
  109. package/dist/sse/json-to-sse/anthropic-json-to-sse-converter.d.ts +14 -0
  110. package/dist/sse/json-to-sse/anthropic-json-to-sse-converter.js +106 -73
  111. package/dist/sse/json-to-sse/chat-json-to-sse-converter.js +6 -2
  112. package/dist/sse/json-to-sse/gemini-json-to-sse-converter.d.ts +14 -0
  113. package/dist/sse/json-to-sse/gemini-json-to-sse-converter.js +99 -0
  114. package/dist/sse/json-to-sse/index.d.ts +7 -0
  115. package/dist/sse/json-to-sse/index.js +2 -0
  116. package/dist/sse/json-to-sse/sequencers/anthropic-sequencer.d.ts +13 -0
  117. package/dist/sse/json-to-sse/sequencers/anthropic-sequencer.js +150 -0
  118. package/dist/sse/json-to-sse/sequencers/chat-sequencer.d.ts +39 -0
  119. package/dist/sse/json-to-sse/sequencers/chat-sequencer.js +49 -3
  120. package/dist/sse/json-to-sse/sequencers/gemini-sequencer.d.ts +10 -0
  121. package/dist/sse/json-to-sse/sequencers/gemini-sequencer.js +95 -0
  122. package/dist/sse/json-to-sse/sequencers/responses-sequencer.js +31 -5
  123. package/dist/sse/registry/sse-codec-registry.d.ts +32 -0
  124. package/dist/sse/registry/sse-codec-registry.js +30 -1
  125. package/dist/sse/shared/reasoning-dispatcher.d.ts +10 -0
  126. package/dist/sse/shared/reasoning-dispatcher.js +25 -0
  127. package/dist/sse/shared/responses-output-normalizer.d.ts +12 -0
  128. package/dist/sse/shared/responses-output-normalizer.js +45 -0
  129. package/dist/sse/shared/serializers/anthropic-event-serializer.d.ts +2 -0
  130. package/dist/sse/shared/serializers/anthropic-event-serializer.js +9 -0
  131. package/dist/sse/shared/serializers/gemini-event-serializer.d.ts +2 -0
  132. package/dist/sse/shared/serializers/gemini-event-serializer.js +5 -0
  133. package/dist/sse/shared/serializers/index.d.ts +41 -0
  134. package/dist/sse/shared/serializers/index.js +2 -0
  135. package/dist/sse/shared/writer.d.ts +127 -0
  136. package/dist/sse/shared/writer.js +37 -1
  137. package/dist/sse/sse-to-json/anthropic-sse-to-json-converter.d.ts +11 -0
  138. package/dist/sse/sse-to-json/anthropic-sse-to-json-converter.js +92 -127
  139. package/dist/sse/sse-to-json/builders/anthropic-response-builder.d.ts +16 -0
  140. package/dist/sse/sse-to-json/builders/anthropic-response-builder.js +151 -0
  141. package/dist/sse/sse-to-json/builders/response-builder.d.ts +165 -0
  142. package/dist/sse/sse-to-json/builders/response-builder.js +27 -6
  143. package/dist/sse/sse-to-json/chat-sse-to-json-converter.d.ts +114 -0
  144. package/dist/sse/sse-to-json/chat-sse-to-json-converter.js +79 -3
  145. package/dist/sse/sse-to-json/gemini-sse-to-json-converter.d.ts +13 -0
  146. package/dist/sse/sse-to-json/gemini-sse-to-json-converter.js +160 -0
  147. package/dist/sse/sse-to-json/index.d.ts +7 -0
  148. package/dist/sse/sse-to-json/index.js +2 -0
  149. package/dist/sse/sse-to-json/parsers/sse-parser.js +53 -1
  150. package/dist/sse/types/anthropic-types.d.ts +170 -0
  151. package/dist/sse/types/anthropic-types.js +8 -5
  152. package/dist/sse/types/chat-types.d.ts +10 -0
  153. package/dist/sse/types/chat-types.js +2 -1
  154. package/dist/sse/types/core-interfaces.d.ts +1 -1
  155. package/dist/sse/types/gemini-types.d.ts +116 -0
  156. package/dist/sse/types/gemini-types.js +5 -0
  157. package/dist/sse/types/index.d.ts +5 -2
  158. package/dist/sse/types/index.js +2 -0
  159. package/package.json +1 -1
@@ -0,0 +1,473 @@
1
+ import { normalizeFunctionCallId, normalizeFunctionCallOutputId } from './bridge-id-utils.js';
2
+ import { normalizeChatMessageContent } from './chat-output-normalizer.js';
3
+ export function coerceBridgeRole(role) {
4
+ if (typeof role === 'string') {
5
+ const normalized = role.toLowerCase();
6
+ if (normalized === 'system' || normalized === 'assistant' || normalized === 'user' || normalized === 'tool') {
7
+ return normalized;
8
+ }
9
+ }
10
+ return 'user';
11
+ }
12
+ export function serializeToolArguments(argsStringOrObj, _functionName, _tools) {
13
+ if (typeof argsStringOrObj === 'string')
14
+ return argsStringOrObj;
15
+ try {
16
+ return JSON.stringify(argsStringOrObj ?? {});
17
+ }
18
+ catch {
19
+ return String(argsStringOrObj);
20
+ }
21
+ }
22
+ export function serializeToolOutput(entry) {
23
+ const out = entry?.output;
24
+ if (typeof out === 'string')
25
+ return out;
26
+ if (out && typeof out === 'object') {
27
+ try {
28
+ return JSON.stringify(out);
29
+ }
30
+ catch {
31
+ return String(out);
32
+ }
33
+ }
34
+ return null;
35
+ }
36
+ function collectText(value) {
37
+ if (!value)
38
+ return '';
39
+ if (typeof value === 'string')
40
+ return value;
41
+ if (Array.isArray(value)) {
42
+ return value.map(part => collectText(part)).join('');
43
+ }
44
+ if (typeof value === 'object') {
45
+ const record = value;
46
+ if (typeof record.text === 'string')
47
+ return record.text;
48
+ if (Array.isArray(record.content))
49
+ return collectText(record.content);
50
+ if (typeof record.content === 'string')
51
+ return record.content;
52
+ }
53
+ return '';
54
+ }
55
+ function extractUserTextFromEntry(entry) {
56
+ if (!entry || typeof entry !== 'object')
57
+ return '';
58
+ const directContent = entry.content ?? entry.message?.content;
59
+ if (typeof directContent === 'string')
60
+ return directContent.trim();
61
+ if (Array.isArray(directContent)) {
62
+ return directContent.map(block => collectText(block)).join('').trim();
63
+ }
64
+ const text = entry.text ?? entry.message?.text;
65
+ if (typeof text === 'string')
66
+ return text.trim();
67
+ return '';
68
+ }
69
+ export function convertMessagesToBridgeInput(options) {
70
+ const { messages, tools } = options;
71
+ const input = [];
72
+ const systemParts = [];
73
+ const originalSystemMessages = [];
74
+ let latestUserInstruction = null;
75
+ const pendingToolCallIds = [];
76
+ const knownToolCallIds = new Set();
77
+ for (const m of messages) {
78
+ if (!m || typeof m !== 'object')
79
+ continue;
80
+ const role = coerceBridgeRole(m.role || 'user');
81
+ const content = m.content;
82
+ const collectedText = collectText(content);
83
+ const text = role === 'system' ? collectedText : collectedText.trim();
84
+ if (role === 'system') {
85
+ if (collectedText && collectedText.length) {
86
+ originalSystemMessages.push(collectedText);
87
+ systemParts.push(collectedText);
88
+ }
89
+ continue;
90
+ }
91
+ if (role === 'tool') {
92
+ const rawToolId = m.tool_call_id ||
93
+ m.call_id ||
94
+ m.tool_use_id ||
95
+ m.id ||
96
+ undefined;
97
+ let callId = typeof rawToolId === 'string' && rawToolId.trim().length ? rawToolId.trim() : undefined;
98
+ if (callId && knownToolCallIds.has(callId)) {
99
+ const idx = pendingToolCallIds.indexOf(callId);
100
+ if (idx >= 0)
101
+ pendingToolCallIds.splice(idx, 1);
102
+ }
103
+ if (!callId && pendingToolCallIds.length) {
104
+ callId = pendingToolCallIds.shift();
105
+ }
106
+ if (!callId) {
107
+ callId = normalizeFunctionCallId({
108
+ callId,
109
+ fallback: `fc_call_${input.length + 1}`
110
+ });
111
+ }
112
+ knownToolCallIds.add(callId);
113
+ const normalizedId = normalizeFunctionCallOutputId({
114
+ callId,
115
+ fallback: `fc_tool_${input.length + 1}`
116
+ });
117
+ const entry = {
118
+ type: 'function_call_output',
119
+ id: normalizedId,
120
+ call_id: callId,
121
+ output: typeof text === 'string' ? text : ''
122
+ };
123
+ input.push(entry);
124
+ continue;
125
+ }
126
+ const toolCalls = Array.isArray(m.tool_calls) ? m.tool_calls : [];
127
+ if (toolCalls.length) {
128
+ for (const tc of toolCalls) {
129
+ try {
130
+ const rawIdCandidate = (typeof tc?.id === 'string' && tc.id.trim().length ? tc.id.trim() : undefined) ??
131
+ (typeof tc?.call_id === 'string' && tc.call_id.trim().length ? tc.call_id.trim() : undefined);
132
+ const callId = rawIdCandidate ?? normalizeFunctionCallId({
133
+ callId: rawIdCandidate,
134
+ fallback: `fc_call_${input.length + 1}`
135
+ });
136
+ const fn = tc?.function || {};
137
+ const name = typeof fn?.name === 'string' ? String(fn.name) : 'tool';
138
+ const argsRaw = fn?.arguments;
139
+ const args = typeof argsRaw === 'string'
140
+ ? argsRaw
141
+ : serializeToolArguments(argsRaw, name, tools);
142
+ const entry = {
143
+ type: 'function_call',
144
+ id: callId,
145
+ call_id: callId,
146
+ name,
147
+ arguments: args
148
+ };
149
+ input.push(entry);
150
+ knownToolCallIds.add(callId);
151
+ pendingToolCallIds.push(callId);
152
+ }
153
+ catch {
154
+ // ignore malformed tool_call
155
+ }
156
+ }
157
+ continue;
158
+ }
159
+ if (typeof text === 'string') {
160
+ const tRole = role === 'assistant' ? 'output_text' : 'input_text';
161
+ const entry = {
162
+ type: 'message',
163
+ role,
164
+ content: [{ type: tRole, text }]
165
+ };
166
+ input.push(entry);
167
+ if (role === 'user') {
168
+ const trimmed = typeof text === 'string' ? text.trim() : '';
169
+ if (trimmed.length) {
170
+ latestUserInstruction = trimmed;
171
+ }
172
+ }
173
+ }
174
+ }
175
+ if (!latestUserInstruction) {
176
+ for (let i = input.length - 1; i >= 0; i -= 1) {
177
+ const entry = input[i];
178
+ const roleSource = entry?.role ?? entry?.message?.role;
179
+ const role = typeof roleSource === 'string' ? roleSource.toLowerCase() : '';
180
+ if (role !== 'user')
181
+ continue;
182
+ const text = extractUserTextFromEntry(entry);
183
+ if (text) {
184
+ latestUserInstruction = text;
185
+ break;
186
+ }
187
+ }
188
+ }
189
+ const combinedSystemInstruction = systemParts.join('\n\n').trim();
190
+ return {
191
+ input,
192
+ combinedSystemInstruction: combinedSystemInstruction.length ? combinedSystemInstruction : undefined,
193
+ latestUserInstruction: latestUserInstruction || undefined,
194
+ originalSystemMessages
195
+ };
196
+ }
197
+ function defaultNormalizeFunctionName(raw) {
198
+ if (typeof raw !== 'string')
199
+ return undefined;
200
+ const trimmed = raw.trim();
201
+ return trimmed.length ? trimmed : undefined;
202
+ }
203
+ function toReasoningSegments(value) {
204
+ if (Array.isArray(value)) {
205
+ return value.map((entry) => (typeof entry === 'string' ? entry.trim() : '')).filter((entry) => entry.length);
206
+ }
207
+ if (typeof value === 'string') {
208
+ const trimmed = value.trim();
209
+ return trimmed.length ? [trimmed] : [];
210
+ }
211
+ return [];
212
+ }
213
+ function combineReasoningSegments(primary, secondary) {
214
+ const combined = [];
215
+ if (Array.isArray(primary)) {
216
+ combined.push(...primary.filter((entry) => typeof entry === 'string' && entry.trim().length).map((entry) => entry.trim()));
217
+ }
218
+ if (Array.isArray(secondary)) {
219
+ combined.push(...secondary.filter((entry) => typeof entry === 'string' && entry.trim().length).map((entry) => entry.trim()));
220
+ }
221
+ return combined;
222
+ }
223
+ function pushNormalizedChatMessage(target, role, rawContent, options) {
224
+ if (typeof rawContent !== 'string') {
225
+ return;
226
+ }
227
+ const normalized = normalizeChatMessageContent(rawContent);
228
+ const contentText = typeof normalized.contentText === 'string' ? normalized.contentText : '';
229
+ const reasoningText = typeof normalized.reasoningText === 'string' ? normalized.reasoningText.trim() : '';
230
+ const hasContent = contentText.trim().length > 0;
231
+ if (!hasContent && !reasoningText) {
232
+ return;
233
+ }
234
+ const message = {
235
+ role,
236
+ content: contentText
237
+ };
238
+ const combinedReasoning = combineReasoningSegments(reasoningText.length ? [reasoningText] : [], options?.reasoningSegments);
239
+ if (combinedReasoning.length) {
240
+ message.reasoning_content = combinedReasoning.join('\n');
241
+ }
242
+ target.push(message);
243
+ }
244
+ function processMessageBlocks(blocks, normalizeFunctionName, tools, toolNameById, lastToolCallId, toolResultFallbackText) {
245
+ const textParts = [];
246
+ const toolCalls = [];
247
+ const toolMessages = [];
248
+ let currentLastCall = lastToolCallId;
249
+ const reasoningSegments = [];
250
+ for (const block of blocks) {
251
+ if (!block || typeof block !== 'object')
252
+ continue;
253
+ const type = typeof block.type === 'string' ? block.type.toLowerCase() : '';
254
+ if (type === 'input_text' || type === 'output_text' || type === 'text' || type === 'commentary') {
255
+ if (typeof block.text === 'string')
256
+ textParts.push(block.text);
257
+ else if (typeof block.content === 'string')
258
+ textParts.push(block.content);
259
+ reasoningSegments.push(...toReasoningSegments(block.reasoning_content));
260
+ continue;
261
+ }
262
+ if (type === 'message' && Array.isArray(block.content)) {
263
+ const nested = processMessageBlocks(block.content, normalizeFunctionName, tools, toolNameById, currentLastCall, toolResultFallbackText);
264
+ if (nested.text)
265
+ textParts.push(nested.text);
266
+ for (const tc of nested.toolCalls)
267
+ toolCalls.push(tc);
268
+ for (const tm of nested.toolMessages)
269
+ toolMessages.push(tm);
270
+ currentLastCall = nested.lastCallId;
271
+ reasoningSegments.push(...nested.reasoningSegments);
272
+ continue;
273
+ }
274
+ if (type === 'function_call') {
275
+ const rawName = typeof block.name === 'string'
276
+ ? block.name
277
+ : (typeof block?.function?.name === 'string'
278
+ ? block.function.name
279
+ : undefined);
280
+ const name = normalizeFunctionName(rawName);
281
+ const args = block.arguments ?? block?.function?.arguments ?? {};
282
+ const parsedArgs = args;
283
+ const callIdCandidate = (typeof block.id === 'string' && block.id.trim().length ? block.id.trim() : undefined) ??
284
+ (typeof block.call_id === 'string' && block.call_id.trim().length ? block.call_id.trim() : undefined);
285
+ const callId = callIdCandidate ??
286
+ normalizeFunctionCallId({
287
+ callId: callIdCandidate,
288
+ fallback: `fc_call_${toolCalls.length + 1}`
289
+ });
290
+ if (typeof name !== 'string' || !name.trim()) {
291
+ currentLastCall = null;
292
+ continue;
293
+ }
294
+ const serialized = serializeToolArguments(parsedArgs, name, tools).trim();
295
+ toolNameById.set(callId, name);
296
+ toolCalls.push({ id: callId, type: 'function', function: { name, arguments: serialized } });
297
+ currentLastCall = callId;
298
+ continue;
299
+ }
300
+ if (type === 'function_call_output' || type === 'tool_result' || type === 'tool_message') {
301
+ let toolCallId = block.tool_call_id ||
302
+ block.call_id ||
303
+ block.tool_use_id ||
304
+ block.id ||
305
+ currentLastCall;
306
+ toolCallId = typeof toolCallId === 'string' && toolCallId.trim().length ? toolCallId.trim() : currentLastCall;
307
+ const output = serializeToolOutput(block);
308
+ if (toolCallId) {
309
+ try {
310
+ let contentStr = output != null ? String(output) : '';
311
+ if (!contentStr || contentStr.trim().length === 0) {
312
+ contentStr = toolResultFallbackText;
313
+ }
314
+ const nm = toolNameById.get(String(toolCallId));
315
+ const toolMsg = { role: 'tool', tool_call_id: String(toolCallId), content: contentStr };
316
+ if (typeof nm === 'string' && nm.trim().length)
317
+ toolMsg.name = nm;
318
+ toolMessages.push(toolMsg);
319
+ }
320
+ catch {
321
+ const fallback = (output ?? toolResultFallbackText);
322
+ const nm = toolNameById.get(String(toolCallId));
323
+ const toolMsg = { role: 'tool', tool_call_id: String(toolCallId), content: String(fallback) };
324
+ if (typeof nm === 'string' && nm.trim().length)
325
+ toolMsg.name = nm;
326
+ toolMessages.push(toolMsg);
327
+ }
328
+ currentLastCall = null;
329
+ }
330
+ continue;
331
+ }
332
+ }
333
+ const text = textParts.length ? textParts.join('\n').trim() : null;
334
+ return { text, toolCalls, toolMessages, lastCallId: currentLastCall, reasoningSegments };
335
+ }
336
+ export function convertBridgeInputToChatMessages(options) {
337
+ const { input, tools, normalizeFunctionName, toolResultFallbackText } = options;
338
+ const messages = [];
339
+ if (!Array.isArray(input))
340
+ return messages;
341
+ const toolNameById = new Map();
342
+ let lastToolCallId = null;
343
+ const resolveFunctionName = normalizeFunctionName ?? defaultNormalizeFunctionName;
344
+ const fallbackText = toolResultFallbackText ?? 'Command succeeded (no output).';
345
+ for (let entryIndex = 0; entryIndex < input.length; entryIndex++) {
346
+ const entry = input[entryIndex];
347
+ if (!entry || typeof entry !== 'object')
348
+ continue;
349
+ const entryType = typeof entry.type === 'string' ? entry.type.toLowerCase() : 'message';
350
+ const entryReasoningSegments = toReasoningSegments(entry.reasoning_content);
351
+ let entryReasoningConsumed = false;
352
+ const consumeEntryReasoning = () => {
353
+ if (entryReasoningConsumed || !entryReasoningSegments.length) {
354
+ return undefined;
355
+ }
356
+ entryReasoningConsumed = true;
357
+ return entryReasoningSegments;
358
+ };
359
+ if (typeof entry.content === 'string') {
360
+ const normalizedRole = coerceBridgeRole(entry.role || 'user');
361
+ const directText = (entry.content || '').toString();
362
+ pushNormalizedChatMessage(messages, normalizedRole, directText, {
363
+ reasoningSegments: consumeEntryReasoning()
364
+ });
365
+ continue;
366
+ }
367
+ if (entryType === 'function_call' || entryType === 'tool_call') {
368
+ const rawName = typeof entry.name === 'string'
369
+ ? entry.name
370
+ : (typeof entry?.function?.name === 'string' ? entry.function.name : undefined);
371
+ const name = resolveFunctionName(rawName);
372
+ if (typeof name !== 'string' || !name.trim()) {
373
+ continue;
374
+ }
375
+ const args = entry.arguments ?? entry?.function?.arguments ?? {};
376
+ const parsedArgs = args;
377
+ const callIdRaw = typeof entry.id === 'string' ? entry.id : (typeof entry.call_id === 'string' ? entry.call_id : undefined);
378
+ const callIdSource = typeof callIdRaw === 'string' && callIdRaw.trim().length ? callIdRaw.trim() : undefined;
379
+ let callId = callIdSource;
380
+ if (!callId) {
381
+ callId = normalizeFunctionCallId({
382
+ callId: callIdSource,
383
+ fallback: `fc_call_${messages.length + 1}`
384
+ });
385
+ }
386
+ const serialized = serializeToolArguments(parsedArgs, name, tools).trim();
387
+ toolNameById.set(callId, name);
388
+ messages.push({ role: 'assistant', tool_calls: [{ id: callId, type: 'function', function: { name, arguments: serialized } }] });
389
+ lastToolCallId = callId;
390
+ continue;
391
+ }
392
+ if (entryType === 'function_call_output' || entryType === 'tool_result' || entryType === 'tool_message') {
393
+ let toolCallId = entry.tool_call_id ||
394
+ entry.call_id ||
395
+ entry.tool_use_id ||
396
+ entry.id ||
397
+ lastToolCallId;
398
+ toolCallId = typeof toolCallId === 'string' && toolCallId.trim().length ? toolCallId.trim() : (lastToolCallId ?? undefined);
399
+ const output = serializeToolOutput(entry);
400
+ if (toolCallId) {
401
+ try {
402
+ let contentStr = output != null ? String(output) : '';
403
+ if (!contentStr || contentStr.trim().length === 0) {
404
+ contentStr = fallbackText;
405
+ }
406
+ const nm = toolNameById.get(String(toolCallId));
407
+ const toolMsg = { role: 'tool', tool_call_id: String(toolCallId), content: contentStr };
408
+ if (typeof nm === 'string' && nm.trim().length)
409
+ toolMsg.name = nm;
410
+ messages.push(toolMsg);
411
+ }
412
+ catch {
413
+ const fallback = (output ?? fallbackText);
414
+ const nm = toolNameById.get(String(toolCallId));
415
+ const toolMsg = { role: 'tool', tool_call_id: String(toolCallId), content: String(fallback) };
416
+ if (typeof nm === 'string' && nm.trim().length)
417
+ toolMsg.name = nm;
418
+ messages.push(toolMsg);
419
+ }
420
+ lastToolCallId = null;
421
+ }
422
+ continue;
423
+ }
424
+ let handledViaExplicitMessage = false;
425
+ if (entry && typeof entry.message === 'object' && Array.isArray(entry.message?.content)) {
426
+ const explicit = entry.message;
427
+ const nested = processMessageBlocks(Array.isArray(explicit.content) ? explicit.content : [], resolveFunctionName, tools, toolNameById, lastToolCallId, fallbackText);
428
+ if (nested.toolCalls.length)
429
+ messages.push({ role: 'assistant', tool_calls: nested.toolCalls });
430
+ for (const msg of nested.toolMessages)
431
+ messages.push(msg);
432
+ const normalizedRole = coerceBridgeRole((explicit.role ?? entry.role) || 'user');
433
+ if (typeof nested.text === 'string') {
434
+ pushNormalizedChatMessage(messages, normalizedRole, nested.text, {
435
+ reasoningSegments: combineReasoningSegments(consumeEntryReasoning(), nested.reasoningSegments)
436
+ });
437
+ }
438
+ lastToolCallId = nested.lastCallId;
439
+ handledViaExplicitMessage = true;
440
+ }
441
+ if (!handledViaExplicitMessage) {
442
+ const nested = processMessageBlocks(Array.isArray(entry.content) ? entry.content : [], resolveFunctionName, tools, toolNameById, lastToolCallId, fallbackText);
443
+ if (nested.toolCalls.length)
444
+ messages.push({ role: 'assistant', tool_calls: nested.toolCalls });
445
+ for (const msg of nested.toolMessages)
446
+ messages.push(msg);
447
+ const normalizedRole = coerceBridgeRole(entry.role || 'user');
448
+ if (typeof nested.text === 'string') {
449
+ pushNormalizedChatMessage(messages, normalizedRole, nested.text, {
450
+ reasoningSegments: combineReasoningSegments(consumeEntryReasoning(), nested.reasoningSegments)
451
+ });
452
+ }
453
+ lastToolCallId = nested.lastCallId;
454
+ }
455
+ try {
456
+ const t = String(entry.type || '').toLowerCase();
457
+ if ((t === 'input_text' || t === 'text' || t === 'output_text' || t === 'commentary') &&
458
+ typeof entry.text === 'string') {
459
+ const normalizedRole = coerceBridgeRole(entry.role || 'user');
460
+ const s = entry.text;
461
+ if (s && s.length) {
462
+ pushNormalizedChatMessage(messages, normalizedRole, s, {
463
+ reasoningSegments: consumeEntryReasoning()
464
+ });
465
+ }
466
+ }
467
+ }
468
+ catch {
469
+ /* ignore */
470
+ }
471
+ }
472
+ return messages;
473
+ }
@@ -0,0 +1 @@
1
+ export declare const BRIDGE_RAW_SYSTEM_METADATA_KEY = "__rcc_raw_system";
@@ -0,0 +1 @@
1
+ export const BRIDGE_RAW_SYSTEM_METADATA_KEY = '__rcc_raw_system';
@@ -0,0 +1,18 @@
1
+ import type { BridgeActionDescriptor, BridgeActionStage } from './bridge-actions.js';
2
+ type PhaseConfig = {
3
+ inbound?: BridgeActionDescriptor[];
4
+ outbound?: BridgeActionDescriptor[];
5
+ };
6
+ export interface BridgePolicy {
7
+ id: string;
8
+ protocol?: string;
9
+ moduleType?: string;
10
+ request?: PhaseConfig;
11
+ response?: PhaseConfig;
12
+ }
13
+ export declare function resolveBridgePolicy(options: {
14
+ protocol?: string;
15
+ moduleType?: string;
16
+ } | undefined): BridgePolicy | undefined;
17
+ export declare function resolvePolicyActions(policy: BridgePolicy | undefined, stage: BridgeActionStage): BridgeActionDescriptor[] | undefined;
18
+ export {};