@jsonstudio/llms 0.4.6 → 0.6.2

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 (99) hide show
  1. package/dist/conversion/codecs/anthropic-openai-codec.js +28 -2
  2. package/dist/conversion/codecs/gemini-openai-codec.js +23 -0
  3. package/dist/conversion/codecs/responses-openai-codec.js +8 -1
  4. package/dist/conversion/hub/node-support.js +14 -1
  5. package/dist/conversion/hub/pipeline/hub-pipeline.d.ts +66 -0
  6. package/dist/conversion/hub/pipeline/hub-pipeline.js +284 -193
  7. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage1_format_parse/index.d.ts +11 -0
  8. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage1_format_parse/index.js +6 -0
  9. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage2_semantic_map/index.d.ts +16 -0
  10. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage2_semantic_map/index.js +17 -0
  11. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/context-factories.d.ts +5 -0
  12. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/context-factories.js +17 -0
  13. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/index.d.ts +19 -0
  14. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/index.js +269 -0
  15. package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/index.d.ts +18 -0
  16. package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/index.js +141 -0
  17. package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage2_format_build/index.d.ts +11 -0
  18. package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage2_format_build/index.js +29 -0
  19. package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage1_tool_governance/index.d.ts +16 -0
  20. package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage1_tool_governance/index.js +15 -0
  21. package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage2_route_select/index.d.ts +17 -0
  22. package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage2_route_select/index.js +18 -0
  23. package/dist/conversion/hub/pipeline/stages/resp_inbound/resp_inbound_stage1_sse_decode/index.d.ts +17 -0
  24. package/dist/conversion/hub/pipeline/stages/resp_inbound/resp_inbound_stage1_sse_decode/index.js +63 -0
  25. package/dist/conversion/hub/pipeline/stages/resp_inbound/resp_inbound_stage2_format_parse/index.d.ts +11 -0
  26. package/dist/conversion/hub/pipeline/stages/resp_inbound/resp_inbound_stage2_format_parse/index.js +6 -0
  27. package/dist/conversion/hub/pipeline/stages/resp_inbound/resp_inbound_stage3_semantic_map/index.d.ts +12 -0
  28. package/dist/conversion/hub/pipeline/stages/resp_inbound/resp_inbound_stage3_semantic_map/index.js +6 -0
  29. package/dist/conversion/hub/pipeline/stages/resp_outbound/resp_outbound_stage1_client_remap/index.d.ts +13 -0
  30. package/dist/conversion/hub/pipeline/stages/resp_outbound/resp_outbound_stage1_client_remap/index.js +43 -0
  31. package/dist/conversion/hub/pipeline/stages/resp_outbound/resp_outbound_stage2_sse_stream/index.d.ts +17 -0
  32. package/dist/conversion/hub/pipeline/stages/resp_outbound/resp_outbound_stage2_sse_stream/index.js +22 -0
  33. package/dist/conversion/hub/pipeline/stages/resp_process/resp_process_stage1_tool_governance/index.d.ts +16 -0
  34. package/dist/conversion/hub/pipeline/stages/resp_process/resp_process_stage1_tool_governance/index.js +19 -0
  35. package/dist/conversion/hub/pipeline/stages/resp_process/resp_process_stage2_finalize/index.d.ts +17 -0
  36. package/dist/conversion/hub/pipeline/stages/resp_process/resp_process_stage2_finalize/index.js +19 -0
  37. package/dist/conversion/hub/pipeline/stages/utils.d.ts +2 -0
  38. package/dist/conversion/hub/pipeline/stages/utils.js +11 -0
  39. package/dist/conversion/hub/pipeline/target-utils.d.ts +5 -0
  40. package/dist/conversion/hub/pipeline/target-utils.js +87 -0
  41. package/dist/conversion/hub/process/chat-process.js +23 -17
  42. package/dist/conversion/hub/response/provider-response.js +69 -122
  43. package/dist/conversion/hub/response/response-mappers.d.ts +19 -0
  44. package/dist/conversion/hub/response/response-mappers.js +22 -2
  45. package/dist/conversion/hub/response/response-runtime.d.ts +8 -0
  46. package/dist/conversion/hub/response/response-runtime.js +239 -6
  47. package/dist/conversion/hub/semantic-mappers/anthropic-mapper.d.ts +8 -0
  48. package/dist/conversion/hub/semantic-mappers/anthropic-mapper.js +135 -55
  49. package/dist/conversion/hub/semantic-mappers/chat-mapper.js +80 -40
  50. package/dist/conversion/hub/semantic-mappers/gemini-mapper.js +5 -29
  51. package/dist/conversion/hub/semantic-mappers/responses-mapper.js +16 -13
  52. package/dist/conversion/hub/snapshot-recorder.d.ts +13 -0
  53. package/dist/conversion/hub/snapshot-recorder.js +90 -50
  54. package/dist/conversion/hub/standardized-bridge.js +49 -38
  55. package/dist/conversion/hub/types/chat-envelope.d.ts +68 -0
  56. package/dist/conversion/hub/types/standardized.d.ts +97 -0
  57. package/dist/conversion/pipeline/codecs/v2/anthropic-openai-pipeline.js +29 -2
  58. package/dist/conversion/pipeline/codecs/v2/responses-openai-pipeline.js +68 -1
  59. package/dist/conversion/responses/responses-openai-bridge.d.ts +6 -1
  60. package/dist/conversion/responses/responses-openai-bridge.js +132 -10
  61. package/dist/conversion/shared/anthropic-message-utils.d.ts +9 -1
  62. package/dist/conversion/shared/anthropic-message-utils.js +414 -26
  63. package/dist/conversion/shared/bridge-actions.js +267 -95
  64. package/dist/conversion/shared/bridge-message-utils.js +54 -8
  65. package/dist/conversion/shared/bridge-policies.js +21 -2
  66. package/dist/conversion/shared/chat-envelope-validator.d.ts +8 -0
  67. package/dist/conversion/shared/chat-envelope-validator.js +128 -0
  68. package/dist/conversion/shared/chat-request-filters.js +109 -28
  69. package/dist/conversion/shared/mcp-injection.js +41 -20
  70. package/dist/conversion/shared/openai-finalizer.d.ts +11 -0
  71. package/dist/conversion/shared/openai-finalizer.js +73 -0
  72. package/dist/conversion/shared/openai-message-normalize.js +32 -31
  73. package/dist/conversion/shared/protocol-state.d.ts +4 -0
  74. package/dist/conversion/shared/protocol-state.js +23 -0
  75. package/dist/conversion/shared/reasoning-normalizer.d.ts +1 -0
  76. package/dist/conversion/shared/reasoning-normalizer.js +50 -18
  77. package/dist/conversion/shared/responses-output-builder.d.ts +1 -1
  78. package/dist/conversion/shared/responses-output-builder.js +76 -25
  79. package/dist/conversion/shared/responses-reasoning-registry.d.ts +8 -0
  80. package/dist/conversion/shared/responses-reasoning-registry.js +61 -0
  81. package/dist/conversion/shared/responses-response-utils.js +32 -2
  82. package/dist/conversion/shared/responses-tool-utils.js +28 -2
  83. package/dist/conversion/shared/snapshot-hooks.d.ts +9 -0
  84. package/dist/conversion/shared/snapshot-hooks.js +60 -6
  85. package/dist/conversion/shared/snapshot-utils.d.ts +16 -0
  86. package/dist/conversion/shared/snapshot-utils.js +84 -0
  87. package/dist/conversion/shared/tool-filter-pipeline.js +46 -7
  88. package/dist/conversion/shared/tool-mapping.js +13 -2
  89. package/dist/filters/index.d.ts +18 -0
  90. package/dist/filters/index.js +0 -1
  91. package/dist/filters/special/request-streaming-to-nonstreaming.d.ts +13 -0
  92. package/dist/filters/special/request-streaming-to-nonstreaming.js +13 -1
  93. package/dist/filters/special/request-tool-choice-policy.js +3 -1
  94. package/dist/filters/special/request-tool-list-filter.d.ts +11 -0
  95. package/dist/filters/special/request-tool-list-filter.js +20 -7
  96. package/dist/sse/shared/responses-output-normalizer.js +5 -4
  97. package/dist/sse/sse-to-json/builders/response-builder.js +24 -1
  98. package/dist/sse/types/responses-types.d.ts +2 -0
  99. package/package.json +1 -1
@@ -0,0 +1,68 @@
1
+ export type ChatRole = 'system' | 'user' | 'assistant' | 'tool';
2
+ import type { JsonObject, JsonValue } from './json.js';
3
+ export interface ChatMessageContentPart {
4
+ type: string;
5
+ text?: string;
6
+ [key: string]: JsonValue;
7
+ }
8
+ export interface ChatToolCall {
9
+ id: string;
10
+ type: 'function';
11
+ function: {
12
+ name: string;
13
+ arguments: string;
14
+ };
15
+ [key: string]: JsonValue;
16
+ }
17
+ export interface ChatMessage {
18
+ role: ChatRole;
19
+ content?: string | ChatMessageContentPart[] | null;
20
+ tool_calls?: ChatToolCall[];
21
+ name?: string;
22
+ [key: string]: JsonValue;
23
+ }
24
+ export interface ChatToolDefinition {
25
+ type: 'function' | string;
26
+ function: {
27
+ name: string;
28
+ description?: string;
29
+ parameters?: JsonValue;
30
+ strict?: boolean;
31
+ };
32
+ [key: string]: JsonValue;
33
+ }
34
+ export interface ChatToolOutput {
35
+ tool_call_id: string;
36
+ content: string;
37
+ name?: string;
38
+ [key: string]: JsonValue;
39
+ }
40
+ export interface MissingField extends JsonObject {
41
+ path: string;
42
+ reason: string;
43
+ originalValue?: JsonValue;
44
+ }
45
+ export interface AdapterContext {
46
+ requestId: string;
47
+ entryEndpoint: string;
48
+ providerProtocol: string;
49
+ providerId?: string;
50
+ routeId?: string;
51
+ profileId?: string;
52
+ streamingHint?: 'auto' | 'force' | 'disable';
53
+ originalModelId?: string;
54
+ clientModelId?: string;
55
+ toolCallIdStyle?: 'fc' | 'preserve';
56
+ [key: string]: JsonValue;
57
+ }
58
+ export interface ChatEnvelope {
59
+ messages: ChatMessage[];
60
+ tools?: ChatToolDefinition[];
61
+ toolOutputs?: ChatToolOutput[];
62
+ parameters?: JsonObject;
63
+ metadata: {
64
+ context: AdapterContext;
65
+ missingFields?: MissingField[];
66
+ [key: string]: JsonValue;
67
+ };
68
+ }
@@ -0,0 +1,97 @@
1
+ import type { ChatMessageContentPart } from './chat-envelope.js';
2
+ import type { JsonObject } from './json.js';
3
+ export type ToolChoice = 'none' | 'auto' | 'required' | {
4
+ type: 'function';
5
+ function: {
6
+ name: string;
7
+ };
8
+ } | Record<string, unknown>;
9
+ export interface StandardizedTool {
10
+ type: 'function';
11
+ function: {
12
+ name: string;
13
+ description?: string;
14
+ parameters: {
15
+ type?: string | string[];
16
+ properties?: Record<string, unknown>;
17
+ required?: string[];
18
+ additionalProperties?: boolean;
19
+ [key: string]: unknown;
20
+ };
21
+ strict?: boolean;
22
+ };
23
+ }
24
+ export interface ToolCall {
25
+ id: string;
26
+ type: 'function';
27
+ function: {
28
+ name: string;
29
+ arguments: string;
30
+ };
31
+ }
32
+ export interface ToolCallResult {
33
+ tool_call_id: string;
34
+ status: 'success' | 'error' | 'timeout' | 'pending';
35
+ result?: JsonObject | JsonObject[] | string | number | boolean | null;
36
+ error?: string;
37
+ executionTime?: number;
38
+ }
39
+ export type StandardizedMessageContent = string | ChatMessageContentPart[] | null;
40
+ export interface StandardizedMessage {
41
+ role: 'system' | 'user' | 'assistant' | 'tool';
42
+ content: StandardizedMessageContent;
43
+ tool_calls?: ToolCall[];
44
+ tool_call_id?: string;
45
+ name?: string;
46
+ metadata?: Record<string, unknown>;
47
+ }
48
+ export interface StandardizedParameters {
49
+ temperature?: number;
50
+ max_tokens?: number;
51
+ top_p?: number;
52
+ frequency_penalty?: number;
53
+ presence_penalty?: number;
54
+ stop?: string | string[];
55
+ stream?: boolean;
56
+ [key: string]: unknown;
57
+ }
58
+ export interface StandardizedMetadata {
59
+ originalEndpoint: string;
60
+ capturedContext?: Record<string, unknown>;
61
+ requestId?: string;
62
+ stream?: boolean;
63
+ toolChoice?: ToolChoice;
64
+ providerKey?: string;
65
+ providerType?: string;
66
+ processMode?: 'chat' | 'passthrough';
67
+ routeHint?: string;
68
+ [key: string]: unknown;
69
+ }
70
+ export interface StandardizedRequest {
71
+ model: string;
72
+ messages: StandardizedMessage[];
73
+ tools?: StandardizedTool[];
74
+ parameters: StandardizedParameters;
75
+ metadata: StandardizedMetadata;
76
+ }
77
+ export interface ProcessedRequest extends StandardizedRequest {
78
+ processed: {
79
+ timestamp: number;
80
+ appliedRules: string[];
81
+ status: 'success' | 'partial' | 'failed';
82
+ };
83
+ processingMetadata: {
84
+ toolCalls?: ToolCallResult[];
85
+ streaming?: {
86
+ enabled: boolean;
87
+ chunkCount?: number;
88
+ totalTokens?: number;
89
+ };
90
+ context?: {
91
+ systemPrompt?: string;
92
+ conversationHistory?: string[];
93
+ relevantContext?: Record<string, unknown>;
94
+ };
95
+ passthrough?: boolean;
96
+ };
97
+ }
@@ -14,6 +14,23 @@ function assertJsonObject(value, stage) {
14
14
  }
15
15
  return value;
16
16
  }
17
+ function coerceAliasMap(candidate) {
18
+ if (!candidate || typeof candidate !== 'object' || Array.isArray(candidate)) {
19
+ return undefined;
20
+ }
21
+ let populated = false;
22
+ const result = {};
23
+ for (const [key, value] of Object.entries(candidate)) {
24
+ if (typeof key !== 'string' || typeof value !== 'string')
25
+ continue;
26
+ const trimmedKey = key.trim();
27
+ if (!trimmedKey.length)
28
+ continue;
29
+ result[trimmedKey] = value;
30
+ populated = true;
31
+ }
32
+ return populated ? result : undefined;
33
+ }
17
34
  function createAnthropicHooks() {
18
35
  const formatAdapter = new AnthropicFormatAdapter();
19
36
  const semanticMapper = new AnthropicSemanticMapper();
@@ -28,6 +45,12 @@ function createAnthropicHooks() {
28
45
  });
29
46
  const formatEnvelope = await formatAdapter.parseRequest(wire, adapterContext);
30
47
  const chatEnvelope = await semanticMapper.toChat(formatEnvelope, adapterContext);
48
+ const aliasMap = coerceAliasMap(adapterContext.anthropicToolNameMap) ??
49
+ coerceAliasMap(chatEnvelope.metadata?.anthropicToolNameMap);
50
+ if (aliasMap) {
51
+ context.metadata = context.metadata ?? {};
52
+ context.metadata.anthropicToolNameMap = aliasMap;
53
+ }
31
54
  const canonical = chatEnvelopeToStandardized(chatEnvelope, {
32
55
  adapterContext,
33
56
  endpoint: context.entryEndpoint ?? DEFAULT_ANTHROPIC_ENDPOINT,
@@ -37,8 +60,12 @@ function createAnthropicHooks() {
37
60
  }
38
61
  },
39
62
  outbound: {
40
- serialize: async ({ canonical }) => {
41
- const anthropicPayload = buildAnthropicFromOpenAIChat(canonical);
63
+ serialize: async ({ canonical, context }) => {
64
+ const aliasMap = coerceAliasMap(context.metadata?.anthropicToolNameMap);
65
+ const anthropicPayload = buildAnthropicFromOpenAIChat(canonical, {
66
+ toolNameMap: aliasMap,
67
+ requestId: context.requestId
68
+ });
42
69
  return { payload: assertJsonObject(anthropicPayload, 'anthropic_outbound_serialize') };
43
70
  }
44
71
  }
@@ -14,6 +14,71 @@ function assertJsonObject(value, stage) {
14
14
  }
15
15
  return value;
16
16
  }
17
+ function sanitizeResponsesMessages(payload) {
18
+ const messages = Array.isArray(payload?.messages) ? payload.messages : [];
19
+ if (!messages.length)
20
+ return;
21
+ const sanitized = [];
22
+ let counter = 0;
23
+ const normalizeId = (raw) => {
24
+ if (typeof raw !== 'string')
25
+ return undefined;
26
+ const trimmed = raw.trim();
27
+ if (!trimmed.length)
28
+ return undefined;
29
+ if (trimmed.startsWith('fc_'))
30
+ return trimmed;
31
+ const stripped = trimmed.replace(/^call[_-]?/i, '');
32
+ const normalized = stripped.length ? stripped : trimmed;
33
+ return normalized.startsWith('fc_') ? normalized : `fc_${normalized}`;
34
+ };
35
+ for (const message of messages) {
36
+ if (!message || typeof message !== 'object')
37
+ continue;
38
+ const role = String(message.role || '').toLowerCase();
39
+ if (role === 'assistant' && Array.isArray(message.tool_calls) && message.tool_calls.length) {
40
+ message.tool_calls = message.tool_calls.map((call) => {
41
+ if (!call || typeof call !== 'object')
42
+ return call;
43
+ const existing = normalizeId(call.id) ?? normalizeId(call.call_id) ?? `fc_function_call_${counter++}`;
44
+ if (existing) {
45
+ call.id = existing;
46
+ }
47
+ if (call.call_id !== undefined)
48
+ delete call.call_id;
49
+ if (call.tool_call_id !== undefined)
50
+ delete call.tool_call_id;
51
+ return call;
52
+ });
53
+ sanitized.push(message);
54
+ continue;
55
+ }
56
+ if (role === 'tool') {
57
+ const clone = { ...message };
58
+ const normalizedToolId = normalizeId(clone.tool_call_id ?? clone.call_id);
59
+ if (normalizedToolId) {
60
+ clone.tool_call_id = normalizedToolId;
61
+ }
62
+ else if (typeof clone.tool_call_id === 'string') {
63
+ const trimmed = clone.tool_call_id.trim();
64
+ if (!trimmed.length) {
65
+ delete clone.tool_call_id;
66
+ }
67
+ else {
68
+ clone.tool_call_id = trimmed;
69
+ }
70
+ }
71
+ if ('call_id' in clone)
72
+ delete clone.call_id;
73
+ if ('id' in clone)
74
+ delete clone.id;
75
+ sanitized.push(clone);
76
+ continue;
77
+ }
78
+ sanitized.push(message);
79
+ }
80
+ payload.messages = sanitized;
81
+ }
17
82
  function cloneResponsesContext(context) {
18
83
  try {
19
84
  return JSON.parse(JSON.stringify(context ?? {}));
@@ -143,7 +208,9 @@ export class ResponsesOpenAIPipelineCodec {
143
208
  entryEndpoint: context.entryEndpoint ?? DEFAULT_RESPONSES_ENDPOINT,
144
209
  endpoint: context.endpoint ?? DEFAULT_RESPONSES_ENDPOINT
145
210
  };
146
- return runStandardChatRequestFilters(openaiPayload, profile, filterContext);
211
+ const filtered = await runStandardChatRequestFilters(openaiPayload, profile, filterContext);
212
+ sanitizeResponsesMessages(filtered);
213
+ return filtered;
147
214
  }
148
215
  async convertResponse(payload, profile, context) {
149
216
  this.ensureInitialized();
@@ -1,7 +1,9 @@
1
1
  import type { BridgeInputItem, BridgeToolDefinition } from '../shared/bridge-message-types.js';
2
2
  import type { ChatToolDefinition } from '../hub/types/chat-envelope.js';
3
3
  import type { BridgeInputBuildResult } from '../shared/bridge-message-utils.js';
4
- export interface ResponsesRequestContext {
4
+ import type { ToolCallIdStyle } from '../shared/responses-tool-utils.js';
5
+ type Unknown = Record<string, unknown>;
6
+ export interface ResponsesRequestContext extends Unknown {
5
7
  requestId?: string;
6
8
  originalSystemMessages?: string[];
7
9
  input?: BridgeInputItem[];
@@ -24,6 +26,9 @@ export interface ResponsesRequestContext {
24
26
  } | null;
25
27
  toolsRaw?: BridgeToolDefinition[];
26
28
  toolsNormalized?: Array<Record<string, unknown>>;
29
+ parameters?: Record<string, unknown>;
30
+ systemInstruction?: string;
31
+ toolCallIdStyle?: ToolCallIdStyle;
27
32
  }
28
33
  export interface BuildChatRequestResult {
29
34
  request: Record<string, unknown>;
@@ -17,10 +17,11 @@ function isObject(v) {
17
17
  // NOTE: 自修复提示已移除(统一标准:不做模糊兜底)。
18
18
  // --- Public bridge functions ---
19
19
  export function captureResponsesContext(payload, dto) {
20
+ const preservedInput = cloneBridgeEntries(payload.input);
20
21
  ensureBridgeInstructions(payload);
21
22
  const context = {
22
23
  requestId: dto?.route?.requestId,
23
- input: Array.isArray(payload.input) ? payload.input : undefined,
24
+ input: preservedInput,
24
25
  include: payload.include,
25
26
  store: payload.store,
26
27
  toolChoice: payload.tool_choice,
@@ -30,8 +31,14 @@ export function captureResponsesContext(payload, dto) {
30
31
  stream: typeof payload.stream === 'boolean' ? payload.stream : undefined,
31
32
  isChatPayload: Array.isArray(payload.messages)
32
33
  };
34
+ if (payload.parameters && typeof payload.parameters === 'object') {
35
+ context.parameters = { ...payload.parameters };
36
+ }
37
+ if (typeof payload.instructions === 'string' && payload.instructions.trim().length) {
38
+ context.systemInstruction = payload.instructions;
39
+ }
33
40
  if (Array.isArray(payload.tools)) {
34
- context.toolsRaw = payload.tools;
41
+ context.toolsRaw = cloneBridgeEntries(payload.tools);
35
42
  }
36
43
  context.isResponsesPayload = !context.isChatPayload && Array.isArray(context.input);
37
44
  return context;
@@ -154,7 +161,6 @@ export function buildResponsesRequestFromChat(payload, ctx, extras) {
154
161
  'response_format',
155
162
  'user',
156
163
  'top_p',
157
- 'max_output_tokens',
158
164
  'logit_bias',
159
165
  'seed'
160
166
  ];
@@ -162,9 +168,6 @@ export function buildResponsesRequestFromChat(payload, ctx, extras) {
162
168
  if (chat[key] !== undefined)
163
169
  out[key] = chat[key];
164
170
  }
165
- if (typeof chat.max_tokens === 'number' && chat.max_output_tokens === undefined) {
166
- out.max_output_tokens = chat.max_tokens;
167
- }
168
171
  let messages = Array.isArray(chat.messages) ? chat.messages : [];
169
172
  let bridgeMetadata;
170
173
  try {
@@ -193,8 +196,21 @@ export function buildResponsesRequestFromChat(payload, ctx, extras) {
193
196
  // ignore policy errors
194
197
  }
195
198
  const envelopeMetadata = ctx?.metadata && typeof ctx.metadata === 'object' ? ctx.metadata : undefined;
196
- const toolCallIdStyle = resolveToolCallIdStyle(envelopeMetadata);
197
- const historySeed = normalizeBridgeHistory(bridgeMetadata?.bridgeHistory ?? envelopeMetadata?.bridgeHistory ?? extras?.bridgeHistory);
199
+ const metadataExtraFields = extractMetadataExtraFields(envelopeMetadata);
200
+ const contextToolCallIdStyle = readToolCallIdStyleFromContext(ctx);
201
+ const toolCallIdStyle = contextToolCallIdStyle ?? resolveToolCallIdStyle(envelopeMetadata);
202
+ const fallbackHistory = ctx?.input && Array.isArray(ctx.input)
203
+ ? {
204
+ input: ctx.input,
205
+ originalSystemMessages: ctx.originalSystemMessages,
206
+ combinedSystemInstruction: ctx.systemInstruction
207
+ }
208
+ : undefined;
209
+ const historySeed = normalizeBridgeHistory(extras?.bridgeHistory) ??
210
+ normalizeBridgeHistory(fallbackHistory) ??
211
+ normalizeBridgeHistory(bridgeMetadata?.bridgeHistory) ??
212
+ normalizeBridgeHistory(envelopeMetadata?.bridgeHistory) ??
213
+ fallbackHistory;
198
214
  const history = historySeed ??
199
215
  convertMessagesToBridgeInput({
200
216
  messages,
@@ -206,6 +222,7 @@ export function buildResponsesRequestFromChat(payload, ctx, extras) {
206
222
  }
207
223
  const { input, combinedSystemInstruction, originalSystemMessages } = history;
208
224
  const instructionCandidates = [
225
+ typeof ctx?.systemInstruction === 'string' && ctx.systemInstruction.trim().length ? ctx.systemInstruction.trim() : undefined,
209
226
  typeof extras?.systemInstruction === 'string' && extras.systemInstruction.trim().length ? extras.systemInstruction.trim() : undefined,
210
227
  typeof envelopeMetadata?.systemInstruction === 'string' && envelopeMetadata.systemInstruction.trim().length ? envelopeMetadata.systemInstruction.trim() : undefined,
211
228
  combinedSystemInstruction && combinedSystemInstruction.length > 0 ? combinedSystemInstruction : undefined
@@ -233,9 +250,112 @@ export function buildResponsesRequestFromChat(payload, ctx, extras) {
233
250
  else if (resolvedStream === false) {
234
251
  out.stream = false;
235
252
  }
253
+ if (ctx?.include !== undefined && out.include === undefined) {
254
+ out.include = ctx.include;
255
+ }
256
+ else if (metadataExtraFields?.include !== undefined && out.include === undefined) {
257
+ out.include = metadataExtraFields.include;
258
+ }
259
+ if (ctx?.store !== undefined && out.store === undefined) {
260
+ out.store = ctx.store;
261
+ }
262
+ else if (metadataExtraFields?.store !== undefined && out.store === undefined) {
263
+ out.store = metadataExtraFields.store;
264
+ }
265
+ if (ctx?.toolChoice !== undefined && out.tool_choice === undefined) {
266
+ out.tool_choice = ctx.toolChoice;
267
+ }
268
+ else if (metadataExtraFields?.tool_choice !== undefined && out.tool_choice === undefined) {
269
+ out.tool_choice = metadataExtraFields.tool_choice;
270
+ }
271
+ if (typeof ctx?.parallelToolCalls === 'boolean' && out.parallel_tool_calls === undefined) {
272
+ out.parallel_tool_calls = ctx.parallelToolCalls;
273
+ }
274
+ else if (typeof metadataExtraFields?.parallel_tool_calls === 'boolean' && out.parallel_tool_calls === undefined) {
275
+ out.parallel_tool_calls = metadataExtraFields.parallel_tool_calls;
276
+ }
277
+ if (ctx?.responseFormat !== undefined && out.response_format === undefined) {
278
+ out.response_format = ctx.responseFormat;
279
+ }
280
+ else if (metadataExtraFields?.response_format !== undefined && out.response_format === undefined) {
281
+ out.response_format = metadataExtraFields.response_format;
282
+ }
283
+ if (ctx?.metadata && Object.keys(ctx.metadata).length) {
284
+ out.metadata = { ...ctx.metadata };
285
+ }
286
+ else if (isPlainObject(metadataExtraFields?.metadata)) {
287
+ out.metadata = { ...metadataExtraFields.metadata };
288
+ }
289
+ if (ctx?.parameters && Object.keys(ctx.parameters).length) {
290
+ out.parameters = { ...ctx.parameters };
291
+ }
292
+ else if (chat.parameters && typeof chat.parameters === 'object') {
293
+ out.parameters = { ...chat.parameters };
294
+ }
295
+ else if (isPlainObject(metadataExtraFields?.parameters)) {
296
+ out.parameters = { ...metadataExtraFields.parameters };
297
+ }
236
298
  ensureBridgeInstructions(out);
237
299
  return { request: out, originalSystemMessages };
238
300
  }
301
+ function readToolCallIdStyleFromContext(ctx) {
302
+ if (!ctx) {
303
+ return undefined;
304
+ }
305
+ const direct = normalizeToolCallIdStyleCandidate(ctx.toolCallIdStyle);
306
+ if (direct) {
307
+ return direct;
308
+ }
309
+ if (ctx.metadata && typeof ctx.metadata === 'object') {
310
+ const fromMetadata = normalizeToolCallIdStyleCandidate(ctx.metadata.toolCallIdStyle);
311
+ if (fromMetadata) {
312
+ return fromMetadata;
313
+ }
314
+ }
315
+ return undefined;
316
+ }
317
+ function normalizeToolCallIdStyleCandidate(candidate) {
318
+ if (typeof candidate !== 'string') {
319
+ return undefined;
320
+ }
321
+ const normalized = candidate.trim().toLowerCase();
322
+ if (normalized === 'fc') {
323
+ return 'fc';
324
+ }
325
+ if (normalized === 'preserve') {
326
+ return 'preserve';
327
+ }
328
+ return undefined;
329
+ }
330
+ function cloneBridgeEntries(entries) {
331
+ if (!Array.isArray(entries)) {
332
+ return undefined;
333
+ }
334
+ return entries.map((entry) => {
335
+ if (!entry || typeof entry !== 'object') {
336
+ return entry;
337
+ }
338
+ try {
339
+ return JSON.parse(JSON.stringify(entry));
340
+ }
341
+ catch {
342
+ return entry;
343
+ }
344
+ });
345
+ }
346
+ function extractMetadataExtraFields(metadata) {
347
+ if (!metadata) {
348
+ return undefined;
349
+ }
350
+ const extras = metadata.extraFields;
351
+ if (extras && typeof extras === 'object' && !Array.isArray(extras)) {
352
+ return extras;
353
+ }
354
+ return undefined;
355
+ }
356
+ function isPlainObject(value) {
357
+ return Boolean(value && typeof value === 'object' && !Array.isArray(value));
358
+ }
239
359
  export function buildResponsesPayloadFromChat(payload, context) {
240
360
  if (!payload || typeof payload !== 'object')
241
361
  return payload;
@@ -297,9 +417,11 @@ export function buildResponsesPayloadFromChat(payload, context) {
297
417
  created_at: response.created_at || response.created || Math.floor(Date.now() / 1000),
298
418
  model: response.model,
299
419
  status: outputBuild.status,
300
- output: outputBuild.outputItems,
301
- output_text: outputBuild.outputText || ''
420
+ output: outputBuild.outputItems
302
421
  };
422
+ if (typeof outputBuild.outputText === 'string') {
423
+ out.output_text = outputBuild.outputText;
424
+ }
303
425
  if (outputBuild.usage !== undefined)
304
426
  out.usage = outputBuild.usage;
305
427
  if (outputBuild.requiredAction)
@@ -1,12 +1,20 @@
1
1
  import type { ChatToolDefinition, MissingField } from '../hub/types/chat-envelope.js';
2
+ import { type JsonObject } from '../hub/types/json.js';
2
3
  type Unknown = Record<string, unknown>;
3
4
  type UnknownArray = Unknown[];
4
5
  interface OpenAIChatPayload extends Unknown {
5
6
  messages: UnknownArray;
6
7
  }
8
+ export declare function normalizeAnthropicToolName(value: unknown): string | undefined;
9
+ export declare function denormalizeAnthropicToolName(value: unknown): string | undefined;
7
10
  export declare function buildOpenAIChatFromAnthropic(payload: unknown): OpenAIChatPayload;
8
- export declare function buildAnthropicFromOpenAIChat(oa: unknown): Unknown;
11
+ export interface BuildAnthropicFromOpenAIOptions {
12
+ toolNameMap?: Record<string, string>;
13
+ requestId?: string;
14
+ }
15
+ export declare function buildAnthropicFromOpenAIChat(oa: unknown, options?: BuildAnthropicFromOpenAIOptions): Unknown;
9
16
  export declare function buildAnthropicRequestFromOpenAIChat(chatReq: unknown): Unknown;
10
17
  export declare function mapAnthropicToolsToChat(rawTools: unknown, missing?: MissingField[]): ChatToolDefinition[] | undefined;
11
18
  export declare function mapChatToolsToAnthropicTools(rawTools: unknown): UnknownArray | undefined;
19
+ export declare function buildAnthropicToolAliasMap(rawTools: unknown): JsonObject | undefined;
12
20
  export {};