@jsonstudio/llms 0.6.802 → 0.6.954

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 (188) hide show
  1. package/dist/bridge/routecodex-adapter.d.ts +74 -0
  2. package/dist/config-unified/enhanced-path-resolver.d.ts +5 -0
  3. package/dist/config-unified/unified-config.d.ts +26 -0
  4. package/dist/conversion/codec-registry.d.ts +10 -0
  5. package/dist/conversion/codecs/gemini-openai-codec.d.ts +16 -0
  6. package/dist/conversion/codecs/openai-openai-codec.d.ts +12 -0
  7. package/dist/conversion/codecs/responses-openai-codec.d.ts +12 -0
  8. package/dist/conversion/compat/profiles/chat-gemini.json +12 -0
  9. package/dist/conversion/config/config-manager.d.ts +212 -0
  10. package/dist/conversion/hub/config/types.d.ts +26 -0
  11. package/dist/conversion/hub/core/detour-registry.d.ts +9 -0
  12. package/dist/conversion/hub/core/hub-context.d.ts +21 -0
  13. package/dist/conversion/hub/core/index.d.ts +3 -0
  14. package/dist/conversion/hub/core/stage-driver.d.ts +30 -0
  15. package/dist/conversion/hub/format-adapters/anthropic-format-adapter.d.ts +16 -0
  16. package/dist/conversion/hub/format-adapters/chat-format-adapter.d.ts +17 -0
  17. package/dist/conversion/hub/format-adapters/gemini-format-adapter.d.ts +16 -0
  18. package/dist/conversion/hub/format-adapters/index.d.ts +21 -0
  19. package/dist/conversion/hub/hub-feature.d.ts +1 -0
  20. package/dist/conversion/hub/node-support.d.ts +19 -0
  21. package/dist/conversion/hub/pipeline/compat/compat-pipeline-executor.js +11 -0
  22. package/dist/conversion/hub/pipeline/compat/compat-types.d.ts +3 -0
  23. package/dist/conversion/hub/pipeline/hub-pipeline.d.ts +7 -0
  24. package/dist/conversion/hub/pipeline/hub-pipeline.js +113 -17
  25. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/index.js +6 -3
  26. package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage1_tool_governance/index.js +4 -0
  27. package/dist/conversion/hub/pipeline/stages/resp_outbound/resp_outbound_stage1_client_remap/index.js +23 -1
  28. package/dist/conversion/hub/pipelines/inbound.d.ts +22 -0
  29. package/dist/conversion/hub/pipelines/outbound.d.ts +22 -0
  30. package/dist/conversion/hub/policy/policy-engine.d.ts +46 -0
  31. package/dist/conversion/hub/policy/policy-engine.js +176 -0
  32. package/dist/conversion/hub/policy/protocol-spec.d.ts +50 -0
  33. package/dist/conversion/hub/policy/protocol-spec.js +105 -0
  34. package/dist/conversion/hub/process/chat-process.d.ts +32 -0
  35. package/dist/conversion/hub/registry.d.ts +28 -0
  36. package/dist/conversion/hub/response/chat-response-utils.d.ts +6 -0
  37. package/dist/conversion/hub/response/provider-response.js +31 -0
  38. package/dist/conversion/hub/semantic-mappers/chat-mapper.js +32 -1
  39. package/dist/conversion/hub/semantic-mappers/gemini-mapper.d.ts +7 -0
  40. package/dist/conversion/hub/semantic-mappers/gemini-mapper.js +96 -1
  41. package/dist/conversion/hub/semantic-mappers/index.d.ts +4 -0
  42. package/dist/conversion/hub/semantic-mappers/responses-mapper.d.ts +21 -0
  43. package/dist/conversion/hub/standardized-bridge.d.ts +12 -0
  44. package/dist/conversion/hub/types/chat-schema.d.ts +112 -0
  45. package/dist/conversion/hub/types/errors.d.ts +5 -0
  46. package/dist/conversion/hub/types/format-envelope.d.ts +7 -0
  47. package/dist/conversion/hub/types/index.d.ts +6 -0
  48. package/dist/conversion/hub/types/json.d.ts +9 -0
  49. package/dist/conversion/hub/types/node.d.ts +31 -0
  50. package/dist/conversion/responses/responses-openai-bridge.js +263 -10
  51. package/dist/conversion/schema-validator.d.ts +7 -0
  52. package/dist/conversion/shared/args-mapping.d.ts +18 -0
  53. package/dist/conversion/shared/chat-request-filters.d.ts +9 -0
  54. package/dist/conversion/shared/errors.d.ts +1 -1
  55. package/dist/conversion/shared/gemini-tool-utils.js +105 -1
  56. package/dist/conversion/shared/jsonish.d.ts +3 -0
  57. package/dist/conversion/shared/mcp-injection.d.ts +2 -0
  58. package/dist/conversion/shared/media.d.ts +1 -0
  59. package/dist/conversion/shared/openai-message-normalize.d.ts +1 -0
  60. package/dist/conversion/shared/payload-budget.d.ts +13 -0
  61. package/dist/conversion/shared/reasoning-mapping.d.ts +5 -0
  62. package/dist/conversion/shared/responses-request-adapter.d.ts +1 -28
  63. package/dist/conversion/shared/responses-request-adapter.js +1 -430
  64. package/dist/conversion/shared/snapshot-hooks.js +58 -3
  65. package/dist/conversion/shared/tool-governor.js +8 -2
  66. package/dist/conversion/shared/tool-harvester.d.ts +31 -0
  67. package/dist/conversion/shared/tool-mapping.js +10 -29
  68. package/dist/conversion/types.d.ts +33 -0
  69. package/dist/filters/builtin/add-fields-filter.d.ts +8 -0
  70. package/dist/filters/builtin/blacklist-filter.d.ts +8 -0
  71. package/dist/filters/builtin/whitelist-filter.d.ts +8 -0
  72. package/dist/filters/engine.d.ts +16 -0
  73. package/dist/filters/special/request-tool-choice-policy.d.ts +11 -0
  74. package/dist/filters/special/response-finish-invariants.d.ts +11 -0
  75. package/dist/filters/special/response-openai-to-responses-bridge.d.ts +13 -0
  76. package/dist/filters/special/response-tool-arguments-blacklist.d.ts +12 -0
  77. package/dist/filters/special/response-tool-arguments-schema-converge.d.ts +13 -0
  78. package/dist/filters/special/response-tool-arguments-stringify.d.ts +9 -0
  79. package/dist/filters/special/response-tool-arguments-whitelist.d.ts +11 -0
  80. package/dist/filters/special/tool-filter-hooks.d.ts +19 -0
  81. package/dist/filters/special/tool-post-constraints.d.ts +31 -0
  82. package/dist/filters/types.d.ts +68 -0
  83. package/dist/filters/utils/fieldmap-loader.d.ts +2 -0
  84. package/dist/filters/utils/snapshot-writer.d.ts +10 -0
  85. package/dist/guidance/index.d.ts +3 -0
  86. package/dist/guidance/index.js +78 -83
  87. package/dist/http/sse-response.d.ts +22 -0
  88. package/dist/router/virtual-router/bootstrap.d.ts +6 -0
  89. package/dist/router/virtual-router/bootstrap.js +49 -5
  90. package/dist/router/virtual-router/classifier.d.ts +10 -0
  91. package/dist/router/virtual-router/engine-selection.js +98 -11
  92. package/dist/router/virtual-router/engine.js +177 -31
  93. package/dist/router/virtual-router/error-center.d.ts +10 -0
  94. package/dist/router/virtual-router/features.d.ts +3 -0
  95. package/dist/router/virtual-router/routing-instructions.d.ts +23 -1
  96. package/dist/router/virtual-router/routing-instructions.js +120 -30
  97. package/dist/router/virtual-router/types.d.ts +11 -0
  98. package/dist/servertool/engine.js +192 -17
  99. package/dist/servertool/handlers/apply-patch-guard.js +269 -0
  100. package/dist/servertool/handlers/exec-command-guard.js +558 -0
  101. package/dist/servertool/handlers/followup-message-trimmer.d.ts +16 -0
  102. package/dist/servertool/handlers/followup-message-trimmer.js +198 -0
  103. package/dist/servertool/handlers/followup-request-builder.d.ts +17 -0
  104. package/dist/servertool/handlers/followup-request-builder.js +122 -0
  105. package/dist/servertool/handlers/gemini-empty-reply-continue.js +252 -51
  106. package/dist/servertool/handlers/iflow-model-error-retry.js +12 -22
  107. package/dist/servertool/handlers/stop-message-auto.js +237 -75
  108. package/dist/servertool/handlers/vision.js +15 -27
  109. package/dist/servertool/handlers/web-search.js +17 -43
  110. package/dist/servertool/server-side-tools.d.ts +3 -0
  111. package/dist/servertool/server-side-tools.js +3 -0
  112. package/dist/sse/json-to-sse/anthropic-json-to-sse-converter.d.ts +2 -1
  113. package/dist/sse/json-to-sse/chat-json-to-sse-converter.d.ts +80 -0
  114. package/dist/sse/json-to-sse/event-generators/chat.d.ts +55 -0
  115. package/dist/sse/json-to-sse/event-generators/responses.d.ts +99 -0
  116. package/dist/sse/json-to-sse/gemini-json-to-sse-converter.d.ts +2 -1
  117. package/dist/sse/json-to-sse/responses-json-to-sse-converter.d.ts +80 -0
  118. package/dist/sse/json-to-sse/sequencers/anthropic-sequencer.d.ts +1 -1
  119. package/dist/sse/json-to-sse/sequencers/chat-sequencer.d.ts +2 -2
  120. package/dist/sse/json-to-sse/sequencers/gemini-sequencer.d.ts +1 -1
  121. package/dist/sse/json-to-sse/sequencers/responses-sequencer.d.ts +40 -0
  122. package/dist/sse/shared/chat-serializer.d.ts +4 -0
  123. package/dist/sse/shared/constants.d.ts +272 -0
  124. package/dist/sse/shared/serializers/anthropic-event-serializer.d.ts +1 -1
  125. package/dist/sse/shared/serializers/base-serializer.d.ts +158 -0
  126. package/dist/sse/shared/serializers/chat-event-serializer.d.ts +82 -0
  127. package/dist/sse/shared/serializers/gemini-event-serializer.d.ts +1 -1
  128. package/dist/sse/shared/serializers/index.d.ts +2 -1
  129. package/dist/sse/shared/serializers/responses-event-serializer.d.ts +123 -0
  130. package/dist/sse/shared/serializers/types.d.ts +51 -0
  131. package/dist/sse/shared/utils.d.ts +254 -0
  132. package/dist/sse/shared/writer.d.ts +2 -2
  133. package/dist/sse/sse-to-json/anthropic-sse-to-json-converter.d.ts +1 -1
  134. package/dist/sse/sse-to-json/builders/anthropic-response-builder.d.ts +1 -1
  135. package/dist/sse/sse-to-json/builders/response-builder.d.ts +1 -1
  136. package/dist/sse/sse-to-json/chat-sse-to-json-converter.d.ts +2 -1
  137. package/dist/sse/sse-to-json/gemini-sse-to-json-converter.d.ts +2 -1
  138. package/dist/sse/sse-to-json/parsers/sse-parser.d.ts +73 -0
  139. package/dist/sse/sse-to-json/responses-sse-to-json-converter.d.ts +1 -1
  140. package/dist/sse/types/chat-types.d.ts +1 -1
  141. package/dist/sse/types/responses-types.d.ts +1 -1
  142. package/dist/tools/apply-patch/execution-capturer.d.ts +13 -0
  143. package/dist/tools/apply-patch/execution-capturer.js +158 -0
  144. package/dist/tools/apply-patch/regression-capturer.d.ts +1 -0
  145. package/dist/tools/apply-patch/regression-capturer.js +5 -4
  146. package/dist/tools/apply-patch/structured.js +109 -13
  147. package/dist/tools/apply-patch/validator.js +112 -18
  148. package/dist/tools/tool-registry.d.ts +8 -0
  149. package/dist/tools/tool-registry.js +2 -1
  150. package/package.json +4 -4
  151. package/dist/conversion/compat/actions/apply-patch-format-fixer.js +0 -233
  152. package/dist/conversion/config/compat-profiles.json +0 -38
  153. package/dist/conversion/hub/pipeline/context-limit.d.ts +0 -13
  154. package/dist/conversion/hub/pipeline/context-limit.js +0 -55
  155. package/dist/conversion/hub/response/server-side-tools.d.ts +0 -26
  156. package/dist/conversion/hub/response/server-side-tools.js +0 -383
  157. package/dist/conversion/shared/bridge-conversation-store.d.ts +0 -41
  158. package/dist/conversion/shared/bridge-conversation-store.js +0 -279
  159. package/dist/conversion/shared/bridge-request-adapter.d.ts +0 -28
  160. package/dist/conversion/shared/bridge-request-adapter.js +0 -430
  161. package/dist/conversion/shared/responses-id-utils.js +0 -42
  162. package/dist/conversion/shared/responses-instructions.js +0 -113
  163. package/dist/conversion/shared/responses-message-utils.d.ts +0 -15
  164. package/dist/conversion/shared/responses-message-utils.js +0 -206
  165. package/dist/conversion/shared/responses-metadata.js +0 -1
  166. package/dist/conversion/shared/responses-output-utils.d.ts +0 -7
  167. package/dist/conversion/shared/responses-output-utils.js +0 -108
  168. package/dist/conversion/shared/responses-types.d.ts +0 -33
  169. package/dist/conversion/shared/tool-normalizers.d.ts +0 -4
  170. package/dist/conversion/shared/tool-normalizers.js +0 -84
  171. package/dist/filters/special/request-streaming-to-nonstreaming.d.ts +0 -13
  172. package/dist/filters/special/request-streaming-to-nonstreaming.js +0 -39
  173. package/dist/filters/special/response-apply-patch-toon-decode.d.ts +0 -23
  174. package/dist/filters/special/response-apply-patch-toon-decode.js +0 -460
  175. package/dist/filters/special/response-tool-arguments-toon-decode.d.ts +0 -10
  176. package/dist/filters/special/response-tool-arguments-toon-decode.js +0 -154
  177. package/dist/servertool/flow-types.d.ts +0 -40
  178. package/dist/servertool/flow-types.js +0 -1
  179. package/dist/servertool/orchestration-types.d.ts +0 -33
  180. package/dist/servertool/orchestration-types.js +0 -1
  181. package/dist/servertool/vision-tool.d.ts +0 -2
  182. package/dist/servertool/vision-tool.js +0 -185
  183. package/dist/tools/patch-args-normalizer.d.ts +0 -15
  184. package/dist/tools/patch-args-normalizer.js +0 -472
  185. package/dist/utils/toon.d.ts +0 -4
  186. package/dist/utils/toon.js +0 -75
  187. /package/dist/{conversion/compat/actions/apply-patch-format-fixer.d.ts → servertool/handlers/apply-patch-guard.d.ts} +0 -0
  188. /package/dist/{conversion/shared/responses-types.js → servertool/handlers/exec-command-guard.d.ts} +0 -0
@@ -0,0 +1,198 @@
1
+ function isMessageRecord(value) {
2
+ return !!value && typeof value === 'object' && !Array.isArray(value);
3
+ }
4
+ function normalizeRole(role) {
5
+ return typeof role === 'string' ? role.trim().toLowerCase() : '';
6
+ }
7
+ function isSystemRole(role) {
8
+ const normalized = role.trim().toLowerCase();
9
+ return normalized === 'system' || normalized === 'developer';
10
+ }
11
+ function isUserMessage(msg) {
12
+ return normalizeRole(msg.role) === 'user';
13
+ }
14
+ function isToolResponseMessage(msg) {
15
+ const role = normalizeRole(msg.role);
16
+ return role === 'tool' || role === 'function';
17
+ }
18
+ function isAssistantToolCallMessage(msg) {
19
+ const role = normalizeRole(msg.role);
20
+ if (role !== 'assistant' && role !== 'model') {
21
+ return false;
22
+ }
23
+ const toolCalls = Array.isArray(msg.tool_calls)
24
+ ? (msg.tool_calls)
25
+ : [];
26
+ if (toolCalls.length > 0) {
27
+ return true;
28
+ }
29
+ const fnCall = msg.function_call;
30
+ if (fnCall && typeof fnCall === 'object' && !Array.isArray(fnCall)) {
31
+ return true;
32
+ }
33
+ return false;
34
+ }
35
+ function findPrevIndex(messages, startIndexExclusive, predicate) {
36
+ for (let i = startIndexExclusive - 1; i >= 0; i -= 1) {
37
+ const msg = messages[i];
38
+ if (!msg)
39
+ continue;
40
+ if (predicate(msg))
41
+ return i;
42
+ }
43
+ return null;
44
+ }
45
+ /**
46
+ * Trim OpenAI-style messages for internal servertool followups.
47
+ *
48
+ * Goal: avoid sending a massive chat history on auto-followup requests (e.g. stop_message_flow),
49
+ * which can push Gemini/Antigravity into empty/malformed responses under long-context loads.
50
+ *
51
+ * Strategy:
52
+ * - Always keep system/developer messages (regardless of position).
53
+ * - Keep only the tail of non-system messages (maxNonSystemMessages), preserving original order.
54
+ */
55
+ export function trimOpenAiMessagesForFollowup(rawMessages, options) {
56
+ const maxNonSystemMessages = typeof options?.maxNonSystemMessages === 'number' && Number.isFinite(options.maxNonSystemMessages)
57
+ ? Math.max(1, Math.floor(options.maxNonSystemMessages))
58
+ : 16;
59
+ const messages = Array.isArray(rawMessages) ? rawMessages : [];
60
+ if (!messages.length) {
61
+ return [];
62
+ }
63
+ const messageRecords = messages.filter(isMessageRecord);
64
+ if (!messageRecords.length) {
65
+ return [];
66
+ }
67
+ const nonSystemIndices = [];
68
+ for (let i = 0; i < messageRecords.length; i += 1) {
69
+ const entry = messageRecords[i];
70
+ const role = typeof entry.role === 'string' ? entry.role : '';
71
+ if (!role || isSystemRole(role)) {
72
+ continue;
73
+ }
74
+ nonSystemIndices.push(i);
75
+ }
76
+ if (nonSystemIndices.length <= maxNonSystemMessages) {
77
+ return messageRecords;
78
+ }
79
+ const keepSet = new Set(nonSystemIndices.slice(nonSystemIndices.length - maxNonSystemMessages));
80
+ // Expand keepSet to preserve tool-call adjacency:
81
+ // - If we keep tool responses, keep their preceding tool call + its anchor.
82
+ // - If we keep tool calls, keep their anchor + following tool responses.
83
+ //
84
+ // Gemini tool-calling constraint: functionCall turn must come immediately after a user turn
85
+ // or after a functionResponse turn. When trimming, we must not cut away the user anchor.
86
+ let changed = true;
87
+ let guard = 0;
88
+ while (changed && guard < 8) {
89
+ changed = false;
90
+ guard += 1;
91
+ const sorted = Array.from(keepSet).sort((a, b) => a - b);
92
+ for (const idx of sorted) {
93
+ const msg = messageRecords[idx];
94
+ if (!msg)
95
+ continue;
96
+ if (isToolResponseMessage(msg)) {
97
+ const toolCallIndex = findPrevIndex(messageRecords, idx, isAssistantToolCallMessage);
98
+ if (toolCallIndex !== null && !keepSet.has(toolCallIndex)) {
99
+ keepSet.add(toolCallIndex);
100
+ changed = true;
101
+ }
102
+ if (toolCallIndex !== null) {
103
+ const anchorIndex = findPrevIndex(messageRecords, toolCallIndex, (m) => isUserMessage(m) || isToolResponseMessage(m));
104
+ if (anchorIndex !== null && !keepSet.has(anchorIndex)) {
105
+ keepSet.add(anchorIndex);
106
+ changed = true;
107
+ }
108
+ }
109
+ continue;
110
+ }
111
+ if (isAssistantToolCallMessage(msg)) {
112
+ const anchorIndex = findPrevIndex(messageRecords, idx, (m) => isUserMessage(m) || isToolResponseMessage(m));
113
+ if (anchorIndex !== null && !keepSet.has(anchorIndex)) {
114
+ keepSet.add(anchorIndex);
115
+ changed = true;
116
+ }
117
+ for (let i = idx + 1; i < messageRecords.length; i += 1) {
118
+ const next = messageRecords[i];
119
+ if (!next)
120
+ continue;
121
+ if (!isToolResponseMessage(next)) {
122
+ break;
123
+ }
124
+ if (!keepSet.has(i)) {
125
+ keepSet.add(i);
126
+ changed = true;
127
+ }
128
+ }
129
+ }
130
+ }
131
+ }
132
+ // Ensure the first kept non-system message is a user turn (do not drop history; add an anchor).
133
+ const firstKeptNonSystem = (() => {
134
+ for (let i = 0; i < messageRecords.length; i += 1) {
135
+ const role = normalizeRole(messageRecords[i]?.role);
136
+ if (!role || isSystemRole(role))
137
+ continue;
138
+ if (keepSet.has(i))
139
+ return i;
140
+ }
141
+ return null;
142
+ })();
143
+ if (firstKeptNonSystem !== null && !isUserMessage(messageRecords[firstKeptNonSystem])) {
144
+ const userAnchor = findPrevIndex(messageRecords, firstKeptNonSystem, isUserMessage);
145
+ if (userAnchor !== null) {
146
+ keepSet.add(userAnchor);
147
+ // One more pass to ensure tool adjacency around the newly added anchor.
148
+ for (const idx of Array.from(keepSet).sort((a, b) => a - b)) {
149
+ const msg = messageRecords[idx];
150
+ if (!msg)
151
+ continue;
152
+ if (isToolResponseMessage(msg)) {
153
+ const toolCallIndex = findPrevIndex(messageRecords, idx, isAssistantToolCallMessage);
154
+ if (toolCallIndex !== null)
155
+ keepSet.add(toolCallIndex);
156
+ }
157
+ else if (isAssistantToolCallMessage(msg)) {
158
+ const anchorIndex = findPrevIndex(messageRecords, idx, (m) => isUserMessage(m) || isToolResponseMessage(m));
159
+ if (anchorIndex !== null)
160
+ keepSet.add(anchorIndex);
161
+ }
162
+ }
163
+ }
164
+ else {
165
+ // If there is no user message before the kept window, the history prefix is already invalid
166
+ // for Gemini tool-calling (tool_calls/functionCall must be preceded by user or tool response).
167
+ // In this case, preserve system/developer messages and start the followup from the first user
168
+ // message that exists inside the kept window.
169
+ let firstUserAfter = null;
170
+ for (let i = firstKeptNonSystem; i < messageRecords.length; i += 1) {
171
+ if (keepSet.has(i) && isUserMessage(messageRecords[i])) {
172
+ firstUserAfter = i;
173
+ break;
174
+ }
175
+ }
176
+ if (firstUserAfter !== null) {
177
+ for (const idx of Array.from(keepSet)) {
178
+ if (idx < firstUserAfter) {
179
+ keepSet.delete(idx);
180
+ }
181
+ }
182
+ }
183
+ }
184
+ }
185
+ const trimmed = [];
186
+ for (let i = 0; i < messageRecords.length; i += 1) {
187
+ const entry = messageRecords[i];
188
+ const role = typeof entry.role === 'string' ? entry.role : '';
189
+ if (role && isSystemRole(role)) {
190
+ trimmed.push(entry);
191
+ continue;
192
+ }
193
+ if (keepSet.has(i)) {
194
+ trimmed.push(entry);
195
+ }
196
+ }
197
+ return trimmed;
198
+ }
@@ -0,0 +1,17 @@
1
+ import type { JsonObject } from '../../conversion/hub/types/json.js';
2
+ export type CapturedChatSeed = {
3
+ model?: string;
4
+ messages: JsonObject[];
5
+ tools?: JsonObject[];
6
+ parameters?: Record<string, unknown>;
7
+ };
8
+ export declare function extractCapturedChatSeed(source: unknown): CapturedChatSeed | null;
9
+ export declare function normalizeFollowupParameters(value: unknown): Record<string, unknown> | undefined;
10
+ export declare function buildEntryAwareFollowupPayload(args: {
11
+ entryEndpoint: string;
12
+ model?: string;
13
+ messages: JsonObject[];
14
+ tools?: JsonObject[];
15
+ parameters?: Record<string, unknown>;
16
+ }): JsonObject;
17
+ export declare function dropToolByFunctionName(tools: JsonObject[] | undefined, dropName: string): JsonObject[] | undefined;
@@ -0,0 +1,122 @@
1
+ import { buildAnthropicRequestFromOpenAIChat } from '../../conversion/codecs/anthropic-openai-codec.js';
2
+ import { buildChatRequestFromResponses, buildResponsesRequestFromChat, captureResponsesContext } from '../../conversion/responses/responses-openai-bridge.js';
3
+ import { cloneJson } from '../server-side-tools.js';
4
+ function extractResponsesTopLevelParameters(record) {
5
+ const allowed = new Set([
6
+ 'temperature',
7
+ 'top_p',
8
+ 'max_output_tokens',
9
+ 'seed',
10
+ 'logit_bias',
11
+ 'user',
12
+ 'parallel_tool_calls',
13
+ 'tool_choice',
14
+ 'response_format',
15
+ 'stream'
16
+ ]);
17
+ const out = {};
18
+ // Back-compat: StandardizedRequest uses max_tokens; map to Responses max_output_tokens.
19
+ if (record.max_output_tokens === undefined && record.max_tokens !== undefined) {
20
+ out.max_output_tokens = record.max_tokens;
21
+ }
22
+ for (const key of Object.keys(record)) {
23
+ if (!allowed.has(key))
24
+ continue;
25
+ out[key] = record[key];
26
+ }
27
+ return Object.keys(out).length ? out : undefined;
28
+ }
29
+ export function extractCapturedChatSeed(source) {
30
+ if (!source || typeof source !== 'object' || Array.isArray(source)) {
31
+ return null;
32
+ }
33
+ const record = source;
34
+ const model = typeof record.model === 'string' && record.model.trim().length ? record.model.trim() : undefined;
35
+ const rawMessages = Array.isArray(record.messages) ? record.messages : null;
36
+ if (rawMessages) {
37
+ const tools = Array.isArray(record.tools) ? cloneJson(record.tools) : undefined;
38
+ const parameters = normalizeFollowupParameters(record.parameters ?? extractResponsesTopLevelParameters(record));
39
+ return {
40
+ ...(model ? { model } : {}),
41
+ messages: cloneJson(rawMessages),
42
+ ...(tools ? { tools } : {}),
43
+ ...(parameters ? { parameters } : {})
44
+ };
45
+ }
46
+ // Backward/compat: some hosts may have captured the raw /v1/responses payload.
47
+ const rawInput = Array.isArray(record.input) ? record.input : null;
48
+ if (rawInput) {
49
+ try {
50
+ const ctx = captureResponsesContext(record);
51
+ if (!ctx.isResponsesPayload) {
52
+ return null;
53
+ }
54
+ const rebuilt = buildChatRequestFromResponses(record, ctx).request;
55
+ const rebuiltModel = typeof rebuilt.model === 'string' && rebuilt.model.trim().length ? String(rebuilt.model).trim() : model;
56
+ const rebuiltMessages = Array.isArray(rebuilt.messages) ? rebuilt.messages : [];
57
+ const rebuiltTools = Array.isArray(rebuilt.tools) ? rebuilt.tools : undefined;
58
+ const parameters = normalizeFollowupParameters(record.parameters ?? rebuilt.parameters ?? extractResponsesTopLevelParameters(record));
59
+ return {
60
+ ...(rebuiltModel ? { model: rebuiltModel } : {}),
61
+ messages: cloneJson(rebuiltMessages),
62
+ ...(rebuiltTools ? { tools: cloneJson(rebuiltTools) } : {}),
63
+ ...(parameters ? { parameters } : {})
64
+ };
65
+ }
66
+ catch {
67
+ return null;
68
+ }
69
+ }
70
+ return null;
71
+ }
72
+ export function normalizeFollowupParameters(value) {
73
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
74
+ return undefined;
75
+ }
76
+ const cloned = cloneJson(value);
77
+ // Followup requests are always non-streaming (servertool orchestration enforces this),
78
+ // so remove any inherited stream hints to avoid conflicting flags.
79
+ delete cloned.stream;
80
+ return Object.keys(cloned).length ? cloned : undefined;
81
+ }
82
+ export function buildEntryAwareFollowupPayload(args) {
83
+ const chatPayload = {
84
+ ...(args.model ? { model: args.model } : {}),
85
+ messages: args.messages,
86
+ ...(args.tools ? { tools: args.tools } : {})
87
+ };
88
+ const normalizedEntry = typeof args.entryEndpoint === 'string' ? args.entryEndpoint.trim().toLowerCase() : '';
89
+ if (normalizedEntry.includes('/v1/responses')) {
90
+ return buildResponsesRequestFromChat(chatPayload, {
91
+ stream: false,
92
+ ...(args.parameters ? { parameters: args.parameters } : {})
93
+ }).request;
94
+ }
95
+ if (normalizedEntry.includes('/v1/messages')) {
96
+ const anthropicChatPayload = {
97
+ ...chatPayload,
98
+ ...(args.parameters ? args.parameters : {})
99
+ };
100
+ return buildAnthropicRequestFromOpenAIChat(anthropicChatPayload);
101
+ }
102
+ const openaiChatPayload = {
103
+ ...chatPayload,
104
+ ...(args.parameters ? args.parameters : {})
105
+ };
106
+ return openaiChatPayload;
107
+ }
108
+ export function dropToolByFunctionName(tools, dropName) {
109
+ const name = typeof dropName === 'string' ? dropName.trim() : '';
110
+ if (!tools || !tools.length || !name) {
111
+ return tools;
112
+ }
113
+ return tools.filter((tool) => {
114
+ if (!tool || typeof tool !== 'object')
115
+ return false;
116
+ const fn = tool.function;
117
+ const toolName = fn && typeof fn.name === 'string' ? fn.name : '';
118
+ if (!toolName)
119
+ return true;
120
+ return toolName !== name;
121
+ });
122
+ }