@jsonstudio/llms 0.6.3409 → 0.6.3541

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 (85) hide show
  1. package/dist/conversion/codecs/anthropic-openai-codec.d.ts +12 -3
  2. package/dist/conversion/codecs/anthropic-openai-codec.js +32 -92
  3. package/dist/conversion/codecs/gemini-openai-codec.d.ts +6 -5
  4. package/dist/conversion/codecs/gemini-openai-codec.js +48 -685
  5. package/dist/conversion/codecs/openai-openai-codec.d.ts +1 -1
  6. package/dist/conversion/codecs/openai-openai-codec.js +34 -100
  7. package/dist/conversion/codecs/responses-openai-codec.d.ts +1 -1
  8. package/dist/conversion/codecs/responses-openai-codec.js +47 -159
  9. package/dist/conversion/compat/actions/anthropic-claude-code-system-prompt.d.ts +2 -6
  10. package/dist/conversion/compat/actions/anthropic-claude-code-system-prompt.js +29 -245
  11. package/dist/conversion/compat/actions/anthropic-claude-code-user-id.d.ts +3 -0
  12. package/dist/conversion/compat/actions/anthropic-claude-code-user-id.js +30 -0
  13. package/dist/conversion/compat/actions/antigravity-thought-signature-prepare.js +21 -232
  14. package/dist/conversion/compat/actions/deepseek-web-request.js +41 -276
  15. package/dist/conversion/compat/actions/deepseek-web-response.js +117 -855
  16. package/dist/conversion/compat/actions/gemini-cli-request.d.ts +1 -1
  17. package/dist/conversion/compat/actions/gemini-cli-request.js +20 -613
  18. package/dist/conversion/compat/actions/gemini-web-search.d.ts +1 -15
  19. package/dist/conversion/compat/actions/gemini-web-search.js +22 -69
  20. package/dist/conversion/compat/actions/glm-tool-extraction.d.ts +3 -2
  21. package/dist/conversion/compat/actions/glm-tool-extraction.js +28 -257
  22. package/dist/conversion/compat/actions/iflow-tool-text-fallback.d.ts +0 -8
  23. package/dist/conversion/compat/actions/iflow-tool-text-fallback.js +24 -206
  24. package/dist/conversion/compat/actions/qwen-transform.d.ts +3 -2
  25. package/dist/conversion/compat/actions/qwen-transform.js +30 -271
  26. package/dist/conversion/compat/actions/tool-text-request-guidance.js +3 -173
  27. package/dist/conversion/compat/actions/universal-shape-filter.d.ts +6 -23
  28. package/dist/conversion/compat/actions/universal-shape-filter.js +4 -383
  29. package/dist/conversion/hub/pipeline/compat/native-adapter-context.js +1 -0
  30. package/dist/conversion/pipeline/codecs/v2/anthropic-openai-pipeline.d.ts +1 -2
  31. package/dist/conversion/pipeline/codecs/v2/anthropic-openai-pipeline.js +50 -104
  32. package/dist/conversion/pipeline/codecs/v2/openai-openai-pipeline.js +12 -10
  33. package/dist/conversion/pipeline/codecs/v2/responses-openai-pipeline.d.ts +0 -2
  34. package/dist/conversion/pipeline/codecs/v2/responses-openai-pipeline.js +46 -67
  35. package/dist/conversion/pipeline/codecs/v2/shared/openai-chat-helpers.js +15 -40
  36. package/dist/conversion/responses/responses-openai-bridge/response-payload.js +47 -348
  37. package/dist/conversion/responses/responses-openai-bridge.js +129 -611
  38. package/dist/conversion/shared/chat-output-normalizer.js +6 -0
  39. package/dist/conversion/shared/chat-request-filters.js +1 -1
  40. package/dist/conversion/shared/output-content-normalizer.js +10 -0
  41. package/dist/conversion/shared/responses-conversation-store.js +22 -135
  42. package/dist/conversion/shared/responses-output-builder.d.ts +0 -2
  43. package/dist/conversion/shared/responses-output-builder.js +28 -318
  44. package/dist/conversion/shared/responses-response-utils.js +35 -86
  45. package/dist/conversion/shared/streaming-text-extractor.d.ts +1 -2
  46. package/dist/conversion/shared/streaming-text-extractor.js +13 -14
  47. package/dist/native/router_hotpath_napi.node +0 -0
  48. package/dist/quota/quota-state.js +29 -7
  49. package/dist/quota/types.d.ts +1 -0
  50. package/dist/router/virtual-router/bootstrap/routing-config.js +11 -3
  51. package/dist/router/virtual-router/engine-legacy.d.ts +3 -3
  52. package/dist/router/virtual-router/engine-legacy.js +15 -7
  53. package/dist/router/virtual-router/engine-selection/native-compat-action-semantics.d.ts +16 -0
  54. package/dist/router/virtual-router/engine-selection/native-compat-action-semantics.js +434 -46
  55. package/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics.d.ts +83 -0
  56. package/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics.js +295 -0
  57. package/dist/router/virtual-router/engine-selection/native-hub-pipeline-req-outbound-semantics.d.ts +1 -0
  58. package/dist/router/virtual-router/engine-selection/native-hub-pipeline-resp-semantics.d.ts +7 -0
  59. package/dist/router/virtual-router/engine-selection/native-hub-pipeline-resp-semantics.js +8 -1
  60. package/dist/router/virtual-router/engine-selection/native-router-hotpath-loader.js +383 -298
  61. package/dist/router/virtual-router/engine-selection/native-shared-conversion-semantics.d.ts +20 -0
  62. package/dist/router/virtual-router/engine-selection/native-shared-conversion-semantics.js +201 -0
  63. package/dist/router/virtual-router/engine-selection/native-virtual-router-routing-instructions-semantics.d.ts +1 -0
  64. package/dist/router/virtual-router/engine-selection/native-virtual-router-routing-instructions-semantics.js +37 -0
  65. package/dist/router/virtual-router/engine.js +0 -38
  66. package/dist/router/virtual-router/features.js +44 -3
  67. package/dist/router/virtual-router/routing-instructions/parse.d.ts +0 -12
  68. package/dist/router/virtual-router/routing-instructions/parse.js +9 -389
  69. package/dist/router/virtual-router/stop-message-state-sync.d.ts +3 -6
  70. package/dist/router/virtual-router/stop-message-state-sync.js +50 -21
  71. package/dist/servertool/handlers/followup-request-builder.js +12 -2
  72. package/dist/sse/sse-to-json/anthropic-sse-to-json-converter.d.ts +1 -0
  73. package/dist/sse/sse-to-json/anthropic-sse-to-json-converter.js +26 -0
  74. package/dist/sse/sse-to-json/builders/anthropic-response-builder.js +12 -2
  75. package/package.json +1 -1
  76. package/dist/router/virtual-router/engine-legacy/route-finalize.d.ts +0 -9
  77. package/dist/router/virtual-router/engine-legacy/route-finalize.js +0 -84
  78. package/dist/router/virtual-router/engine-legacy/route-selection.d.ts +0 -17
  79. package/dist/router/virtual-router/engine-legacy/route-selection.js +0 -205
  80. package/dist/router/virtual-router/engine-legacy/route-state-allowlist.d.ts +0 -3
  81. package/dist/router/virtual-router/engine-legacy/route-state-allowlist.js +0 -36
  82. package/dist/router/virtual-router/engine-legacy/route-state.d.ts +0 -12
  83. package/dist/router/virtual-router/engine-legacy/route-state.js +0 -386
  84. package/dist/router/virtual-router/engine-legacy/routing.d.ts +0 -8
  85. package/dist/router/virtual-router/engine-legacy/routing.js +0 -8
@@ -1,38 +1,15 @@
1
- import { applyToolTextRequestGuidance } from './tool-text-request-guidance.js';
2
- const DEFAULT_OPTIONS = {
3
- strictToolRequired: true,
4
- toolProtocol: undefined
5
- };
6
- const SEARCH_ROUTE_PREFIXES = ['web_search', 'search'];
7
- const readString = (value) => {
8
- if (typeof value !== 'string') {
9
- return undefined;
10
- }
11
- const trimmed = value.trim();
12
- return trimmed.length ? trimmed : undefined;
13
- };
1
+ import { buildNativeReqOutboundCompatAdapterContext } from '../../hub/pipeline/compat/native-adapter-context.js';
2
+ import { runReqOutboundStage3CompatWithNative } from '../../../router/virtual-router/engine-selection/native-hub-pipeline-req-outbound-semantics.js';
3
+ const PROFILE = 'chat:deepseek-web';
4
+ const DEFAULT_PROVIDER_PROTOCOL = 'openai-chat';
5
+ const DEFAULT_ENTRY_ENDPOINT = '/v1/chat/completions';
14
6
  const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
15
- function readBoolean(input, fallback) {
16
- if (typeof input === 'boolean') {
17
- return input;
18
- }
19
- if (typeof input === 'string') {
20
- const normalized = input.trim().toLowerCase();
21
- if (['true', '1', 'yes', 'on'].includes(normalized)) {
22
- return true;
23
- }
24
- if (['false', '0', 'no', 'off'].includes(normalized)) {
25
- return false;
26
- }
27
- }
28
- return fallback;
29
- }
30
- function readOptionalBoolean(input) {
31
- if (typeof input === 'boolean') {
32
- return input;
7
+ const readBoolean = (value) => {
8
+ if (typeof value === 'boolean') {
9
+ return value;
33
10
  }
34
- if (typeof input === 'string') {
35
- const normalized = input.trim().toLowerCase();
11
+ if (typeof value === 'string') {
12
+ const normalized = value.trim().toLowerCase();
36
13
  if (['true', '1', 'yes', 'on'].includes(normalized)) {
37
14
  return true;
38
15
  }
@@ -41,257 +18,45 @@ function readOptionalBoolean(input) {
41
18
  }
42
19
  }
43
20
  return undefined;
44
- }
45
- function readToolProtocol(input) {
46
- if (typeof input !== 'string') {
21
+ };
22
+ const readToolProtocol = (value) => {
23
+ if (typeof value !== 'string') {
47
24
  return undefined;
48
25
  }
49
- const normalized = input.trim().toLowerCase();
50
- if (normalized === 'text' || normalized === 'native') {
51
- return normalized;
52
- }
53
- return undefined;
54
- }
55
- function resolveOptions(adapterContext) {
56
- const context = (adapterContext ?? {});
57
- const deepseekNode = isRecord(context.deepseek)
58
- ? context.deepseek
59
- : isRecord(context.__rt) && isRecord(context.__rt.deepseek)
60
- ? context.__rt.deepseek
61
- : undefined;
62
- if (!deepseekNode) {
63
- return { ...DEFAULT_OPTIONS };
64
- }
65
- const legacyFallback = readOptionalBoolean(deepseekNode.textToolFallback);
66
- const toolProtocol = readToolProtocol(deepseekNode.toolProtocol) ??
67
- (legacyFallback !== undefined ? (legacyFallback ? 'text' : 'native') : undefined);
26
+ const normalized = value.trim().toLowerCase();
27
+ return normalized === 'native' || normalized === 'text' ? normalized : undefined;
28
+ };
29
+ function resolveDeepseekNode(adapterContext) {
30
+ const nativeContext = buildNativeReqOutboundCompatAdapterContext(adapterContext);
31
+ const baseNode = isRecord(nativeContext.deepseek) ? nativeContext.deepseek : {};
32
+ const baseProtocol = readToolProtocol(baseNode.toolProtocol);
33
+ const baseFallback = readBoolean(baseNode.textToolFallback);
34
+ const protocol = baseProtocol ?? (baseFallback === undefined ? undefined : baseFallback ? 'text' : 'native');
68
35
  return {
69
- strictToolRequired: readBoolean(deepseekNode.strictToolRequired, DEFAULT_OPTIONS.strictToolRequired),
70
- toolProtocol
36
+ ...baseNode,
37
+ strictToolRequired: readBoolean(baseNode.strictToolRequired) ?? true,
38
+ textToolFallback: protocol ? protocol === 'text' : baseFallback ?? true,
39
+ ...(protocol ? { toolProtocol: protocol } : {})
71
40
  };
72
41
  }
73
- function normalizeContentToText(content) {
74
- if (typeof content === 'string') {
75
- return content;
76
- }
77
- if (content === null || content === undefined) {
78
- return '';
79
- }
80
- if (Array.isArray(content)) {
81
- const parts = [];
82
- for (const item of content) {
83
- if (!isRecord(item)) {
84
- continue;
85
- }
86
- const type = readString(item.type)?.toLowerCase();
87
- if ((type === 'text' || type === 'input_text' || type === 'output_text') && readString(item.text)) {
88
- parts.push(readString(item.text));
89
- continue;
90
- }
91
- if (readString(item.content)) {
92
- parts.push(readString(item.content));
93
- continue;
94
- }
95
- if (type === 'tool_result' && item.content !== undefined) {
96
- parts.push(stringifyUnknown(item.content));
97
- }
98
- }
99
- return parts.join('\n').trim();
100
- }
101
- return stringifyUnknown(content);
102
- }
103
- function stringifyUnknown(value) {
104
- if (typeof value === 'string') {
105
- return value;
106
- }
107
- if (value === null || value === undefined) {
108
- return '';
109
- }
110
- try {
111
- return JSON.stringify(value);
112
- }
113
- catch {
114
- return String(value);
115
- }
116
- }
117
- function normalizeToolCallsAsText(toolCallsRaw) {
118
- if (!Array.isArray(toolCallsRaw) || toolCallsRaw.length === 0) {
119
- return '';
120
- }
121
- const toolCalls = toolCallsRaw
122
- .filter((item) => isRecord(item))
123
- .map((item) => {
124
- const fn = isRecord(item.function) ? item.function : undefined;
125
- const name = readString(fn?.name);
126
- if (!name) {
127
- return null;
128
- }
129
- const argsRaw = fn?.arguments;
130
- let input = {};
131
- if (typeof argsRaw === 'string') {
132
- const trimmed = argsRaw.trim();
133
- if (trimmed.length) {
134
- try {
135
- input = JSON.parse(trimmed);
136
- }
137
- catch {
138
- input = { _raw: trimmed };
139
- }
140
- }
141
- }
142
- else if (argsRaw !== undefined) {
143
- input = argsRaw;
144
- }
145
- return { name, input };
146
- })
147
- .filter((item) => Boolean(item));
148
- if (!toolCalls.length) {
149
- return '';
150
- }
151
- try {
152
- return JSON.stringify({ tool_calls: toolCalls });
153
- }
154
- catch {
155
- return '';
156
- }
157
- }
158
- function toPromptMessages(root, options) {
159
- const messagesRaw = Array.isArray(root.messages) ? root.messages : [];
160
- const messages = [];
161
- for (const item of messagesRaw) {
162
- if (!isRecord(item)) {
163
- continue;
164
- }
165
- const role = readString(item.role)?.toLowerCase() ?? '';
166
- if (!role) {
167
- continue;
168
- }
169
- const contentText = normalizeContentToText(item.content);
170
- const toolCallsText = normalizeToolCallsAsText(item.tool_calls);
171
- const reasoning = readString(item.reasoning_content) ?? readString(item.reasoning) ?? '';
172
- const parts = [contentText];
173
- if (toolCallsText) {
174
- parts.push(toolCallsText);
175
- }
176
- if (reasoning) {
177
- parts.push(reasoning);
178
- }
179
- const text = parts.filter(Boolean).join('\n').trim();
180
- messages.push({ role, text });
181
- }
182
- return messages;
183
- }
184
- function mergeByRole(messages) {
185
- if (!messages.length) {
186
- return [];
187
- }
188
- const merged = [{ ...messages[0] }];
189
- for (const item of messages.slice(1)) {
190
- const last = merged[merged.length - 1];
191
- if (last.role === item.role) {
192
- last.text = [last.text, item.text].filter(Boolean).join('\n\n');
193
- }
194
- else {
195
- merged.push({ ...item });
196
- }
197
- }
198
- return merged;
199
- }
200
- function buildPromptFromMessages(messages) {
201
- const merged = mergeByRole(messages);
202
- const parts = [];
203
- merged.forEach((block, index) => {
204
- const role = block.role;
205
- const text = block.text ?? '';
206
- if (role === 'assistant') {
207
- parts.push(`<|Assistant|>${text}<|end▁of▁sentence|>`);
208
- return;
209
- }
210
- if (role === 'user' || role === 'system' || role === 'tool') {
211
- if (index > 0) {
212
- parts.push(`<|User|>${text}`);
213
- }
214
- else {
215
- parts.push(text);
216
- }
217
- return;
218
- }
219
- parts.push(text);
220
- });
221
- return parts
222
- .join('')
223
- .replace(/!\[(.*?)\]\((.*?)\)/g, '[$1]($2)')
224
- .trim();
225
- }
226
- function resolveModel(payload, adapterContext) {
227
- const direct = readString(payload.model);
228
- if (direct) {
229
- return direct;
230
- }
231
- const context = (adapterContext ?? {});
232
- return readString(context.modelId) ?? readString(context.originalModelId) ?? '';
233
- }
234
- function resolveThinkingSearchFlags(modelRaw) {
235
- const model = modelRaw.trim().toLowerCase();
236
- if (model === 'deepseek-v3' || model === 'deepseek-chat') {
237
- return { thinking: false, search: false };
238
- }
239
- if (model === 'deepseek-r1' || model === 'deepseek-reasoner') {
240
- return { thinking: true, search: false };
241
- }
242
- if (model === 'deepseek-v3-search' || model === 'deepseek-chat-search') {
243
- return { thinking: false, search: true };
244
- }
245
- if (model === 'deepseek-r1-search' || model === 'deepseek-reasoner-search') {
246
- return { thinking: true, search: true };
247
- }
248
- return { thinking: false, search: false };
249
- }
250
- function shouldForceSearch(root, adapterContext) {
251
- const routeId = readString(adapterContext?.routeId)?.toLowerCase() ?? '';
252
- if (SEARCH_ROUTE_PREFIXES.some((prefix) => routeId.startsWith(prefix))) {
253
- return true;
254
- }
255
- if (isRecord(root.web_search)) {
256
- return true;
257
- }
258
- const context = (adapterContext ?? {});
259
- if (isRecord(context.__rt) && context.__rt.forceWebSearch === true) {
260
- return true;
261
- }
262
- return false;
42
+ function buildCompatInput(payload, adapterContext) {
43
+ const nativeContext = buildNativeReqOutboundCompatAdapterContext(adapterContext);
44
+ const normalizedContext = {
45
+ ...nativeContext,
46
+ compatibilityProfile: PROFILE,
47
+ providerProtocol: nativeContext.providerProtocol ?? adapterContext?.providerProtocol ?? DEFAULT_PROVIDER_PROTOCOL,
48
+ entryEndpoint: nativeContext.entryEndpoint ?? adapterContext?.entryEndpoint ?? DEFAULT_ENTRY_ENDPOINT,
49
+ deepseek: resolveDeepseekNode(adapterContext)
50
+ };
51
+ return {
52
+ payload,
53
+ adapterContext: normalizedContext,
54
+ explicitProfile: PROFILE
55
+ };
263
56
  }
264
57
  export function applyDeepSeekWebRequestTransform(payload, adapterContext) {
265
58
  if (!payload || typeof payload !== 'object') {
266
59
  return payload;
267
60
  }
268
- const root = structuredClone(payload);
269
- const options = resolveOptions(adapterContext);
270
- const guidedRoot = options.toolProtocol === 'text'
271
- ? applyToolTextRequestGuidance(root, { enabled: true })
272
- : root;
273
- const model = resolveModel(guidedRoot, adapterContext);
274
- const flags = resolveThinkingSearchFlags(model);
275
- const forceSearch = shouldForceSearch(guidedRoot, adapterContext);
276
- const prompt = buildPromptFromMessages(toPromptMessages(guidedRoot, options));
277
- const next = {
278
- ...(readString(guidedRoot.chat_session_id) ? { chat_session_id: readString(guidedRoot.chat_session_id) } : {}),
279
- parent_message_id: readString(guidedRoot.parent_message_id) ?? null,
280
- prompt,
281
- ref_file_ids: Array.isArray(guidedRoot.ref_file_ids) ? guidedRoot.ref_file_ids : [],
282
- thinking_enabled: flags.thinking,
283
- search_enabled: forceSearch ? true : flags.search
284
- };
285
- if (guidedRoot.stream === true) {
286
- next.stream = true;
287
- }
288
- // Preserve a tiny runtime hint surface for response-side strict/fallback checks.
289
- next.metadata = {
290
- ...(isRecord(guidedRoot.metadata) ? guidedRoot.metadata : {}),
291
- deepseek: {
292
- strictToolRequired: options.strictToolRequired,
293
- ...(options.toolProtocol ? { toolProtocol: options.toolProtocol } : {})
294
- }
295
- };
296
- return next;
61
+ return runReqOutboundStage3CompatWithNative(buildCompatInput(payload, adapterContext)).payload;
297
62
  }