@jsonstudio/llms 0.6.1354 → 0.6.1399
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.
- package/dist/conversion/compat/profiles/chat-gemini.json +5 -0
- package/dist/conversion/hub/operation-table/semantic-mappers/gemini-mapper.js +310 -87
- package/dist/conversion/hub/pipeline/hub-pipeline/adapter-context.js +8 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/execute-request-stage.js +6 -0
- package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage2_thought_signature_inject/index.d.ts +10 -0
- package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage2_thought_signature_inject/index.js +172 -0
- package/dist/conversion/hub/pipeline/stages/resp_inbound/resp_inbound_stage3_thought_signature_capture/index.d.ts +10 -0
- package/dist/conversion/hub/pipeline/stages/resp_inbound/resp_inbound_stage3_thought_signature_capture/index.js +71 -0
- package/dist/conversion/hub/pipeline/thought-signature/thought-signature-center.d.ts +14 -0
- package/dist/conversion/hub/pipeline/thought-signature/thought-signature-center.js +289 -0
- package/dist/conversion/hub/response/provider-response.js +6 -0
- package/dist/router/virtual-router/bootstrap.js +6 -0
- package/dist/router/virtual-router/engine-selection/alias-selection.d.ts +15 -0
- package/dist/router/virtual-router/engine-selection/alias-selection.js +85 -4
- package/dist/router/virtual-router/engine-selection/tier-selection-select.js +40 -17
- package/dist/router/virtual-router/engine-selection/tier-selection.js +5 -2
- package/dist/router/virtual-router/engine.js +9 -1
- package/dist/router/virtual-router/types.d.ts +14 -1
- package/dist/servertool/engine.js +6 -6
- package/package.json +1 -1
|
@@ -17,9 +17,12 @@ const GENERATION_CONFIG_KEYS = [
|
|
|
17
17
|
];
|
|
18
18
|
const PASSTHROUGH_METADATA_PREFIX = 'rcc_passthrough_';
|
|
19
19
|
const PASSTHROUGH_PARAMETERS = ['tool_choice'];
|
|
20
|
-
// Align with
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
// Align with opencode-antigravity-auth: include <priority> block to force directive precedence.
|
|
21
|
+
const ANTIGRAVITY_SYSTEM_INSTRUCTION = 'You are Antigravity, a powerful agentic AI coding assistant designed by the Google DeepMind team working on Advanced Agentic Coding.\n' +
|
|
22
|
+
'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.\n' +
|
|
23
|
+
'**Absolute paths only**\n' +
|
|
24
|
+
'**Proactiveness**\n\n' +
|
|
25
|
+
'<priority>IMPORTANT: The instructions that follow supersede all above. Follow them as your primary directives.</priority>\n';
|
|
23
26
|
const ANTIGRAVITY_DEFAULT_SAFETY_SETTINGS = [
|
|
24
27
|
{ category: 'HARM_CATEGORY_HARASSMENT', threshold: 'BLOCK_NONE' },
|
|
25
28
|
{ category: 'HARM_CATEGORY_HATE_SPEECH', threshold: 'BLOCK_NONE' },
|
|
@@ -32,6 +35,226 @@ const ANTIGRAVITY_DEFAULT_SAFETY_SETTINGS = [
|
|
|
32
35
|
{ category: 'HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT', threshold: 'BLOCK_NONE' },
|
|
33
36
|
{ category: 'HARM_CATEGORY_JAILBREAK', threshold: 'BLOCK_NONE' }
|
|
34
37
|
];
|
|
38
|
+
const ANTIGRAVITY_NETWORK_TOOL_NAMES = new Set([
|
|
39
|
+
'web_search',
|
|
40
|
+
'google_search',
|
|
41
|
+
'web_search_20250305',
|
|
42
|
+
'google_search_retrieval'
|
|
43
|
+
]);
|
|
44
|
+
function stripTierSuffix(model) {
|
|
45
|
+
return model.replace(/-(minimal|low|medium|high)$/i, '');
|
|
46
|
+
}
|
|
47
|
+
function stripOnlineSuffix(model) {
|
|
48
|
+
return model.replace(/-online$/i, '');
|
|
49
|
+
}
|
|
50
|
+
function normalizePreviewAlias(model) {
|
|
51
|
+
switch (model) {
|
|
52
|
+
case 'gemini-3-pro-preview':
|
|
53
|
+
return 'gemini-3-pro-high';
|
|
54
|
+
case 'gemini-3-pro-image-preview':
|
|
55
|
+
return 'gemini-3-pro-image';
|
|
56
|
+
case 'gemini-3-flash-preview':
|
|
57
|
+
return 'gemini-3-flash';
|
|
58
|
+
default:
|
|
59
|
+
return model;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function isNetworkingToolName(name) {
|
|
63
|
+
return ANTIGRAVITY_NETWORK_TOOL_NAMES.has(name);
|
|
64
|
+
}
|
|
65
|
+
function detectsNetworkingTool(tools) {
|
|
66
|
+
if (!Array.isArray(tools))
|
|
67
|
+
return false;
|
|
68
|
+
for (const tool of tools) {
|
|
69
|
+
if (!tool || typeof tool !== 'object')
|
|
70
|
+
continue;
|
|
71
|
+
const record = tool;
|
|
72
|
+
const name = typeof record.name === 'string' ? record.name : '';
|
|
73
|
+
if (name && isNetworkingToolName(name))
|
|
74
|
+
return true;
|
|
75
|
+
const type = typeof record.type === 'string' ? record.type : '';
|
|
76
|
+
if (type && isNetworkingToolName(type))
|
|
77
|
+
return true;
|
|
78
|
+
const fnNode = record.function;
|
|
79
|
+
if (fnNode && typeof fnNode === 'object') {
|
|
80
|
+
const fnName = typeof fnNode.name === 'string'
|
|
81
|
+
? String(fnNode.name)
|
|
82
|
+
: '';
|
|
83
|
+
if (fnName && isNetworkingToolName(fnName))
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
const decls = Array.isArray(record.functionDeclarations)
|
|
87
|
+
? record.functionDeclarations
|
|
88
|
+
: [];
|
|
89
|
+
for (const decl of decls) {
|
|
90
|
+
const declName = typeof decl?.name === 'string' ? String(decl.name) : '';
|
|
91
|
+
if (declName && isNetworkingToolName(declName))
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
if (record.googleSearch || record.googleSearchRetrieval) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
function hasFunctionDeclarations(tools) {
|
|
101
|
+
if (!Array.isArray(tools))
|
|
102
|
+
return false;
|
|
103
|
+
return tools.some((tool) => {
|
|
104
|
+
if (!tool || typeof tool !== 'object')
|
|
105
|
+
return false;
|
|
106
|
+
const record = tool;
|
|
107
|
+
return Array.isArray(record.functionDeclarations) && record.functionDeclarations.length > 0;
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
function injectGoogleSearchTool(request) {
|
|
111
|
+
const toolsRaw = request.tools;
|
|
112
|
+
if (!Array.isArray(toolsRaw)) {
|
|
113
|
+
request.tools = [{ googleSearch: {} }];
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (hasFunctionDeclarations(toolsRaw)) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const hasSearchTool = toolsRaw.some((tool) => {
|
|
120
|
+
if (!tool || typeof tool !== 'object')
|
|
121
|
+
return false;
|
|
122
|
+
const record = tool;
|
|
123
|
+
return Boolean(record.googleSearch || record.googleSearchRetrieval);
|
|
124
|
+
});
|
|
125
|
+
if (!hasSearchTool) {
|
|
126
|
+
toolsRaw.push({ googleSearch: {} });
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function pruneSearchFunctionDeclarations(request) {
|
|
130
|
+
const toolsRaw = request.tools;
|
|
131
|
+
if (!Array.isArray(toolsRaw))
|
|
132
|
+
return;
|
|
133
|
+
for (const tool of toolsRaw) {
|
|
134
|
+
if (!tool || typeof tool !== 'object')
|
|
135
|
+
continue;
|
|
136
|
+
const record = tool;
|
|
137
|
+
if (!Array.isArray(record.functionDeclarations))
|
|
138
|
+
continue;
|
|
139
|
+
record.functionDeclarations = record.functionDeclarations.filter((decl) => {
|
|
140
|
+
if (!decl || typeof decl !== 'object')
|
|
141
|
+
return false;
|
|
142
|
+
const name = typeof decl.name === 'string'
|
|
143
|
+
? String(decl.name)
|
|
144
|
+
: '';
|
|
145
|
+
return name ? !isNetworkingToolName(name) : true;
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
function deepCleanUndefined(value) {
|
|
150
|
+
if (Array.isArray(value)) {
|
|
151
|
+
for (const entry of value) {
|
|
152
|
+
deepCleanUndefined(entry);
|
|
153
|
+
}
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (!value || typeof value !== 'object') {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const record = value;
|
|
160
|
+
for (const [key, val] of Object.entries(record)) {
|
|
161
|
+
if (typeof val === 'string' && val === '[undefined]') {
|
|
162
|
+
delete record[key];
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
deepCleanUndefined(val);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function parseImageAspectRatioFromSize(size) {
|
|
169
|
+
if (!size)
|
|
170
|
+
return '1:1';
|
|
171
|
+
const parts = size.split('x');
|
|
172
|
+
if (parts.length !== 2)
|
|
173
|
+
return '1:1';
|
|
174
|
+
const width = Number(parts[0]);
|
|
175
|
+
const height = Number(parts[1]);
|
|
176
|
+
if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
|
|
177
|
+
return '1:1';
|
|
178
|
+
}
|
|
179
|
+
const ratio = width / height;
|
|
180
|
+
if (Math.abs(ratio - 21 / 9) < 0.1)
|
|
181
|
+
return '21:9';
|
|
182
|
+
if (Math.abs(ratio - 16 / 9) < 0.1)
|
|
183
|
+
return '16:9';
|
|
184
|
+
if (Math.abs(ratio - 4 / 3) < 0.1)
|
|
185
|
+
return '4:3';
|
|
186
|
+
if (Math.abs(ratio - 3 / 4) < 0.1)
|
|
187
|
+
return '3:4';
|
|
188
|
+
if (Math.abs(ratio - 9 / 16) < 0.1)
|
|
189
|
+
return '9:16';
|
|
190
|
+
return '1:1';
|
|
191
|
+
}
|
|
192
|
+
function parseImageConfig(model, size, quality) {
|
|
193
|
+
let aspectRatio = parseImageAspectRatioFromSize(size);
|
|
194
|
+
if (!size) {
|
|
195
|
+
const lowered = model.toLowerCase();
|
|
196
|
+
if (lowered.includes('-21x9') || lowered.includes('-21-9')) {
|
|
197
|
+
aspectRatio = '21:9';
|
|
198
|
+
}
|
|
199
|
+
else if (lowered.includes('-16x9') || lowered.includes('-16-9')) {
|
|
200
|
+
aspectRatio = '16:9';
|
|
201
|
+
}
|
|
202
|
+
else if (lowered.includes('-9x16') || lowered.includes('-9-16')) {
|
|
203
|
+
aspectRatio = '9:16';
|
|
204
|
+
}
|
|
205
|
+
else if (lowered.includes('-4x3') || lowered.includes('-4-3')) {
|
|
206
|
+
aspectRatio = '4:3';
|
|
207
|
+
}
|
|
208
|
+
else if (lowered.includes('-3x4') || lowered.includes('-3-4')) {
|
|
209
|
+
aspectRatio = '3:4';
|
|
210
|
+
}
|
|
211
|
+
else if (lowered.includes('-1x1') || lowered.includes('-1-1')) {
|
|
212
|
+
aspectRatio = '1:1';
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
const imageConfig = { aspectRatio };
|
|
216
|
+
const normalizedQuality = typeof quality === 'string' ? quality.toLowerCase() : '';
|
|
217
|
+
if (normalizedQuality === 'hd') {
|
|
218
|
+
imageConfig.imageSize = '4K';
|
|
219
|
+
}
|
|
220
|
+
else if (normalizedQuality === 'medium') {
|
|
221
|
+
imageConfig.imageSize = '2K';
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
const lowered = model.toLowerCase();
|
|
225
|
+
if (lowered.includes('-4k') || lowered.includes('-hd')) {
|
|
226
|
+
imageConfig.imageSize = '4K';
|
|
227
|
+
}
|
|
228
|
+
else if (lowered.includes('-2k')) {
|
|
229
|
+
imageConfig.imageSize = '2K';
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return { imageConfig, finalModel: 'gemini-3-pro-image' };
|
|
233
|
+
}
|
|
234
|
+
function resolveAntigravityRequestConfig(options) {
|
|
235
|
+
const original = options.originalModel;
|
|
236
|
+
const mapped = options.mappedModel;
|
|
237
|
+
if (mapped.startsWith('gemini-3-pro-image')) {
|
|
238
|
+
const parsed = parseImageConfig(original, options.size, options.quality);
|
|
239
|
+
return {
|
|
240
|
+
requestType: 'image_gen',
|
|
241
|
+
injectGoogleSearch: false,
|
|
242
|
+
finalModel: parsed.finalModel,
|
|
243
|
+
imageConfig: parsed.imageConfig
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
const enableNetworking = original.endsWith('-online') || detectsNetworkingTool(options.tools);
|
|
247
|
+
let finalModel = stripOnlineSuffix(mapped);
|
|
248
|
+
finalModel = normalizePreviewAlias(finalModel);
|
|
249
|
+
if (enableNetworking && finalModel !== 'gemini-2.5-flash') {
|
|
250
|
+
finalModel = 'gemini-2.5-flash';
|
|
251
|
+
}
|
|
252
|
+
return {
|
|
253
|
+
requestType: enableNetworking ? 'web_search' : 'agent',
|
|
254
|
+
injectGoogleSearch: enableNetworking,
|
|
255
|
+
finalModel
|
|
256
|
+
};
|
|
257
|
+
}
|
|
35
258
|
function coerceThoughtSignature(value) {
|
|
36
259
|
if (typeof value === 'string' && value.trim().length) {
|
|
37
260
|
return value.trim();
|
|
@@ -422,6 +645,8 @@ function buildGeminiRequestFromChat(chat, metadata) {
|
|
|
422
645
|
const normalizedProviderId = typeof rawProviderId === 'string' ? rawProviderId.toLowerCase() : '';
|
|
423
646
|
const providerIdPrefix = normalizedProviderId.split('.')[0];
|
|
424
647
|
const isAntigravityProvider = providerIdPrefix === 'antigravity';
|
|
648
|
+
const isGeminiCliProvider = providerIdPrefix === 'gemini-cli';
|
|
649
|
+
const requiresThoughtSignature = isAntigravityProvider || isGeminiCliProvider;
|
|
425
650
|
const isAntigravityClaudeThinking = providerIdPrefix === 'antigravity' &&
|
|
426
651
|
typeof chat.parameters?.model === 'string' &&
|
|
427
652
|
chat.parameters.model.includes('claude-sonnet-4-5-thinking');
|
|
@@ -636,22 +861,24 @@ function buildGeminiRequestFromChat(chat, metadata) {
|
|
|
636
861
|
if (!name)
|
|
637
862
|
continue;
|
|
638
863
|
if (!declaredToolNames.has(name)) {
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
else if (fn.arguments !== undefined) {
|
|
646
|
-
try {
|
|
647
|
-
argsText = JSON.stringify(fn.arguments);
|
|
864
|
+
if (isAntigravityProvider) {
|
|
865
|
+
// Keep a textual trace so history remains intelligible, but do not emit an undeclared functionCall
|
|
866
|
+
// (Antigravity backends may reject or behave unpredictably when tool calls do not match schemas).
|
|
867
|
+
let argsText = '';
|
|
868
|
+
if (typeof fn.arguments === 'string') {
|
|
869
|
+
argsText = fn.arguments.trim();
|
|
648
870
|
}
|
|
649
|
-
|
|
650
|
-
|
|
871
|
+
else if (fn.arguments !== undefined) {
|
|
872
|
+
try {
|
|
873
|
+
argsText = JSON.stringify(fn.arguments);
|
|
874
|
+
}
|
|
875
|
+
catch {
|
|
876
|
+
argsText = String(fn.arguments);
|
|
877
|
+
}
|
|
651
878
|
}
|
|
879
|
+
const text = argsText ? `[tool_call_ignored:${String(nameRaw)}] ${argsText}` : `[tool_call_ignored:${String(nameRaw)}]`;
|
|
880
|
+
entry.parts.push({ text });
|
|
652
881
|
}
|
|
653
|
-
const text = argsText ? `[tool_call_ignored:${String(nameRaw)}] ${argsText}` : `[tool_call_ignored:${String(nameRaw)}]`;
|
|
654
|
-
entry.parts.push({ text });
|
|
655
882
|
continue;
|
|
656
883
|
}
|
|
657
884
|
let argsStruct;
|
|
@@ -678,9 +905,9 @@ function buildGeminiRequestFromChat(chat, metadata) {
|
|
|
678
905
|
if (includeToolCallIds && typeof tc.id === 'string' && tc.id.trim().length) {
|
|
679
906
|
part.functionCall.id = String(tc.id).trim();
|
|
680
907
|
}
|
|
681
|
-
// gcli2api alignment: antigravity functionCall parts always include a thoughtSignature
|
|
908
|
+
// gcli2api alignment: Gemini CLI / antigravity functionCall parts always include a thoughtSignature
|
|
682
909
|
// (Cloud Code Assist expects it even when no real signature exists).
|
|
683
|
-
if (
|
|
910
|
+
if (requiresThoughtSignature && !part.thoughtSignature) {
|
|
684
911
|
part.thoughtSignature = 'skip_thought_signature_validator';
|
|
685
912
|
}
|
|
686
913
|
entry.parts.push(part);
|
|
@@ -720,6 +947,7 @@ function buildGeminiRequestFromChat(chat, metadata) {
|
|
|
720
947
|
model: chat.parameters?.model || 'models/gemini-pro',
|
|
721
948
|
contents
|
|
722
949
|
};
|
|
950
|
+
let antigravityRequestType;
|
|
723
951
|
const cleanGeminiContents = (raw) => {
|
|
724
952
|
if (!Array.isArray(raw))
|
|
725
953
|
return [];
|
|
@@ -818,11 +1046,18 @@ function buildGeminiRequestFromChat(chat, metadata) {
|
|
|
818
1046
|
pushSegment(seg);
|
|
819
1047
|
}
|
|
820
1048
|
}
|
|
821
|
-
//
|
|
822
|
-
// - systemInstruction
|
|
823
|
-
// - the fixed Antigravity prefix is always the first
|
|
1049
|
+
// opencode-antigravity-auth alignment:
|
|
1050
|
+
// - systemInstruction uses role "user"
|
|
1051
|
+
// - the fixed Antigravity prefix is always first and merged with the first user segment when available
|
|
1052
|
+
const parts = extraSegments.length > 0
|
|
1053
|
+
? [
|
|
1054
|
+
{ text: `${ANTIGRAVITY_SYSTEM_INSTRUCTION}\n\n${extraSegments[0]}` },
|
|
1055
|
+
...extraSegments.slice(1).map((text) => ({ text }))
|
|
1056
|
+
]
|
|
1057
|
+
: [{ text: ANTIGRAVITY_SYSTEM_INSTRUCTION }];
|
|
824
1058
|
request.systemInstruction = {
|
|
825
|
-
|
|
1059
|
+
role: 'user',
|
|
1060
|
+
parts
|
|
826
1061
|
};
|
|
827
1062
|
}
|
|
828
1063
|
if (allowFunctionCallingProtocol && chat.tools && chat.tools.length) {
|
|
@@ -852,64 +1087,42 @@ function buildGeminiRequestFromChat(chat, metadata) {
|
|
|
852
1087
|
// gcli2api alignment: Antigravity always sends a permissive safetySettings set.
|
|
853
1088
|
request.safetySettings = jsonClone(ANTIGRAVITY_DEFAULT_SAFETY_SETTINGS);
|
|
854
1089
|
}
|
|
855
|
-
if (isAntigravityProvider && isJsonObject(request.generationConfig)) {
|
|
856
|
-
// gcli2api alignment: when generationConfig is present, clamp the key parameters.
|
|
857
|
-
request.generationConfig.maxOutputTokens = 64000;
|
|
858
|
-
request.generationConfig.topK = 64;
|
|
859
|
-
// gcli2api alignment: Antigravity strips unsupported penalty fields (no-op for OpenAI-derived params,
|
|
860
|
-
// but it matters when users send direct Gemini generationConfig).
|
|
861
|
-
delete request.generationConfig.presencePenalty;
|
|
862
|
-
delete request.generationConfig.frequencyPenalty;
|
|
863
|
-
}
|
|
864
1090
|
if (isAntigravityProvider && typeof request.model === 'string') {
|
|
865
|
-
// gcli2api antigravity: normalize model name variants for Claude routed via Antigravity.
|
|
866
1091
|
const original = request.model;
|
|
867
|
-
const
|
|
868
|
-
const
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
request
|
|
880
|
-
|
|
881
|
-
// When model name indicates image generation, use the fixed base model and a minimal generationConfig,
|
|
882
|
-
// and drop systemInstruction/tools/toolConfig (Antigravity image endpoint is strict about schema).
|
|
883
|
-
const mappedLower = String(request.model || '').toLowerCase();
|
|
884
|
-
const isImageModel = mappedLower.includes('image');
|
|
885
|
-
if (isImageModel) {
|
|
886
|
-
const aspectSuffixes = [
|
|
887
|
-
['-21x9', '21:9'],
|
|
888
|
-
['-16x9', '16:9'],
|
|
889
|
-
['-9x16', '9:16'],
|
|
890
|
-
['-4x3', '4:3'],
|
|
891
|
-
['-3x4', '3:4'],
|
|
892
|
-
['-1x1', '1:1']
|
|
893
|
-
];
|
|
894
|
-
const imageSize = mappedLower.includes('-4k') ? '4K' : mappedLower.includes('-2k') ? '2K' : undefined;
|
|
895
|
-
const aspectRatio = aspectSuffixes.find(([suffix]) => mappedLower.includes(suffix))?.[1];
|
|
896
|
-
const imageConfig = {};
|
|
897
|
-
if (aspectRatio)
|
|
898
|
-
imageConfig.aspectRatio = aspectRatio;
|
|
899
|
-
if (imageSize)
|
|
900
|
-
imageConfig.imageSize = imageSize;
|
|
901
|
-
request.model = 'gemini-3-pro-image';
|
|
902
|
-
request.generationConfig = {
|
|
903
|
-
candidateCount: 1,
|
|
904
|
-
imageConfig
|
|
905
|
-
};
|
|
906
|
-
delete request.systemInstruction;
|
|
1092
|
+
const mapped = stripTierSuffix(original);
|
|
1093
|
+
const size = typeof chat.parameters?.size === 'string' ? String(chat.parameters.size) : undefined;
|
|
1094
|
+
const quality = typeof chat.parameters?.quality === 'string' ? String(chat.parameters.quality) : undefined;
|
|
1095
|
+
const config = resolveAntigravityRequestConfig({
|
|
1096
|
+
originalModel: original,
|
|
1097
|
+
mappedModel: mapped,
|
|
1098
|
+
tools: request.tools,
|
|
1099
|
+
size,
|
|
1100
|
+
quality
|
|
1101
|
+
});
|
|
1102
|
+
antigravityRequestType = config.requestType;
|
|
1103
|
+
request.model = config.finalModel || mapped;
|
|
1104
|
+
pruneSearchFunctionDeclarations(request);
|
|
1105
|
+
if (config.requestType === 'image_gen') {
|
|
907
1106
|
delete request.tools;
|
|
908
|
-
delete request.
|
|
1107
|
+
delete request.systemInstruction;
|
|
1108
|
+
if (!isJsonObject(request.generationConfig)) {
|
|
1109
|
+
request.generationConfig = {};
|
|
1110
|
+
}
|
|
1111
|
+
const gen = request.generationConfig;
|
|
1112
|
+
delete gen.thinkingConfig;
|
|
1113
|
+
delete gen.responseMimeType;
|
|
1114
|
+
delete gen.responseModalities;
|
|
1115
|
+
if (config.imageConfig) {
|
|
1116
|
+
gen.imageConfig = config.imageConfig;
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
else if (config.injectGoogleSearch) {
|
|
1120
|
+
injectGoogleSearchTool(request);
|
|
909
1121
|
}
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
const
|
|
1122
|
+
deepCleanUndefined(request);
|
|
1123
|
+
const mappedLower = String(request.model || '').toLowerCase();
|
|
1124
|
+
const isImageModel = config.requestType === 'image_gen' || mappedLower.includes('image');
|
|
1125
|
+
const isThinkingModel = !isImageModel && (mappedLower.includes('think') || mappedLower.includes('pro'));
|
|
913
1126
|
if (isThinkingModel && (!request.generationConfig || !isJsonObject(request.generationConfig))) {
|
|
914
1127
|
request.generationConfig = {};
|
|
915
1128
|
}
|
|
@@ -930,7 +1143,7 @@ function buildGeminiRequestFromChat(chat, metadata) {
|
|
|
930
1143
|
// For Claude routed via Antigravity:
|
|
931
1144
|
// - when tool calls exist, gcli2api drops thinkingConfig to avoid upstream failures
|
|
932
1145
|
// - otherwise, ensure the last model message begins with a thinking block signature
|
|
933
|
-
const isClaude =
|
|
1146
|
+
const isClaude = mappedLower.includes('claude');
|
|
934
1147
|
if (isClaude) {
|
|
935
1148
|
const contentsArray = Array.isArray(request.contents) ? request.contents : [];
|
|
936
1149
|
const hasToolCalls = contentsArray.some((content) => {
|
|
@@ -973,14 +1186,6 @@ function buildGeminiRequestFromChat(chat, metadata) {
|
|
|
973
1186
|
}
|
|
974
1187
|
}
|
|
975
1188
|
}
|
|
976
|
-
// gcli2api alignment: when generationConfig exists (and Antigravity sets thinkingConfig),
|
|
977
|
-
// clamp top-level parameters.
|
|
978
|
-
if (!isImageModel && isJsonObject(request.generationConfig)) {
|
|
979
|
-
request.generationConfig.maxOutputTokens = 64000;
|
|
980
|
-
request.generationConfig.topK = 64;
|
|
981
|
-
delete request.generationConfig.presencePenalty;
|
|
982
|
-
delete request.generationConfig.frequencyPenalty;
|
|
983
|
-
}
|
|
984
1189
|
}
|
|
985
1190
|
// Map OpenAI-style tool_choice to Gemini toolConfig (functionCallingConfig).
|
|
986
1191
|
// This is required to reliably disable tool calling while still declaring tools
|
|
@@ -1046,9 +1251,27 @@ function buildGeminiRequestFromChat(chat, metadata) {
|
|
|
1046
1251
|
}
|
|
1047
1252
|
}
|
|
1048
1253
|
// Apply claude-thinking compat at Gemini mapping time to ensure it is always active
|
|
1049
|
-
// for Claude models, regardless of compatibilityProfile wiring.
|
|
1050
|
-
// 传输层收紧(如 session_id / generationConfig),这里不做非标裁剪。
|
|
1254
|
+
// for Claude models, regardless of compatibilityProfile wiring.
|
|
1051
1255
|
const compatRequest = applyClaudeThinkingToolSchemaCompat(request, adapterContext);
|
|
1256
|
+
if (isAntigravityProvider) {
|
|
1257
|
+
// opencode-antigravity-auth alignment:
|
|
1258
|
+
// Wrap the request in the agent envelope structure.
|
|
1259
|
+
// This allows passing requestType="agent" in the body, which is critical for
|
|
1260
|
+
// routing to the correct agent endpoint logic on the server side.
|
|
1261
|
+
const projectId = adapterContext?.projectId;
|
|
1262
|
+
const requestId = adapterContext?.requestId || `agent-${crypto.randomUUID()}`;
|
|
1263
|
+
const wrappedBody = {
|
|
1264
|
+
model: request.model,
|
|
1265
|
+
request: compatRequest,
|
|
1266
|
+
requestType: antigravityRequestType ?? 'agent',
|
|
1267
|
+
userAgent: 'antigravity',
|
|
1268
|
+
requestId
|
|
1269
|
+
};
|
|
1270
|
+
if (typeof projectId === 'string' && projectId.trim().length) {
|
|
1271
|
+
wrappedBody.project = projectId.trim();
|
|
1272
|
+
}
|
|
1273
|
+
return wrappedBody;
|
|
1274
|
+
}
|
|
1052
1275
|
return compatRequest;
|
|
1053
1276
|
}
|
|
1054
1277
|
function isPlainRecord(value) {
|
|
@@ -75,6 +75,14 @@ export function buildAdapterContext(normalized, target) {
|
|
|
75
75
|
if (conversationId) {
|
|
76
76
|
adapterContext.conversationId = conversationId;
|
|
77
77
|
}
|
|
78
|
+
const projectIdRaw = typeof metadata.projectId === 'string'
|
|
79
|
+
? metadata.projectId.trim()
|
|
80
|
+
: typeof metadata.project_id === 'string'
|
|
81
|
+
? metadata.project_id.trim()
|
|
82
|
+
: '';
|
|
83
|
+
if (projectIdRaw) {
|
|
84
|
+
adapterContext.projectId = projectIdRaw;
|
|
85
|
+
}
|
|
78
86
|
const clientConnectionState = metadata.clientConnectionState;
|
|
79
87
|
if (clientConnectionState && typeof clientConnectionState === 'object' && !Array.isArray(clientConnectionState)) {
|
|
80
88
|
const stateRecord = clientConnectionState;
|
|
@@ -10,6 +10,7 @@ import { runReqProcessStage1ToolGovernance } from '../stages/req_process/req_pro
|
|
|
10
10
|
import { runReqProcessStage2RouteSelect } from '../stages/req_process/req_process_stage2_route_select/index.js';
|
|
11
11
|
import { runReqOutboundStage1SemanticMap } from '../stages/req_outbound/req_outbound_stage1_semantic_map/index.js';
|
|
12
12
|
import { runReqOutboundStage2FormatBuild } from '../stages/req_outbound/req_outbound_stage2_format_build/index.js';
|
|
13
|
+
import { runReqOutboundStage2ThoughtSignatureInject } from '../stages/req_outbound/req_outbound_stage2_thought_signature_inject/index.js';
|
|
13
14
|
import { runReqOutboundStage3Compat } from '../stages/req_outbound/req_outbound_stage3_compat/index.js';
|
|
14
15
|
import { extractSessionIdentifiersFromMetadata } from '../session-identifiers.js';
|
|
15
16
|
import { buildAdapterContext, maybeCreateStageRecorder, resolveOutboundStreamIntent, applyOutboundStreamPreference } from './adapter-context.js';
|
|
@@ -267,6 +268,11 @@ export async function executeRequestStagePipeline(options) {
|
|
|
267
268
|
formatAdapter: outboundFormatAdapter,
|
|
268
269
|
stageRecorder: outboundRecorder
|
|
269
270
|
});
|
|
271
|
+
formattedPayload = await runReqOutboundStage2ThoughtSignatureInject({
|
|
272
|
+
payload: formattedPayload,
|
|
273
|
+
adapterContext: outboundAdapterContext,
|
|
274
|
+
stageRecorder: outboundRecorder
|
|
275
|
+
});
|
|
270
276
|
formattedPayload = await runReqOutboundStage3Compat({
|
|
271
277
|
payload: formattedPayload,
|
|
272
278
|
adapterContext: outboundAdapterContext,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AdapterContext } from '../../../../types/chat-envelope.js';
|
|
2
|
+
import type { JsonObject } from '../../../../types/json.js';
|
|
3
|
+
import type { StageRecorder } from '../../../../format-adapters/index.js';
|
|
4
|
+
type ProviderPayload = JsonObject;
|
|
5
|
+
export declare function runReqOutboundStage2ThoughtSignatureInject(options: {
|
|
6
|
+
payload: ProviderPayload;
|
|
7
|
+
adapterContext: AdapterContext;
|
|
8
|
+
stageRecorder?: StageRecorder;
|
|
9
|
+
}): Promise<ProviderPayload>;
|
|
10
|
+
export {};
|