@jsonstudio/llms 0.6.1739 → 0.6.1890

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 (107) hide show
  1. package/dist/conversion/compat/actions/deepseek-web-request.d.ts +3 -0
  2. package/dist/conversion/compat/actions/deepseek-web-request.js +350 -0
  3. package/dist/conversion/compat/actions/deepseek-web-response.d.ts +3 -0
  4. package/dist/conversion/compat/actions/deepseek-web-response.js +886 -0
  5. package/dist/conversion/compat/actions/gemini-cli-request.js +3 -1
  6. package/dist/conversion/compat/profiles/chat-deepseek-web.json +18 -0
  7. package/dist/conversion/hub/operation-table/semantic-mappers/anthropic-mapper.js +166 -2
  8. package/dist/conversion/hub/operation-table/semantic-mappers/gemini-mapper.js +169 -0
  9. package/dist/conversion/hub/operation-table/semantic-mappers/responses-mapper.js +6 -0
  10. package/dist/conversion/hub/pipeline/compat/compat-pipeline-executor.js +12 -0
  11. package/dist/conversion/hub/pipeline/compat/compat-profile-resolver.js +1 -0
  12. package/dist/conversion/hub/pipeline/compat/compat-types.d.ts +4 -0
  13. package/dist/conversion/hub/pipeline/hub-pipeline.js +365 -144
  14. package/dist/conversion/hub/pipeline/stages/resp_outbound/resp_outbound_stage1_client_remap/index.js +9 -0
  15. package/dist/conversion/hub/policy/policy-engine.d.ts +2 -0
  16. package/dist/conversion/hub/policy/policy-engine.js +8 -0
  17. package/dist/conversion/hub/process/chat-process.js +466 -16
  18. package/dist/conversion/hub/response/provider-response.js +0 -35
  19. package/dist/conversion/responses/responses-openai-bridge.d.ts +2 -0
  20. package/dist/conversion/responses/responses-openai-bridge.js +166 -8
  21. package/dist/conversion/shared/anthropic-message-utils.js +10 -1
  22. package/dist/conversion/shared/protocol-field-allowlists.d.ts +2 -2
  23. package/dist/conversion/shared/protocol-field-allowlists.js +4 -0
  24. package/dist/conversion/shared/tool-governor.js +102 -0
  25. package/dist/guidance/index.js +17 -0
  26. package/dist/router/virtual-router/bootstrap.js +46 -1
  27. package/dist/router/virtual-router/classifier.js +59 -4
  28. package/dist/router/virtual-router/engine/health/index.js +6 -6
  29. package/dist/router/virtual-router/engine/routing-state/store.js +16 -3
  30. package/dist/router/virtual-router/engine-logging.js +62 -24
  31. package/dist/router/virtual-router/engine-selection/route-utils.js +20 -20
  32. package/dist/router/virtual-router/engine-selection/tier-selection.js +2 -2
  33. package/dist/router/virtual-router/engine.d.ts +3 -1
  34. package/dist/router/virtual-router/engine.js +359 -39
  35. package/dist/router/virtual-router/features.js +2 -1
  36. package/dist/router/virtual-router/pre-command-file-resolver.d.ts +2 -0
  37. package/dist/router/virtual-router/pre-command-file-resolver.js +90 -0
  38. package/dist/router/virtual-router/provider-registry.js +3 -1
  39. package/dist/router/virtual-router/routing-instructions.d.ts +15 -1
  40. package/dist/router/virtual-router/routing-instructions.js +110 -151
  41. package/dist/router/virtual-router/routing-pre-command-actions.d.ts +3 -0
  42. package/dist/router/virtual-router/routing-pre-command-actions.js +26 -0
  43. package/dist/router/virtual-router/routing-pre-command-parser.d.ts +2 -0
  44. package/dist/router/virtual-router/routing-pre-command-parser.js +85 -0
  45. package/dist/router/virtual-router/routing-pre-command-state-codec.d.ts +3 -0
  46. package/dist/router/virtual-router/routing-pre-command-state-codec.js +24 -0
  47. package/dist/router/virtual-router/routing-stop-message-actions.d.ts +2 -0
  48. package/dist/router/virtual-router/routing-stop-message-actions.js +96 -0
  49. package/dist/router/virtual-router/routing-stop-message-parser.d.ts +3 -0
  50. package/dist/router/virtual-router/routing-stop-message-parser.js +142 -0
  51. package/dist/router/virtual-router/routing-stop-message-state-codec.d.ts +4 -0
  52. package/dist/router/virtual-router/routing-stop-message-state-codec.js +85 -0
  53. package/dist/router/virtual-router/sticky-session-store.js +206 -57
  54. package/dist/router/virtual-router/stop-message-stage-template-files.d.ts +12 -0
  55. package/dist/router/virtual-router/stop-message-stage-template-files.js +67 -0
  56. package/dist/router/virtual-router/stop-message-state-sync.d.ts +1 -1
  57. package/dist/router/virtual-router/stop-message-state-sync.js +5 -0
  58. package/dist/router/virtual-router/token-file-scanner.d.ts +9 -0
  59. package/dist/router/virtual-router/token-file-scanner.js +64 -3
  60. package/dist/router/virtual-router/tool-signals.d.ts +5 -0
  61. package/dist/router/virtual-router/tool-signals.js +42 -3
  62. package/dist/router/virtual-router/types.d.ts +19 -1
  63. package/dist/router/virtual-router/types.js +1 -0
  64. package/dist/servertool/clock/config.d.ts +1 -1
  65. package/dist/servertool/clock/config.js +27 -4
  66. package/dist/servertool/clock/state.js +41 -2
  67. package/dist/servertool/clock/task-store.d.ts +2 -2
  68. package/dist/servertool/clock/task-store.js +1 -1
  69. package/dist/servertool/clock/tasks.d.ts +3 -1
  70. package/dist/servertool/clock/tasks.js +209 -18
  71. package/dist/servertool/clock/types.d.ts +17 -0
  72. package/dist/servertool/continue-execution/log.d.ts +3 -0
  73. package/dist/servertool/continue-execution/log.js +13 -0
  74. package/dist/servertool/engine.js +414 -68
  75. package/dist/servertool/handlers/antigravity-thought-signature-bootstrap.js +6 -6
  76. package/dist/servertool/handlers/clock-auto.js +54 -71
  77. package/dist/servertool/handlers/clock.js +121 -6
  78. package/dist/servertool/handlers/continue-execution.d.ts +1 -0
  79. package/dist/servertool/handlers/continue-execution.js +91 -0
  80. package/dist/servertool/handlers/followup-request-builder.js +13 -0
  81. package/dist/servertool/handlers/gemini-empty-reply-continue.js +1 -1
  82. package/dist/servertool/handlers/iflow-model-error-retry.js +1 -1
  83. package/dist/servertool/handlers/recursive-detection-guard.js +1 -1
  84. package/dist/servertool/handlers/stop-message-auto.js +386 -257
  85. package/dist/servertool/handlers/stop-message-stage-policy.d.ts +43 -0
  86. package/dist/servertool/handlers/stop-message-stage-policy.js +684 -0
  87. package/dist/servertool/handlers/vision.js +1 -1
  88. package/dist/servertool/log/progress-file.d.ts +14 -0
  89. package/dist/servertool/log/progress-file.js +88 -0
  90. package/dist/servertool/pre-command-hooks.d.ts +17 -0
  91. package/dist/servertool/pre-command-hooks.js +491 -0
  92. package/dist/servertool/registry.d.ts +23 -6
  93. package/dist/servertool/registry.js +66 -1
  94. package/dist/servertool/server-side-tools.d.ts +1 -0
  95. package/dist/servertool/server-side-tools.js +216 -14
  96. package/dist/servertool/stop-gateway-context.d.ts +14 -0
  97. package/dist/servertool/stop-gateway-context.js +167 -0
  98. package/dist/servertool/stop-message-compare-context.d.ts +24 -0
  99. package/dist/servertool/stop-message-compare-context.js +133 -0
  100. package/dist/servertool/types.d.ts +12 -0
  101. package/dist/sse/sse-to-json/anthropic-sse-to-json-converter.d.ts +1 -0
  102. package/dist/sse/sse-to-json/anthropic-sse-to-json-converter.js +36 -1
  103. package/dist/sse/sse-to-json/builders/anthropic-response-builder.js +3 -0
  104. package/dist/sse/sse-to-json/chat-sse-to-json-converter.d.ts +3 -0
  105. package/dist/sse/sse-to-json/chat-sse-to-json-converter.js +118 -1
  106. package/dist/tools/apply-patch/args-normalizer/default-actions.js +1 -1
  107. package/package.json +1 -1
@@ -520,7 +520,9 @@ function shouldEnableAntigravitySignature(adapterContext) {
520
520
  // Treat the first segment as the effective provider id for compatibility checks.
521
521
  const providerIdOrKey = providerIdOrKeyRaw.trim().toLowerCase();
522
522
  const effectiveProviderId = providerIdOrKey.split('.')[0] ?? '';
523
- return effectiveProviderId === 'antigravity';
523
+ // Antigravity-Manager alignment: thoughtSignature compat applies to both Antigravity and Gemini CLI
524
+ // (both route to Google Gemini internals that enforce thoughtSignature on tool loops).
525
+ return effectiveProviderId === 'antigravity' || effectiveProviderId === 'gemini-cli';
524
526
  }
525
527
  function injectAntigravityThoughtSignature(requestNode, signature) {
526
528
  if (!signature || !signature.trim())
@@ -0,0 +1,18 @@
1
+ {
2
+ "id": "chat:deepseek-web",
3
+ "protocol": "openai-chat",
4
+ "request": {
5
+ "mappings": [
6
+ { "action": "snapshot", "phase": "compat-pre" },
7
+ { "action": "deepseek_web_request" },
8
+ { "action": "snapshot", "phase": "compat-post" }
9
+ ]
10
+ },
11
+ "response": {
12
+ "mappings": [
13
+ { "action": "snapshot", "phase": "compat-pre" },
14
+ { "action": "deepseek_web_response" },
15
+ { "action": "snapshot", "phase": "compat-post" }
16
+ ]
17
+ }
18
+ }
@@ -12,7 +12,8 @@ const ANTHROPIC_PARAMETER_KEYS = [
12
12
  'max_output_tokens',
13
13
  'metadata',
14
14
  'stream',
15
- 'tool_choice'
15
+ 'tool_choice',
16
+ 'thinking'
16
17
  ];
17
18
  const ANTHROPIC_TOP_LEVEL_FIELDS = new Set([
18
19
  'model',
@@ -27,10 +28,20 @@ const ANTHROPIC_TOP_LEVEL_FIELDS = new Set([
27
28
  'max_output_tokens',
28
29
  'metadata',
29
30
  'stream',
30
- 'tool_choice'
31
+ 'tool_choice',
32
+ 'thinking'
31
33
  ]);
32
34
  const PASSTHROUGH_METADATA_PREFIX = 'rcc_passthrough_';
33
35
  const PASSTHROUGH_PARAMETERS = ['tool_choice'];
36
+ const RESPONSES_DROPPED_PARAMETER_KEYS = [
37
+ 'prompt_cache_key',
38
+ 'response_format',
39
+ 'parallel_tool_calls',
40
+ 'service_tier',
41
+ 'truncation',
42
+ 'include',
43
+ 'store'
44
+ ];
34
45
  function ensureSemantics(chat) {
35
46
  if (!chat.semantics || typeof chat.semantics !== 'object') {
36
47
  chat.semantics = {};
@@ -88,6 +99,86 @@ function collectParameters(payload) {
88
99
  }
89
100
  return Object.keys(params).length ? params : undefined;
90
101
  }
102
+ function mapReasoningEffortToAnthropicBudget(effort) {
103
+ const normalized = effort.trim().toLowerCase();
104
+ if (normalized === 'minimal' || normalized === 'low')
105
+ return 1024;
106
+ if (normalized === 'medium')
107
+ return 4096;
108
+ if (normalized === 'high')
109
+ return 8192;
110
+ return 4096;
111
+ }
112
+ function buildAnthropicThinkingFromReasoning(reasoning) {
113
+ if (reasoning === undefined || reasoning === null) {
114
+ return undefined;
115
+ }
116
+ if (typeof reasoning === 'boolean') {
117
+ if (!reasoning) {
118
+ return { type: 'disabled' };
119
+ }
120
+ return { type: 'enabled', budget_tokens: 4096 };
121
+ }
122
+ if (typeof reasoning === 'string') {
123
+ const normalized = reasoning.trim().toLowerCase();
124
+ if (!normalized.length) {
125
+ return undefined;
126
+ }
127
+ if (normalized === 'off' || normalized === 'none' || normalized === 'disabled' || normalized === 'false') {
128
+ return { type: 'disabled' };
129
+ }
130
+ return {
131
+ type: 'enabled',
132
+ budget_tokens: mapReasoningEffortToAnthropicBudget(normalized)
133
+ };
134
+ }
135
+ if (typeof reasoning === 'number' && Number.isFinite(reasoning)) {
136
+ const budget = Math.max(0, Math.floor(reasoning));
137
+ return budget <= 0
138
+ ? { type: 'disabled' }
139
+ : { type: 'enabled', budget_tokens: budget };
140
+ }
141
+ if (!isJsonObject(reasoning)) {
142
+ return undefined;
143
+ }
144
+ const node = reasoning;
145
+ const enabledRaw = node.enabled;
146
+ if (enabledRaw === false) {
147
+ return { type: 'disabled' };
148
+ }
149
+ const effortRaw = typeof node.effort === 'string'
150
+ ? node.effort
151
+ : typeof node.level === 'string'
152
+ ? node.level
153
+ : undefined;
154
+ const budgetRaw = typeof node.budget_tokens === 'number'
155
+ ? node.budget_tokens
156
+ : typeof node.budget === 'number'
157
+ ? node.budget
158
+ : typeof node.max_tokens === 'number'
159
+ ? node.max_tokens
160
+ : undefined;
161
+ if (typeof budgetRaw === 'number' && Number.isFinite(budgetRaw)) {
162
+ const budget = Math.max(0, Math.floor(budgetRaw));
163
+ return budget <= 0
164
+ ? { type: 'disabled' }
165
+ : { type: 'enabled', budget_tokens: budget };
166
+ }
167
+ if (typeof effortRaw === 'string' && effortRaw.trim().length) {
168
+ const normalized = effortRaw.trim().toLowerCase();
169
+ if (normalized === 'off' || normalized === 'none' || normalized === 'disabled') {
170
+ return { type: 'disabled' };
171
+ }
172
+ return {
173
+ type: 'enabled',
174
+ budget_tokens: mapReasoningEffortToAnthropicBudget(normalized)
175
+ };
176
+ }
177
+ if (enabledRaw === true) {
178
+ return { type: 'enabled', budget_tokens: 4096 };
179
+ }
180
+ return { type: 'enabled', budget_tokens: 4096 };
181
+ }
91
182
  function cloneAnthropicSystemBlocks(value) {
92
183
  if (value === undefined || value === null) {
93
184
  return undefined;
@@ -98,6 +189,55 @@ function cloneAnthropicSystemBlocks(value) {
98
189
  }
99
190
  return blocks.map((entry) => jsonClone(entry));
100
191
  }
192
+ function isResponsesOrigin(chat) {
193
+ const semantics = chat?.semantics;
194
+ if (semantics && semantics.responses && isJsonObject(semantics.responses)) {
195
+ return true;
196
+ }
197
+ const ctx = chat?.metadata && typeof chat.metadata === 'object'
198
+ ? chat.metadata.context
199
+ : undefined;
200
+ const protocol = typeof ctx?.providerProtocol === 'string' ? ctx.providerProtocol.trim().toLowerCase() : '';
201
+ if (protocol === 'openai-responses') {
202
+ return true;
203
+ }
204
+ const endpoint = typeof ctx?.entryEndpoint === 'string' ? ctx.entryEndpoint.trim().toLowerCase() : '';
205
+ return endpoint === '/v1/responses';
206
+ }
207
+ function appendMappingAudit(chat, options) {
208
+ const metadata = chat.metadata && typeof chat.metadata === 'object'
209
+ ? chat.metadata
210
+ : (chat.metadata = { context: chat.metadata?.context ?? {} });
211
+ const root = metadata.mappingAudit && typeof metadata.mappingAudit === 'object' && !Array.isArray(metadata.mappingAudit)
212
+ ? metadata.mappingAudit
213
+ : (metadata.mappingAudit = {});
214
+ const current = Array.isArray(root[options.bucket]) ? root[options.bucket] : [];
215
+ const duplicate = current.find((entry) => entry &&
216
+ entry.field === options.field &&
217
+ entry.targetProtocol === options.targetProtocol &&
218
+ entry.reason === options.reason);
219
+ if (!duplicate) {
220
+ current.push({
221
+ field: options.field,
222
+ source: options.source ?? 'chat.parameters',
223
+ targetProtocol: options.targetProtocol,
224
+ reason: options.reason
225
+ });
226
+ }
227
+ root[options.bucket] = current;
228
+ }
229
+ function appendDroppedFieldAudit(chat, options) {
230
+ appendMappingAudit(chat, {
231
+ bucket: 'dropped',
232
+ ...options
233
+ });
234
+ }
235
+ function appendLossyFieldAudit(chat, options) {
236
+ appendMappingAudit(chat, {
237
+ bucket: 'lossy',
238
+ ...options
239
+ });
240
+ }
101
241
  export class AnthropicSemanticMapper {
102
242
  chatMapper = new ChatSemanticMapper();
103
243
  async toChat(format, ctx) {
@@ -215,6 +355,19 @@ export class AnthropicSemanticMapper {
215
355
  };
216
356
  const explicitEmptyTools = hasExplicitEmptyToolsSemantics(chat);
217
357
  const trimmedParameters = chat.parameters && typeof chat.parameters === 'object' ? chat.parameters : undefined;
358
+ const responsesOrigin = isResponsesOrigin(chat);
359
+ if (trimmedParameters && responsesOrigin) {
360
+ for (const field of RESPONSES_DROPPED_PARAMETER_KEYS) {
361
+ if (!Object.prototype.hasOwnProperty.call(trimmedParameters, field)) {
362
+ continue;
363
+ }
364
+ appendDroppedFieldAudit(chat, {
365
+ field,
366
+ targetProtocol: 'anthropic-messages',
367
+ reason: 'unsupported_semantics_no_equivalent'
368
+ });
369
+ }
370
+ }
218
371
  if (trimmedParameters) {
219
372
  for (const [key, value] of Object.entries(trimmedParameters)) {
220
373
  if (ANTHROPIC_TOP_LEVEL_FIELDS.has(key) || key === 'stop') {
@@ -242,6 +395,17 @@ export class AnthropicSemanticMapper {
242
395
  if (baseRequest.max_output_tokens && !baseRequest.max_tokens) {
243
396
  baseRequest.max_tokens = baseRequest.max_output_tokens;
244
397
  }
398
+ const mappedThinking = buildAnthropicThinkingFromReasoning(trimmedParameters?.reasoning);
399
+ if (mappedThinking && baseRequest.thinking === undefined) {
400
+ baseRequest.thinking = mappedThinking;
401
+ }
402
+ if (responsesOrigin && trimmedParameters && Object.prototype.hasOwnProperty.call(trimmedParameters, 'reasoning')) {
403
+ appendLossyFieldAudit(chat, {
404
+ field: 'reasoning',
405
+ targetProtocol: 'anthropic-messages',
406
+ reason: 'normalized_to_anthropic_thinking_budget'
407
+ });
408
+ }
245
409
  // 出站阶段不再直接透传其它协议的 providerMetadata,避免跨协议打洞;
246
410
  // Anthropic 自身入口的 metadata 已在入站阶段通过 collectParameters/encodeMetadataPassthrough
247
411
  // 按白名单收集,这里仅依赖这些显式映射结果。
@@ -18,6 +18,15 @@ const GENERATION_CONFIG_KEYS = [
18
18
  ];
19
19
  const PASSTHROUGH_METADATA_PREFIX = 'rcc_passthrough_';
20
20
  const PASSTHROUGH_PARAMETERS = ['tool_choice'];
21
+ const RESPONSES_DROPPED_PARAMETER_KEYS = [
22
+ 'prompt_cache_key',
23
+ 'response_format',
24
+ 'parallel_tool_calls',
25
+ 'service_tier',
26
+ 'truncation',
27
+ 'include',
28
+ 'store'
29
+ ];
21
30
  // Ported from CLIProxyAPI v6.6.89 (antigravity auth constants)
22
31
  const ANTIGRAVITY_SYSTEM_INSTRUCTION = `You are Antigravity, a powerful agentic AI coding assistant designed by the Google DeepMind team working on Advanced Agentic Coding.
23
32
  You are pair programming with a USER to solve their coding task. The task may require creating a new codebase, modifying or debugging an existing codebase, or simply answering a question.
@@ -662,6 +671,19 @@ function buildGeminiRequestFromChat(chat, metadata) {
662
671
  const isGeminiCliProvider = providerIdPrefix === 'gemini-cli';
663
672
  const requiresThoughtSignature = isAntigravityProvider || isGeminiCliProvider;
664
673
  const parameters = chat.parameters && typeof chat.parameters === 'object' ? chat.parameters : {};
674
+ const responsesOrigin = isResponsesOrigin(chat);
675
+ if (responsesOrigin) {
676
+ for (const field of RESPONSES_DROPPED_PARAMETER_KEYS) {
677
+ if (!Object.prototype.hasOwnProperty.call(parameters, field)) {
678
+ continue;
679
+ }
680
+ appendDroppedFieldAudit(chat, {
681
+ field,
682
+ targetProtocol: 'gemini-chat',
683
+ reason: 'unsupported_semantics_no_equivalent'
684
+ });
685
+ }
686
+ }
665
687
  const isAntigravityClaudeThinking = providerIdPrefix === 'antigravity' &&
666
688
  typeof parameters.model === 'string' &&
667
689
  String(parameters.model).includes('claude-sonnet-4-5-thinking');
@@ -901,6 +923,13 @@ function buildGeminiRequestFromChat(chat, metadata) {
901
923
  }
902
924
  }
903
925
  const generationConfig = buildGenerationConfigFromParameters(chat.parameters || {});
926
+ if (responsesOrigin && Object.prototype.hasOwnProperty.call(parameters, 'reasoning')) {
927
+ appendLossyFieldAudit(chat, {
928
+ field: 'reasoning',
929
+ targetProtocol: 'gemini-chat',
930
+ reason: 'normalized_to_gemini_thinking_config'
931
+ });
932
+ }
904
933
  if (semanticsNode?.generationConfig && isJsonObject(semanticsNode.generationConfig)) {
905
934
  for (const [key, value] of Object.entries(semanticsNode.generationConfig)) {
906
935
  if (generationConfig[key] !== undefined) {
@@ -1210,6 +1239,97 @@ function buildGenerationConfigFromParameters(parameters) {
1210
1239
  config[source] = value;
1211
1240
  }
1212
1241
  }
1242
+ const reasoningRaw = parameters.reasoning;
1243
+ const applyThinkingDisabled = () => {
1244
+ config.thinkingConfig = {
1245
+ includeThoughts: false,
1246
+ thinkingBudget: 0
1247
+ };
1248
+ };
1249
+ const applyThinkingEnabled = (budget) => {
1250
+ const next = {
1251
+ includeThoughts: true
1252
+ };
1253
+ if (typeof budget === 'number' && Number.isFinite(budget) && budget > 0) {
1254
+ next.thinkingBudget = Math.floor(budget);
1255
+ }
1256
+ config.thinkingConfig = next;
1257
+ };
1258
+ if (typeof reasoningRaw === 'boolean') {
1259
+ if (reasoningRaw) {
1260
+ applyThinkingEnabled();
1261
+ }
1262
+ else {
1263
+ applyThinkingDisabled();
1264
+ }
1265
+ }
1266
+ else if (typeof reasoningRaw === 'string') {
1267
+ const normalized = reasoningRaw.trim().toLowerCase();
1268
+ if (normalized === 'off' || normalized === 'none' || normalized === 'disabled' || normalized === 'false') {
1269
+ applyThinkingDisabled();
1270
+ }
1271
+ else if (normalized.length) {
1272
+ const effortBudget = {
1273
+ minimal: 1024,
1274
+ low: 1024,
1275
+ medium: 4096,
1276
+ high: 8192
1277
+ };
1278
+ applyThinkingEnabled(effortBudget[normalized]);
1279
+ }
1280
+ }
1281
+ else if (typeof reasoningRaw === 'number' && Number.isFinite(reasoningRaw)) {
1282
+ if (reasoningRaw <= 0) {
1283
+ applyThinkingDisabled();
1284
+ }
1285
+ else {
1286
+ applyThinkingEnabled(reasoningRaw);
1287
+ }
1288
+ }
1289
+ else if (isJsonObject(reasoningRaw)) {
1290
+ const node = reasoningRaw;
1291
+ const enabled = node.enabled;
1292
+ if (enabled === false) {
1293
+ applyThinkingDisabled();
1294
+ }
1295
+ else {
1296
+ const effort = typeof node.effort === 'string'
1297
+ ? node.effort.trim().toLowerCase()
1298
+ : typeof node.level === 'string'
1299
+ ? node.level.trim().toLowerCase()
1300
+ : '';
1301
+ const budget = typeof node.budget_tokens === 'number'
1302
+ ? node.budget_tokens
1303
+ : typeof node.budget === 'number'
1304
+ ? node.budget
1305
+ : typeof node.max_tokens === 'number'
1306
+ ? node.max_tokens
1307
+ : undefined;
1308
+ if (typeof budget === 'number' && Number.isFinite(budget)) {
1309
+ if (budget <= 0) {
1310
+ applyThinkingDisabled();
1311
+ }
1312
+ else {
1313
+ applyThinkingEnabled(budget);
1314
+ }
1315
+ }
1316
+ else if (effort === 'off' || effort === 'none' || effort === 'disabled') {
1317
+ applyThinkingDisabled();
1318
+ }
1319
+ else if (effort.length) {
1320
+ const effortBudget = {
1321
+ minimal: 1024,
1322
+ low: 1024,
1323
+ medium: 4096,
1324
+ high: 8192
1325
+ };
1326
+ applyThinkingEnabled(effortBudget[effort]);
1327
+ }
1328
+ else if (enabled === true) {
1329
+ applyThinkingEnabled();
1330
+ }
1331
+ }
1332
+ }
1213
1333
  return config;
1214
1334
  }
1215
1335
  function mapChatRoleToGemini(role) {
@@ -1270,6 +1390,55 @@ function cloneAsJsonValue(value) {
1270
1390
  return String(value ?? '');
1271
1391
  }
1272
1392
  }
1393
+ function isResponsesOrigin(chat) {
1394
+ const semantics = chat?.semantics;
1395
+ if (semantics && semantics.responses && isJsonObject(semantics.responses)) {
1396
+ return true;
1397
+ }
1398
+ const ctx = chat?.metadata && typeof chat.metadata === 'object'
1399
+ ? chat.metadata.context
1400
+ : undefined;
1401
+ const protocol = typeof ctx?.providerProtocol === 'string' ? ctx.providerProtocol.trim().toLowerCase() : '';
1402
+ if (protocol === 'openai-responses') {
1403
+ return true;
1404
+ }
1405
+ const endpoint = typeof ctx?.entryEndpoint === 'string' ? ctx.entryEndpoint.trim().toLowerCase() : '';
1406
+ return endpoint === '/v1/responses';
1407
+ }
1408
+ function appendMappingAudit(chat, options) {
1409
+ const metadata = chat.metadata && typeof chat.metadata === 'object'
1410
+ ? chat.metadata
1411
+ : (chat.metadata = { context: chat.metadata?.context ?? {} });
1412
+ const root = metadata.mappingAudit && typeof metadata.mappingAudit === 'object' && !Array.isArray(metadata.mappingAudit)
1413
+ ? metadata.mappingAudit
1414
+ : (metadata.mappingAudit = {});
1415
+ const current = Array.isArray(root[options.bucket]) ? root[options.bucket] : [];
1416
+ const duplicate = current.find((entry) => entry &&
1417
+ entry.field === options.field &&
1418
+ entry.targetProtocol === options.targetProtocol &&
1419
+ entry.reason === options.reason);
1420
+ if (!duplicate) {
1421
+ current.push({
1422
+ field: options.field,
1423
+ source: options.source ?? 'chat.parameters',
1424
+ targetProtocol: options.targetProtocol,
1425
+ reason: options.reason
1426
+ });
1427
+ }
1428
+ root[options.bucket] = current;
1429
+ }
1430
+ function appendDroppedFieldAudit(chat, options) {
1431
+ appendMappingAudit(chat, {
1432
+ bucket: 'dropped',
1433
+ ...options
1434
+ });
1435
+ }
1436
+ function appendLossyFieldAudit(chat, options) {
1437
+ appendMappingAudit(chat, {
1438
+ bucket: 'lossy',
1439
+ ...options
1440
+ });
1441
+ }
1273
1442
  export class GeminiSemanticMapper {
1274
1443
  async toChat(format, ctx) {
1275
1444
  const payload = (format.payload ?? {});
@@ -6,11 +6,17 @@ const RESPONSES_PARAMETER_KEYS = [
6
6
  'temperature',
7
7
  'top_p',
8
8
  'top_k',
9
+ 'prompt_cache_key',
10
+ 'reasoning',
9
11
  'max_tokens',
10
12
  'max_output_tokens',
11
13
  'response_format',
12
14
  'tool_choice',
13
15
  'parallel_tool_calls',
16
+ 'service_tier',
17
+ 'truncation',
18
+ 'include',
19
+ 'store',
14
20
  'user',
15
21
  'logit_bias',
16
22
  'seed',
@@ -15,6 +15,8 @@ import { applyGeminiWebSearchCompat } from '../../../compat/actions/gemini-web-s
15
15
  import { applyIflowWebSearchRequestTransform } from '../../../compat/actions/iflow-web-search.js';
16
16
  import { applyIflowToolTextFallback } from '../../../compat/actions/iflow-tool-text-fallback.js';
17
17
  import { unwrapIflowResponseBodyEnvelope } from '../../../compat/actions/iflow-response-body-unwrap.js';
18
+ import { applyDeepSeekWebRequestTransform } from '../../../compat/actions/deepseek-web-request.js';
19
+ import { applyDeepSeekWebResponseTransform } from '../../../compat/actions/deepseek-web-response.js';
18
20
  import { applyIflowKimiHistoryMediaPlaceholder } from '../../../compat/actions/iflow-kimi-history-media-placeholder.js';
19
21
  import { applyIflowKimiCliDefaults } from '../../../compat/actions/iflow-kimi-cli-defaults.js';
20
22
  import { fillIflowKimiThinkingReasoningContent } from '../../../compat/actions/iflow-kimi-thinking-reasoning-fill.js';
@@ -267,6 +269,16 @@ function applyMapping(root, mapping, state) {
267
269
  replaceRoot(root, unwrapIflowResponseBodyEnvelope(root));
268
270
  }
269
271
  break;
272
+ case 'deepseek_web_request':
273
+ if (state.direction === 'request') {
274
+ replaceRoot(root, applyDeepSeekWebRequestTransform(root, state.adapterContext));
275
+ }
276
+ break;
277
+ case 'deepseek_web_response':
278
+ if (state.direction === 'response') {
279
+ replaceRoot(root, applyDeepSeekWebResponseTransform(root, state.adapterContext));
280
+ }
281
+ break;
270
282
  case 'claude_thinking_tool_schema':
271
283
  if (state.direction === 'request') {
272
284
  replaceRoot(root, applyClaudeThinkingToolSchemaCompat(root, state.adapterContext));
@@ -1,6 +1,7 @@
1
1
  const PROFILE_BY_PROVIDER_FAMILY = {
2
2
  iflow: 'chat:iflow',
3
3
  lmstudio: 'chat:lmstudio',
4
+ deepseek: 'chat:deepseek-web',
4
5
  antigravity: 'chat:gemini-cli',
5
6
  'gemini-cli': 'chat:gemini-cli'
6
7
  };
@@ -132,6 +132,10 @@ export type MappingInstruction = {
132
132
  models?: string[];
133
133
  } | {
134
134
  action: 'iflow_response_body_unwrap';
135
+ } | {
136
+ action: 'deepseek_web_request';
137
+ } | {
138
+ action: 'deepseek_web_response';
135
139
  } | {
136
140
  action: 'claude_thinking_tool_schema';
137
141
  } | {