@jsonstudio/llms 0.6.938 → 0.6.1164

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 (131) hide show
  1. package/dist/conversion/hub/operation-table/operation-table-runner.d.ts +18 -0
  2. package/dist/conversion/hub/operation-table/operation-table-runner.js +158 -0
  3. package/dist/conversion/hub/operation-table/semantic-mappers/anthropic-mapper.d.ts +8 -0
  4. package/dist/conversion/hub/operation-table/semantic-mappers/anthropic-mapper.js +303 -0
  5. package/dist/conversion/hub/operation-table/semantic-mappers/chat-mapper.d.ts +8 -0
  6. package/dist/conversion/hub/operation-table/semantic-mappers/chat-mapper.js +413 -0
  7. package/dist/conversion/hub/operation-table/semantic-mappers/gemini-mapper.d.ts +7 -0
  8. package/dist/conversion/hub/operation-table/semantic-mappers/gemini-mapper.js +841 -0
  9. package/dist/conversion/hub/operation-table/semantic-mappers/responses-mapper.d.ts +21 -0
  10. package/dist/conversion/hub/operation-table/semantic-mappers/responses-mapper.js +535 -0
  11. package/dist/conversion/hub/ops/operations.d.ts +19 -0
  12. package/dist/conversion/hub/ops/operations.js +126 -0
  13. package/dist/conversion/hub/pipeline/hub-pipeline.d.ts +9 -0
  14. package/dist/conversion/hub/pipeline/hub-pipeline.js +533 -24
  15. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage2_semantic_map/index.js +6 -0
  16. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/index.js +6 -3
  17. package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/index.js +11 -0
  18. package/dist/conversion/hub/policy/policy-engine.js +41 -9
  19. package/dist/conversion/hub/policy/protocol-spec.d.ts +25 -0
  20. package/dist/conversion/hub/policy/protocol-spec.js +73 -23
  21. package/dist/conversion/hub/process/chat-process.js +252 -41
  22. package/dist/conversion/hub/response/provider-response.js +175 -2
  23. package/dist/conversion/hub/response/response-runtime.js +1 -1
  24. package/dist/conversion/hub/semantic-mappers/anthropic-mapper.d.ts +1 -8
  25. package/dist/conversion/hub/semantic-mappers/anthropic-mapper.js +1 -365
  26. package/dist/conversion/hub/semantic-mappers/chat-mapper.d.ts +1 -8
  27. package/dist/conversion/hub/semantic-mappers/chat-mapper.js +1 -436
  28. package/dist/conversion/hub/semantic-mappers/gemini-mapper.d.ts +1 -7
  29. package/dist/conversion/hub/semantic-mappers/gemini-mapper.js +1 -894
  30. package/dist/conversion/hub/semantic-mappers/responses-mapper.d.ts +1 -21
  31. package/dist/conversion/hub/semantic-mappers/responses-mapper.js +1 -593
  32. package/dist/conversion/hub/tool-surface/tool-surface-engine.d.ts +18 -0
  33. package/dist/conversion/hub/tool-surface/tool-surface-engine.js +571 -0
  34. package/dist/conversion/responses/responses-openai-bridge.js +14 -2
  35. package/dist/conversion/shared/bridge-message-utils.js +2 -8
  36. package/dist/conversion/shared/bridge-policies.js +5 -105
  37. package/dist/conversion/shared/gemini-tool-utils.js +121 -4
  38. package/dist/conversion/shared/protocol-field-allowlists.d.ts +7 -0
  39. package/dist/conversion/shared/protocol-field-allowlists.js +145 -0
  40. package/dist/conversion/shared/reasoning-tool-normalizer.js +4 -2
  41. package/dist/conversion/shared/snapshot-hooks.js +166 -3
  42. package/dist/conversion/shared/text-markup-normalizer.d.ts +2 -0
  43. package/dist/conversion/shared/text-markup-normalizer.js +345 -9
  44. package/dist/conversion/shared/thought-signature-validator.d.ts +52 -0
  45. package/dist/conversion/shared/thought-signature-validator.js +170 -0
  46. package/dist/conversion/shared/tool-argument-repairer.d.ts +39 -0
  47. package/dist/conversion/shared/tool-argument-repairer.js +56 -0
  48. package/dist/conversion/shared/tool-call-id-manager.d.ts +113 -0
  49. package/dist/conversion/shared/tool-call-id-manager.js +231 -0
  50. package/dist/conversion/shared/tool-canonicalizer.js +2 -11
  51. package/dist/router/virtual-router/bootstrap.js +54 -5
  52. package/dist/router/virtual-router/engine-selection.js +132 -42
  53. package/dist/router/virtual-router/engine.d.ts +3 -0
  54. package/dist/router/virtual-router/engine.js +142 -33
  55. package/dist/router/virtual-router/health-weighted.d.ts +25 -0
  56. package/dist/router/virtual-router/health-weighted.js +63 -0
  57. package/dist/router/virtual-router/load-balancer.d.ts +2 -0
  58. package/dist/router/virtual-router/load-balancer.js +45 -16
  59. package/dist/router/virtual-router/routing-instructions.js +17 -1
  60. package/dist/router/virtual-router/sticky-session-store.js +136 -24
  61. package/dist/router/virtual-router/stop-message-file-resolver.d.ts +1 -0
  62. package/dist/router/virtual-router/stop-message-file-resolver.js +74 -0
  63. package/dist/router/virtual-router/stop-message-state-sync.d.ts +15 -0
  64. package/dist/router/virtual-router/stop-message-state-sync.js +57 -0
  65. package/dist/router/virtual-router/types.d.ts +70 -0
  66. package/dist/servertool/clock/config.d.ts +7 -0
  67. package/dist/servertool/clock/config.js +27 -0
  68. package/dist/servertool/clock/daemon.d.ts +3 -0
  69. package/dist/servertool/clock/daemon.js +79 -0
  70. package/dist/servertool/clock/io.d.ts +2 -0
  71. package/dist/servertool/clock/io.js +13 -0
  72. package/dist/servertool/clock/paths.d.ts +4 -0
  73. package/dist/servertool/clock/paths.js +25 -0
  74. package/dist/servertool/clock/session-store.d.ts +3 -0
  75. package/dist/servertool/clock/session-store.js +56 -0
  76. package/dist/servertool/clock/state.d.ts +5 -0
  77. package/dist/servertool/clock/state.js +62 -0
  78. package/dist/servertool/clock/task-store.d.ts +5 -0
  79. package/dist/servertool/clock/task-store.js +4 -0
  80. package/dist/servertool/clock/tasks.d.ts +17 -0
  81. package/dist/servertool/clock/tasks.js +221 -0
  82. package/dist/servertool/clock/types.d.ts +36 -0
  83. package/dist/servertool/clock/types.js +1 -0
  84. package/dist/servertool/engine.d.ts +2 -0
  85. package/dist/servertool/engine.js +164 -8
  86. package/dist/servertool/followup-shadow.d.ts +16 -0
  87. package/dist/servertool/followup-shadow.js +145 -0
  88. package/dist/servertool/handlers/apply-patch-guard.js +1 -265
  89. package/dist/servertool/handlers/clock-auto.d.ts +1 -0
  90. package/dist/servertool/handlers/clock-auto.js +160 -0
  91. package/dist/servertool/handlers/clock.d.ts +1 -0
  92. package/dist/servertool/handlers/clock.js +197 -0
  93. package/dist/servertool/handlers/exec-command-guard.js +7 -555
  94. package/dist/servertool/handlers/followup-request-builder.d.ts +15 -7
  95. package/dist/servertool/handlers/followup-request-builder.js +248 -28
  96. package/dist/servertool/handlers/gemini-empty-reply-continue.js +62 -169
  97. package/dist/servertool/handlers/iflow-model-error-retry.js +18 -28
  98. package/dist/servertool/handlers/recursive-detection-guard.d.ts +1 -0
  99. package/dist/servertool/handlers/recursive-detection-guard.js +333 -0
  100. package/dist/servertool/handlers/stop-message-auto.js +47 -175
  101. package/dist/servertool/handlers/vision.d.ts +7 -1
  102. package/dist/servertool/handlers/vision.js +61 -117
  103. package/dist/servertool/handlers/web-search.d.ts +7 -1
  104. package/dist/servertool/handlers/web-search.js +122 -105
  105. package/dist/servertool/reenter-backend.d.ts +23 -0
  106. package/dist/servertool/reenter-backend.js +18 -0
  107. package/dist/servertool/server-side-tools.d.ts +3 -2
  108. package/dist/servertool/server-side-tools.js +64 -10
  109. package/dist/servertool/types.d.ts +92 -3
  110. package/dist/sse/json-to-sse/event-generators/responses.js +3 -21
  111. package/dist/sse/shared/serializers/responses-event-serializer.d.ts +8 -0
  112. package/dist/sse/shared/serializers/responses-event-serializer.js +19 -0
  113. package/dist/sse/shared/writer.js +24 -7
  114. package/dist/tools/apply-patch/execution-capturer.js +3 -1
  115. package/dist/tools/apply-patch/json/parse-loose.d.ts +3 -0
  116. package/dist/tools/apply-patch/json/parse-loose.js +139 -0
  117. package/dist/tools/apply-patch/patch-text/context-diff.d.ts +1 -0
  118. package/dist/tools/apply-patch/patch-text/context-diff.js +173 -0
  119. package/dist/tools/apply-patch/patch-text/git-diff.d.ts +1 -0
  120. package/dist/tools/apply-patch/patch-text/git-diff.js +138 -0
  121. package/dist/tools/apply-patch/patch-text/looks-like-patch.d.ts +1 -0
  122. package/dist/tools/apply-patch/patch-text/looks-like-patch.js +13 -0
  123. package/dist/tools/apply-patch/patch-text/normalize.d.ts +3 -0
  124. package/dist/tools/apply-patch/patch-text/normalize.js +262 -0
  125. package/dist/tools/apply-patch/structured/coercion.d.ts +3 -0
  126. package/dist/tools/apply-patch/structured/coercion.js +82 -0
  127. package/dist/tools/apply-patch/validation/shared.d.ts +3 -0
  128. package/dist/tools/apply-patch/validation/shared.js +6 -0
  129. package/dist/tools/apply-patch/validator.d.ts +2 -2
  130. package/dist/tools/apply-patch/validator.js +6 -556
  131. package/package.json +1 -1
@@ -1,436 +1 @@
1
- import { isJsonObject, jsonClone } from '../types/json.js';
2
- import { createBridgeActionState, runBridgeActionPipeline } from '../../shared/bridge-actions.js';
3
- import { resolveBridgePolicy, resolvePolicyActions } from '../../shared/bridge-policies.js';
4
- import { normalizeChatMessageContent } from '../../shared/chat-output-normalizer.js';
5
- import { ensureProtocolState } from '../../shared/protocol-state.js';
6
- const CHAT_PARAMETER_KEYS = [
7
- 'model',
8
- 'temperature',
9
- 'top_p',
10
- 'top_k',
11
- 'max_tokens',
12
- 'frequency_penalty',
13
- 'presence_penalty',
14
- 'logit_bias',
15
- 'response_format',
16
- 'parallel_tool_calls',
17
- 'tool_choice',
18
- 'seed',
19
- 'user',
20
- 'metadata',
21
- 'stop',
22
- 'stop_sequences',
23
- 'stream'
24
- ];
25
- const KNOWN_TOP_LEVEL_FIELDS = new Set([
26
- 'messages',
27
- 'tools',
28
- 'tool_outputs',
29
- ...CHAT_PARAMETER_KEYS,
30
- 'stageExpectations',
31
- 'stages'
32
- ]);
33
- function flattenSystemContent(content) {
34
- if (typeof content === 'string')
35
- return content;
36
- if (Array.isArray(content)) {
37
- return content.map(flattenSystemContent).filter(Boolean).join('\n');
38
- }
39
- if (content && typeof content === 'object') {
40
- const obj = content;
41
- if (typeof obj.text === 'string')
42
- return obj.text;
43
- if (typeof obj.content === 'string')
44
- return obj.content;
45
- if (Array.isArray(obj.content))
46
- return obj.content.map(flattenSystemContent).join('\n');
47
- }
48
- return '';
49
- }
50
- function normalizeToolContent(content) {
51
- if (typeof content === 'string')
52
- return content;
53
- if (content === null || content === undefined)
54
- return '';
55
- try {
56
- return JSON.stringify(content);
57
- }
58
- catch {
59
- return String(content ?? '');
60
- }
61
- }
62
- export function maybeAugmentApplyPatchErrorContent(content, toolName) {
63
- if (!content)
64
- return content;
65
- const lower = content.toLowerCase();
66
- const isApplyPatch = (typeof toolName === 'string' && toolName.trim() === 'apply_patch') ||
67
- lower.includes('apply_patch verification failed');
68
- if (!isApplyPatch) {
69
- return content;
70
- }
71
- // 避免重复追加提示。
72
- if (content.includes('[apply_patch hint]')) {
73
- return content;
74
- }
75
- const hint = '\n\n[apply_patch hint] 在使用 apply_patch 之前,请先读取目标文件的最新内容,并基于该内容生成补丁;同时确保补丁格式符合工具规范(统一补丁格式或结构化参数),避免上下文不匹配或语法错误。';
76
- return content + hint;
77
- }
78
- function recordToolCallIssues(message, messageIndex, missing) {
79
- const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : undefined;
80
- if (!toolCalls?.length)
81
- return;
82
- toolCalls.forEach((entry, callIndex) => {
83
- if (!isJsonObject(entry)) {
84
- missing.push({
85
- path: `messages[${messageIndex}].tool_calls[${callIndex}]`,
86
- reason: 'invalid_tool_call_entry',
87
- originalValue: jsonClone(entry)
88
- });
89
- return;
90
- }
91
- const fnBlock = entry.function;
92
- if (!isJsonObject(fnBlock)) {
93
- missing.push({
94
- path: `messages[${messageIndex}].tool_calls[${callIndex}].function`,
95
- reason: 'missing_tool_function',
96
- originalValue: jsonClone(fnBlock)
97
- });
98
- return;
99
- }
100
- const fnName = fnBlock.name;
101
- if (typeof fnName !== 'string' || !fnName.trim().length) {
102
- missing.push({
103
- path: `messages[${messageIndex}].tool_calls[${callIndex}].function.name`,
104
- reason: 'missing_tool_name'
105
- });
106
- }
107
- });
108
- }
109
- function collectSystemRawBlocks(raw) {
110
- if (!Array.isArray(raw))
111
- return undefined;
112
- const blocks = [];
113
- raw.forEach((entry) => {
114
- if (!isJsonObject(entry))
115
- return;
116
- if (String(entry.role ?? '').toLowerCase() !== 'system')
117
- return;
118
- blocks.push(jsonClone(entry));
119
- });
120
- return blocks.length ? blocks : undefined;
121
- }
122
- function normalizeChatMessages(raw) {
123
- const norm = {
124
- messages: [],
125
- systemSegments: [],
126
- toolOutputs: [],
127
- missingFields: []
128
- };
129
- if (raw === undefined) {
130
- norm.missingFields.push({ path: 'messages', reason: 'absent' });
131
- return norm;
132
- }
133
- if (!Array.isArray(raw)) {
134
- norm.missingFields.push({ path: 'messages', reason: 'invalid_type', originalValue: jsonClone(raw) });
135
- return norm;
136
- }
137
- raw.forEach((value, index) => {
138
- if (!isJsonObject(value)) {
139
- norm.missingFields.push({ path: `messages[${index}]`, reason: 'invalid_entry', originalValue: jsonClone(value) });
140
- return;
141
- }
142
- const roleValue = value.role;
143
- if (typeof roleValue !== 'string') {
144
- norm.missingFields.push({ path: `messages[${index}].role`, reason: 'missing_role' });
145
- return;
146
- }
147
- const chatMessage = value;
148
- if (roleValue !== 'system' && roleValue !== 'tool') {
149
- const normalizedContent = normalizeChatMessageContent(chatMessage.content);
150
- const shouldOverwriteContent = !Array.isArray(chatMessage.content);
151
- if (shouldOverwriteContent && normalizedContent.contentText !== undefined) {
152
- chatMessage.content = normalizedContent.contentText;
153
- }
154
- if (typeof normalizedContent.reasoningText === 'string' && normalizedContent.reasoningText.trim().length) {
155
- chatMessage.reasoning_content = normalizedContent.reasoningText.trim();
156
- }
157
- }
158
- norm.messages.push(chatMessage);
159
- const toolCallCandidate = value.tool_calls;
160
- if (Array.isArray(toolCallCandidate) && toolCallCandidate.length) {
161
- recordToolCallIssues(value, index, norm.missingFields);
162
- }
163
- if (roleValue === 'system') {
164
- const segment = flattenSystemContent(chatMessage.content);
165
- if (segment.trim().length) {
166
- norm.systemSegments.push(segment);
167
- }
168
- return;
169
- }
170
- if (roleValue === 'tool') {
171
- const rawCallId = (value.tool_call_id ?? value.call_id ?? value.id);
172
- const toolCallId = typeof rawCallId === 'string' && rawCallId.trim().length ? rawCallId.trim() : undefined;
173
- if (!toolCallId) {
174
- norm.missingFields.push({ path: `messages[${index}].tool_call_id`, reason: 'missing_tool_call_id' });
175
- return;
176
- }
177
- const nameValue = typeof value.name === 'string' && value.name.trim().length ? value.name : undefined;
178
- const outputEntry = {
179
- tool_call_id: toolCallId,
180
- content: normalizeToolContent(value.content ?? value.output),
181
- name: nameValue
182
- };
183
- outputEntry.content = maybeAugmentApplyPatchErrorContent(outputEntry.content, outputEntry.name);
184
- norm.toolOutputs.push(outputEntry);
185
- }
186
- });
187
- return norm;
188
- }
189
- function normalizeStandaloneToolOutputs(raw, missing) {
190
- if (!Array.isArray(raw) || raw.length === 0)
191
- return [];
192
- const outputs = [];
193
- raw.forEach((entry, index) => {
194
- if (!isJsonObject(entry)) {
195
- missing.push({ path: `tool_outputs[${index}]`, reason: 'invalid_entry', originalValue: jsonClone(entry) });
196
- return;
197
- }
198
- const rawCallId = entry.tool_call_id ?? entry.call_id ?? entry.id;
199
- const toolCallId = typeof rawCallId === 'string' && rawCallId.trim().length ? rawCallId.trim() : undefined;
200
- if (!toolCallId) {
201
- missing.push({ path: `tool_outputs[${index}].tool_call_id`, reason: 'missing_tool_call_id' });
202
- return;
203
- }
204
- const nameValue = typeof entry.name === 'string' && entry.name.trim().length ? entry.name : undefined;
205
- const rawContent = normalizeToolContent(entry.content ?? entry.output);
206
- const content = maybeAugmentApplyPatchErrorContent(rawContent, nameValue);
207
- outputs.push({
208
- tool_call_id: toolCallId,
209
- content,
210
- name: nameValue
211
- });
212
- });
213
- return outputs;
214
- }
215
- function normalizeTools(raw, missing) {
216
- if (!Array.isArray(raw) || raw.length === 0)
217
- return undefined;
218
- const tools = [];
219
- raw.forEach((entry, index) => {
220
- if (!isJsonObject(entry)) {
221
- missing.push({ path: `tools[${index}]`, reason: 'invalid_entry', originalValue: jsonClone(entry) });
222
- return;
223
- }
224
- tools.push(entry);
225
- });
226
- return tools.length ? tools : undefined;
227
- }
228
- function extractParameters(body) {
229
- const params = {};
230
- for (const key of CHAT_PARAMETER_KEYS) {
231
- if (body[key] !== undefined) {
232
- params[key] = body[key];
233
- }
234
- }
235
- return Object.keys(params).length ? params : undefined;
236
- }
237
- function collectExtraFields(body) {
238
- const extras = {};
239
- for (const [key, value] of Object.entries(body)) {
240
- if (KNOWN_TOP_LEVEL_FIELDS.has(key)) {
241
- continue;
242
- }
243
- if (value !== undefined) {
244
- extras[key] = jsonClone(value);
245
- }
246
- }
247
- return Object.keys(extras).length ? extras : undefined;
248
- }
249
- function extractOpenAIExtraFieldsFromSemantics(semantics) {
250
- if (!semantics || !semantics.providerExtras || !isJsonObject(semantics.providerExtras)) {
251
- return undefined;
252
- }
253
- const openaiExtras = semantics.providerExtras.openaiChat;
254
- if (!openaiExtras || !isJsonObject(openaiExtras)) {
255
- return undefined;
256
- }
257
- const stored = openaiExtras.extraFields;
258
- if (!stored || !isJsonObject(stored)) {
259
- return undefined;
260
- }
261
- return stored;
262
- }
263
- function hasExplicitEmptyToolsSemantics(semantics) {
264
- if (!semantics || !semantics.tools || !isJsonObject(semantics.tools)) {
265
- return false;
266
- }
267
- const flag = semantics.tools.explicitEmpty;
268
- return flag === true;
269
- }
270
- function buildOpenAISemantics(options) {
271
- const semantics = {};
272
- if (options.systemSegments && options.systemSegments.length) {
273
- semantics.system = {
274
- textBlocks: options.systemSegments.map((segment) => segment)
275
- };
276
- }
277
- if (options.extraFields && Object.keys(options.extraFields).length) {
278
- semantics.providerExtras = {
279
- openaiChat: {
280
- extraFields: jsonClone(options.extraFields)
281
- }
282
- };
283
- }
284
- if (options.explicitEmptyTools) {
285
- semantics.tools = {
286
- explicitEmpty: true
287
- };
288
- }
289
- return Object.keys(semantics).length ? semantics : undefined;
290
- }
291
- function applyExtraFields(body, metadata, semantics) {
292
- const sources = [];
293
- const semanticsExtras = extractOpenAIExtraFieldsFromSemantics(semantics);
294
- if (semanticsExtras) {
295
- sources.push(semanticsExtras);
296
- }
297
- if (metadata?.extraFields && isJsonObject(metadata.extraFields)) {
298
- sources.push(metadata.extraFields);
299
- }
300
- if (!sources.length) {
301
- return;
302
- }
303
- for (const source of sources) {
304
- for (const [key, value] of Object.entries(source)) {
305
- if (body[key] !== undefined) {
306
- continue;
307
- }
308
- body[key] = jsonClone(value);
309
- }
310
- }
311
- }
312
- export class ChatSemanticMapper {
313
- async toChat(format, ctx) {
314
- const payload = (format.payload ?? {});
315
- const normalized = normalizeChatMessages(payload.messages);
316
- const topLevelOutputs = normalizeStandaloneToolOutputs(payload.tool_outputs, normalized.missingFields);
317
- const toolOutputs = [...normalized.toolOutputs];
318
- for (const entry of topLevelOutputs) {
319
- if (!toolOutputs.find(item => item.tool_call_id === entry.tool_call_id)) {
320
- toolOutputs.push(entry);
321
- }
322
- }
323
- const metadata = { context: ctx };
324
- if (normalized.systemSegments.length) {
325
- metadata.systemInstructions = normalized.systemSegments;
326
- }
327
- const rawSystemBlocks = collectSystemRawBlocks(payload.messages);
328
- if (rawSystemBlocks) {
329
- const protocolState = ensureProtocolState(metadata, 'openai');
330
- protocolState.systemMessages = jsonClone(rawSystemBlocks);
331
- }
332
- if (normalized.missingFields.length) {
333
- metadata.missingFields = normalized.missingFields;
334
- }
335
- const extraFields = collectExtraFields(payload);
336
- if (extraFields) {
337
- metadata.extraFields = extraFields;
338
- }
339
- try {
340
- const bridgePolicy = resolveBridgePolicy({ protocol: 'openai-chat' });
341
- const actions = resolvePolicyActions(bridgePolicy, 'request_inbound');
342
- if (actions?.length) {
343
- const actionState = createBridgeActionState({
344
- messages: normalized.messages,
345
- rawRequest: payload,
346
- metadata: metadata
347
- });
348
- runBridgeActionPipeline({
349
- stage: 'request_inbound',
350
- actions,
351
- protocol: bridgePolicy?.protocol ?? 'openai-chat',
352
- moduleType: bridgePolicy?.moduleType ?? 'openai-chat',
353
- requestId: ctx.requestId,
354
- state: actionState
355
- });
356
- }
357
- }
358
- catch {
359
- // noop: best-effort policy application
360
- }
361
- const explicitEmptyTools = Array.isArray(payload.tools) && payload.tools.length === 0;
362
- if (explicitEmptyTools) {
363
- metadata.toolsFieldPresent = true;
364
- }
365
- const semantics = buildOpenAISemantics({
366
- systemSegments: normalized.systemSegments,
367
- extraFields,
368
- explicitEmptyTools
369
- });
370
- return {
371
- messages: normalized.messages,
372
- tools: normalizeTools(payload.tools, normalized.missingFields),
373
- toolOutputs: toolOutputs.length ? toolOutputs : undefined,
374
- parameters: extractParameters(payload),
375
- semantics,
376
- metadata
377
- };
378
- }
379
- async fromChat(chat, ctx) {
380
- const shouldEmitEmptyTools = hasExplicitEmptyToolsSemantics(chat.semantics) || chat.metadata?.toolsFieldPresent === true;
381
- const payload = {
382
- messages: chat.messages,
383
- tools: chat.tools ?? (shouldEmitEmptyTools ? [] : undefined),
384
- ...(chat.parameters || {})
385
- };
386
- applyExtraFields(payload, chat.metadata, chat.semantics);
387
- try {
388
- const bridgePolicy = resolveBridgePolicy({ protocol: 'openai-chat' });
389
- const actions = resolvePolicyActions(bridgePolicy, 'request_outbound');
390
- if (actions?.length && Array.isArray(payload.messages)) {
391
- const capturedToolResults = Array.isArray(chat.toolOutputs)
392
- ? chat.toolOutputs.map((entry) => ({
393
- tool_call_id: entry.tool_call_id,
394
- output: entry.content,
395
- name: entry.name
396
- }))
397
- : undefined;
398
- const actionState = createBridgeActionState({
399
- messages: payload.messages,
400
- rawRequest: payload,
401
- metadata: chat.metadata,
402
- capturedToolResults
403
- });
404
- runBridgeActionPipeline({
405
- stage: 'request_outbound',
406
- actions,
407
- protocol: bridgePolicy?.protocol ?? 'openai-chat',
408
- moduleType: bridgePolicy?.moduleType ?? 'openai-chat',
409
- requestId: ctx.requestId,
410
- state: actionState
411
- });
412
- }
413
- }
414
- catch {
415
- // ignore policy failures
416
- }
417
- // Do not forward tool_outputs to provider wire formats. OpenAI Chat
418
- // endpoints expect tool results to appear as tool role messages, and
419
- // sending the legacy top-level field causes upstream HTTP 400 responses.
420
- // Concrete translation happens earlier when responses input is unfolded
421
- // into ChatEnvelope.messages, so the provider request only needs the
422
- // canonical message list.
423
- if (payload.max_tokens === undefined && typeof payload.max_output_tokens === 'number') {
424
- payload.max_tokens = payload.max_output_tokens;
425
- delete payload.max_output_tokens;
426
- }
427
- return {
428
- protocol: 'openai-chat',
429
- direction: 'response',
430
- payload,
431
- meta: {
432
- context: ctx
433
- }
434
- };
435
- }
436
- }
1
+ export { ChatSemanticMapper, maybeAugmentApplyPatchErrorContent } from '../operation-table/semantic-mappers/chat-mapper.js';
@@ -1,7 +1 @@
1
- import type { SemanticMapper } from '../format-adapters/index.js';
2
- import type { AdapterContext, ChatEnvelope } from '../types/chat-envelope.js';
3
- import type { FormatEnvelope } from '../types/format-envelope.js';
4
- export declare class GeminiSemanticMapper implements SemanticMapper {
5
- toChat(format: FormatEnvelope, ctx: AdapterContext): Promise<ChatEnvelope>;
6
- fromChat(chat: ChatEnvelope, ctx: AdapterContext): Promise<FormatEnvelope>;
7
- }
1
+ export { GeminiSemanticMapper } from '../operation-table/semantic-mappers/gemini-mapper.js';