antigravity-auth 1.6.0 → 1.7.0
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/README.md +79 -41
- package/dist/cli.js +2868 -0
- package/dist/handler.js +25119 -0
- package/dist/index.js +25110 -5
- package/package.json +66 -54
- package/dist/antigravity/oauth.d.ts +0 -30
- package/dist/antigravity/oauth.js +0 -170
- package/dist/claude/login.d.ts +0 -7
- package/dist/claude/login.js +0 -480
- package/dist/claude/menu-helpers.d.ts +0 -22
- package/dist/claude/menu-helpers.js +0 -281
- package/dist/claude/proxy-manager.d.ts +0 -11
- package/dist/claude/proxy-manager.js +0 -129
- package/dist/claude/proxy.d.ts +0 -1
- package/dist/claude/proxy.js +0 -733
- package/dist/constants.d.ts +0 -138
- package/dist/constants.js +0 -216
- package/dist/hooks/auto-update-checker/cache.d.ts +0 -2
- package/dist/hooks/auto-update-checker/cache.js +0 -70
- package/dist/hooks/auto-update-checker/checker.d.ts +0 -15
- package/dist/hooks/auto-update-checker/checker.js +0 -233
- package/dist/hooks/auto-update-checker/constants.d.ts +0 -8
- package/dist/hooks/auto-update-checker/constants.js +0 -22
- package/dist/hooks/auto-update-checker/index.d.ts +0 -33
- package/dist/hooks/auto-update-checker/index.js +0 -121
- package/dist/hooks/auto-update-checker/logging.d.ts +0 -2
- package/dist/hooks/auto-update-checker/logging.js +0 -8
- package/dist/hooks/auto-update-checker/types.d.ts +0 -24
- package/dist/hooks/auto-update-checker/types.js +0 -1
- package/dist/index.d.ts +0 -6
- package/dist/opencode/hooks/auto-update-checker/cache.d.ts +0 -2
- package/dist/opencode/hooks/auto-update-checker/cache.js +0 -70
- package/dist/opencode/hooks/auto-update-checker/checker.d.ts +0 -15
- package/dist/opencode/hooks/auto-update-checker/checker.js +0 -233
- package/dist/opencode/hooks/auto-update-checker/constants.d.ts +0 -8
- package/dist/opencode/hooks/auto-update-checker/constants.js +0 -22
- package/dist/opencode/hooks/auto-update-checker/index.d.ts +0 -33
- package/dist/opencode/hooks/auto-update-checker/index.js +0 -121
- package/dist/opencode/hooks/auto-update-checker/logging.d.ts +0 -2
- package/dist/opencode/hooks/auto-update-checker/logging.js +0 -8
- package/dist/opencode/hooks/auto-update-checker/types.d.ts +0 -24
- package/dist/opencode/hooks/auto-update-checker/types.js +0 -1
- package/dist/opencode/plugin.d.ts +0 -29
- package/dist/opencode/plugin.js +0 -2954
- package/dist/plugin/accounts.d.ts +0 -173
- package/dist/plugin/accounts.js +0 -966
- package/dist/plugin/auth.d.ts +0 -20
- package/dist/plugin/auth.js +0 -44
- package/dist/plugin/cache/index.d.ts +0 -4
- package/dist/plugin/cache/index.js +0 -4
- package/dist/plugin/cache/signature-cache.d.ts +0 -110
- package/dist/plugin/cache/signature-cache.js +0 -347
- package/dist/plugin/cache.d.ts +0 -43
- package/dist/plugin/cache.js +0 -180
- package/dist/plugin/cli.d.ts +0 -26
- package/dist/plugin/cli.js +0 -126
- package/dist/plugin/config/index.d.ts +0 -15
- package/dist/plugin/config/index.js +0 -15
- package/dist/plugin/config/loader.d.ts +0 -38
- package/dist/plugin/config/loader.js +0 -150
- package/dist/plugin/config/models.d.ts +0 -26
- package/dist/plugin/config/models.js +0 -95
- package/dist/plugin/config/schema.d.ts +0 -144
- package/dist/plugin/config/schema.js +0 -458
- package/dist/plugin/config/updater.d.ts +0 -76
- package/dist/plugin/config/updater.js +0 -205
- package/dist/plugin/core/streaming/index.d.ts +0 -2
- package/dist/plugin/core/streaming/index.js +0 -2
- package/dist/plugin/core/streaming/transformer.d.ts +0 -9
- package/dist/plugin/core/streaming/transformer.js +0 -301
- package/dist/plugin/core/streaming/types.d.ts +0 -28
- package/dist/plugin/core/streaming/types.js +0 -1
- package/dist/plugin/debug.d.ts +0 -93
- package/dist/plugin/debug.js +0 -375
- package/dist/plugin/errors.d.ts +0 -27
- package/dist/plugin/errors.js +0 -41
- package/dist/plugin/fingerprint.d.ts +0 -69
- package/dist/plugin/fingerprint.js +0 -137
- package/dist/plugin/image-saver.d.ts +0 -24
- package/dist/plugin/image-saver.js +0 -78
- package/dist/plugin/logger.d.ts +0 -35
- package/dist/plugin/logger.js +0 -67
- package/dist/plugin/logging-utils.d.ts +0 -22
- package/dist/plugin/logging-utils.js +0 -91
- package/dist/plugin/project.d.ts +0 -32
- package/dist/plugin/project.js +0 -229
- package/dist/plugin/quota.d.ts +0 -34
- package/dist/plugin/quota.js +0 -261
- package/dist/plugin/recovery/constants.d.ts +0 -21
- package/dist/plugin/recovery/constants.js +0 -42
- package/dist/plugin/recovery/index.d.ts +0 -11
- package/dist/plugin/recovery/index.js +0 -11
- package/dist/plugin/recovery/storage.d.ts +0 -23
- package/dist/plugin/recovery/storage.js +0 -340
- package/dist/plugin/recovery/types.d.ts +0 -115
- package/dist/plugin/recovery/types.js +0 -6
- package/dist/plugin/recovery.d.ts +0 -60
- package/dist/plugin/recovery.js +0 -360
- package/dist/plugin/refresh-queue.d.ts +0 -99
- package/dist/plugin/refresh-queue.js +0 -235
- package/dist/plugin/request-helpers.d.ts +0 -281
- package/dist/plugin/request-helpers.js +0 -2200
- package/dist/plugin/request.d.ts +0 -110
- package/dist/plugin/request.js +0 -1489
- package/dist/plugin/rotation.d.ts +0 -182
- package/dist/plugin/rotation.js +0 -364
- package/dist/plugin/search.d.ts +0 -31
- package/dist/plugin/search.js +0 -185
- package/dist/plugin/server.d.ts +0 -22
- package/dist/plugin/server.js +0 -306
- package/dist/plugin/storage.d.ts +0 -136
- package/dist/plugin/storage.js +0 -599
- package/dist/plugin/stores/signature-store.d.ts +0 -4
- package/dist/plugin/stores/signature-store.js +0 -24
- package/dist/plugin/thinking-recovery.d.ts +0 -89
- package/dist/plugin/thinking-recovery.js +0 -289
- package/dist/plugin/token.d.ts +0 -18
- package/dist/plugin/token.js +0 -127
- package/dist/plugin/transform/claude.d.ts +0 -79
- package/dist/plugin/transform/claude.js +0 -256
- package/dist/plugin/transform/cross-model-sanitizer.d.ts +0 -34
- package/dist/plugin/transform/cross-model-sanitizer.js +0 -224
- package/dist/plugin/transform/gemini.d.ts +0 -132
- package/dist/plugin/transform/gemini.js +0 -659
- package/dist/plugin/transform/index.d.ts +0 -14
- package/dist/plugin/transform/index.js +0 -9
- package/dist/plugin/transform/model-resolver.d.ts +0 -98
- package/dist/plugin/transform/model-resolver.js +0 -320
- package/dist/plugin/transform/types.d.ts +0 -110
- package/dist/plugin/transform/types.js +0 -1
- package/dist/plugin/types.d.ts +0 -95
- package/dist/plugin/types.js +0 -1
- package/dist/plugin/ui/ansi.d.ts +0 -31
- package/dist/plugin/ui/ansi.js +0 -45
- package/dist/plugin/ui/auth-menu.d.ts +0 -47
- package/dist/plugin/ui/auth-menu.js +0 -199
- package/dist/plugin/ui/confirm.d.ts +0 -1
- package/dist/plugin/ui/confirm.js +0 -14
- package/dist/plugin/ui/select.d.ts +0 -22
- package/dist/plugin/ui/select.js +0 -243
- package/dist/plugin/version.d.ts +0 -18
- package/dist/plugin/version.js +0 -79
- package/dist/src/antigravity/oauth.d.ts +0 -30
- package/dist/src/antigravity/oauth.js +0 -170
- package/dist/src/constants.d.ts +0 -138
- package/dist/src/constants.js +0 -216
- package/dist/src/hooks/auto-update-checker/cache.d.ts +0 -2
- package/dist/src/hooks/auto-update-checker/cache.js +0 -70
- package/dist/src/hooks/auto-update-checker/checker.d.ts +0 -15
- package/dist/src/hooks/auto-update-checker/checker.js +0 -233
- package/dist/src/hooks/auto-update-checker/constants.d.ts +0 -8
- package/dist/src/hooks/auto-update-checker/constants.js +0 -22
- package/dist/src/hooks/auto-update-checker/index.d.ts +0 -33
- package/dist/src/hooks/auto-update-checker/index.js +0 -121
- package/dist/src/hooks/auto-update-checker/logging.d.ts +0 -2
- package/dist/src/hooks/auto-update-checker/logging.js +0 -8
- package/dist/src/hooks/auto-update-checker/types.d.ts +0 -24
- package/dist/src/hooks/auto-update-checker/types.js +0 -1
- package/dist/src/index.d.ts +0 -6
- package/dist/src/index.js +0 -5
- package/dist/src/plugin/accounts.d.ts +0 -173
- package/dist/src/plugin/accounts.js +0 -966
- package/dist/src/plugin/auth.d.ts +0 -20
- package/dist/src/plugin/auth.js +0 -44
- package/dist/src/plugin/cache/index.d.ts +0 -4
- package/dist/src/plugin/cache/index.js +0 -4
- package/dist/src/plugin/cache/signature-cache.d.ts +0 -110
- package/dist/src/plugin/cache/signature-cache.js +0 -347
- package/dist/src/plugin/cache.d.ts +0 -43
- package/dist/src/plugin/cache.js +0 -180
- package/dist/src/plugin/cli.d.ts +0 -26
- package/dist/src/plugin/cli.js +0 -126
- package/dist/src/plugin/config/index.d.ts +0 -15
- package/dist/src/plugin/config/index.js +0 -15
- package/dist/src/plugin/config/loader.d.ts +0 -38
- package/dist/src/plugin/config/loader.js +0 -150
- package/dist/src/plugin/config/models.d.ts +0 -26
- package/dist/src/plugin/config/models.js +0 -95
- package/dist/src/plugin/config/schema.d.ts +0 -144
- package/dist/src/plugin/config/schema.js +0 -458
- package/dist/src/plugin/config/updater.d.ts +0 -76
- package/dist/src/plugin/config/updater.js +0 -205
- package/dist/src/plugin/core/streaming/index.d.ts +0 -2
- package/dist/src/plugin/core/streaming/index.js +0 -2
- package/dist/src/plugin/core/streaming/transformer.d.ts +0 -9
- package/dist/src/plugin/core/streaming/transformer.js +0 -301
- package/dist/src/plugin/core/streaming/types.d.ts +0 -28
- package/dist/src/plugin/core/streaming/types.js +0 -1
- package/dist/src/plugin/debug.d.ts +0 -93
- package/dist/src/plugin/debug.js +0 -375
- package/dist/src/plugin/errors.d.ts +0 -27
- package/dist/src/plugin/errors.js +0 -41
- package/dist/src/plugin/fingerprint.d.ts +0 -69
- package/dist/src/plugin/fingerprint.js +0 -137
- package/dist/src/plugin/image-saver.d.ts +0 -24
- package/dist/src/plugin/image-saver.js +0 -78
- package/dist/src/plugin/logger.d.ts +0 -35
- package/dist/src/plugin/logger.js +0 -67
- package/dist/src/plugin/logging-utils.d.ts +0 -22
- package/dist/src/plugin/logging-utils.js +0 -91
- package/dist/src/plugin/project.d.ts +0 -32
- package/dist/src/plugin/project.js +0 -229
- package/dist/src/plugin/quota.d.ts +0 -34
- package/dist/src/plugin/quota.js +0 -261
- package/dist/src/plugin/recovery/constants.d.ts +0 -21
- package/dist/src/plugin/recovery/constants.js +0 -42
- package/dist/src/plugin/recovery/index.d.ts +0 -11
- package/dist/src/plugin/recovery/index.js +0 -11
- package/dist/src/plugin/recovery/storage.d.ts +0 -23
- package/dist/src/plugin/recovery/storage.js +0 -340
- package/dist/src/plugin/recovery/types.d.ts +0 -115
- package/dist/src/plugin/recovery/types.js +0 -6
- package/dist/src/plugin/recovery.d.ts +0 -60
- package/dist/src/plugin/recovery.js +0 -360
- package/dist/src/plugin/refresh-queue.d.ts +0 -99
- package/dist/src/plugin/refresh-queue.js +0 -235
- package/dist/src/plugin/request-helpers.d.ts +0 -281
- package/dist/src/plugin/request-helpers.js +0 -2200
- package/dist/src/plugin/request.d.ts +0 -110
- package/dist/src/plugin/request.js +0 -1489
- package/dist/src/plugin/rotation.d.ts +0 -182
- package/dist/src/plugin/rotation.js +0 -364
- package/dist/src/plugin/search.d.ts +0 -31
- package/dist/src/plugin/search.js +0 -185
- package/dist/src/plugin/server.d.ts +0 -22
- package/dist/src/plugin/server.js +0 -306
- package/dist/src/plugin/storage.d.ts +0 -136
- package/dist/src/plugin/storage.js +0 -599
- package/dist/src/plugin/stores/signature-store.d.ts +0 -4
- package/dist/src/plugin/stores/signature-store.js +0 -24
- package/dist/src/plugin/thinking-recovery.d.ts +0 -89
- package/dist/src/plugin/thinking-recovery.js +0 -289
- package/dist/src/plugin/token.d.ts +0 -18
- package/dist/src/plugin/token.js +0 -127
- package/dist/src/plugin/transform/claude.d.ts +0 -79
- package/dist/src/plugin/transform/claude.js +0 -256
- package/dist/src/plugin/transform/cross-model-sanitizer.d.ts +0 -34
- package/dist/src/plugin/transform/cross-model-sanitizer.js +0 -224
- package/dist/src/plugin/transform/gemini.d.ts +0 -132
- package/dist/src/plugin/transform/gemini.js +0 -659
- package/dist/src/plugin/transform/index.d.ts +0 -14
- package/dist/src/plugin/transform/index.js +0 -9
- package/dist/src/plugin/transform/model-resolver.d.ts +0 -98
- package/dist/src/plugin/transform/model-resolver.js +0 -320
- package/dist/src/plugin/transform/types.d.ts +0 -110
- package/dist/src/plugin/transform/types.js +0 -1
- package/dist/src/plugin/types.d.ts +0 -95
- package/dist/src/plugin/types.js +0 -1
- package/dist/src/plugin/ui/ansi.d.ts +0 -31
- package/dist/src/plugin/ui/ansi.js +0 -45
- package/dist/src/plugin/ui/auth-menu.d.ts +0 -47
- package/dist/src/plugin/ui/auth-menu.js +0 -199
- package/dist/src/plugin/ui/confirm.d.ts +0 -1
- package/dist/src/plugin/ui/confirm.js +0 -14
- package/dist/src/plugin/ui/select.d.ts +0 -22
- package/dist/src/plugin/ui/select.js +0 -243
- package/dist/src/plugin/version.d.ts +0 -18
- package/dist/src/plugin/version.js +0 -79
|
@@ -1,659 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Gemini-specific Request Transformations
|
|
3
|
-
*
|
|
4
|
-
* Handles Gemini model-specific request transformations including:
|
|
5
|
-
* - Thinking config (camelCase keys, thinkingLevel for Gemini 3)
|
|
6
|
-
* - Tool normalization (function/custom format)
|
|
7
|
-
* - Schema transformation (JSON Schema -> Gemini Schema format)
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* Transform a JSON Schema to Gemini-compatible format.
|
|
11
|
-
* Based on @google/genai SDK's processJsonSchema() function.
|
|
12
|
-
*
|
|
13
|
-
* Key transformations:
|
|
14
|
-
* - Converts type values to uppercase (object -> OBJECT)
|
|
15
|
-
* - Removes unsupported fields like additionalProperties, $schema
|
|
16
|
-
* - Recursively processes nested schemas (properties, items, anyOf, etc.)
|
|
17
|
-
*
|
|
18
|
-
* @param schema - A JSON Schema object or primitive value
|
|
19
|
-
* @returns Gemini-compatible schema
|
|
20
|
-
*
|
|
21
|
-
* Fields that Gemini API rejects and must be removed from schemas.
|
|
22
|
-
* Antigravity uses strict protobuf-backed JSON validation.
|
|
23
|
-
*/
|
|
24
|
-
const UNSUPPORTED_SCHEMA_FIELDS = new Set([
|
|
25
|
-
"additionalProperties",
|
|
26
|
-
"$schema",
|
|
27
|
-
"$id",
|
|
28
|
-
"$comment",
|
|
29
|
-
"$ref",
|
|
30
|
-
"$defs",
|
|
31
|
-
"definitions",
|
|
32
|
-
"const",
|
|
33
|
-
"contentMediaType",
|
|
34
|
-
"contentEncoding",
|
|
35
|
-
"if",
|
|
36
|
-
"then",
|
|
37
|
-
"else",
|
|
38
|
-
"not",
|
|
39
|
-
"patternProperties",
|
|
40
|
-
"unevaluatedProperties",
|
|
41
|
-
"unevaluatedItems",
|
|
42
|
-
"dependentRequired",
|
|
43
|
-
"dependentSchemas",
|
|
44
|
-
"propertyNames",
|
|
45
|
-
"minContains",
|
|
46
|
-
"maxContains",
|
|
47
|
-
]);
|
|
48
|
-
export function toGeminiSchema(schema) {
|
|
49
|
-
if (!schema || typeof schema !== "object" || Array.isArray(schema)) {
|
|
50
|
-
return schema;
|
|
51
|
-
}
|
|
52
|
-
const inputSchema = schema;
|
|
53
|
-
const result = {};
|
|
54
|
-
const propertyNames = new Set();
|
|
55
|
-
if (inputSchema.properties && typeof inputSchema.properties === "object") {
|
|
56
|
-
for (const propName of Object.keys(inputSchema.properties)) {
|
|
57
|
-
propertyNames.add(propName);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
for (const [key, value] of Object.entries(inputSchema)) {
|
|
61
|
-
if (UNSUPPORTED_SCHEMA_FIELDS.has(key)) {
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
if (key === "type" && typeof value === "string") {
|
|
65
|
-
result[key] = value.toUpperCase();
|
|
66
|
-
}
|
|
67
|
-
else if (key === "properties" && typeof value === "object" && value !== null) {
|
|
68
|
-
const props = {};
|
|
69
|
-
for (const [propName, propSchema] of Object.entries(value)) {
|
|
70
|
-
props[propName] = toGeminiSchema(propSchema);
|
|
71
|
-
}
|
|
72
|
-
result[key] = props;
|
|
73
|
-
}
|
|
74
|
-
else if (key === "items" && typeof value === "object") {
|
|
75
|
-
result[key] = toGeminiSchema(value);
|
|
76
|
-
}
|
|
77
|
-
else if ((key === "anyOf" || key === "oneOf" || key === "allOf") && Array.isArray(value)) {
|
|
78
|
-
result[key] = value.map((item) => toGeminiSchema(item));
|
|
79
|
-
}
|
|
80
|
-
else if (key === "enum" && Array.isArray(value)) {
|
|
81
|
-
result[key] = value;
|
|
82
|
-
}
|
|
83
|
-
else if (key === "default" || key === "examples") {
|
|
84
|
-
result[key] = value;
|
|
85
|
-
}
|
|
86
|
-
else if (key === "required" && Array.isArray(value)) {
|
|
87
|
-
if (propertyNames.size > 0) {
|
|
88
|
-
const validRequired = value.filter((prop) => typeof prop === "string" && propertyNames.has(prop));
|
|
89
|
-
if (validRequired.length > 0) {
|
|
90
|
-
result[key] = validRequired;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
result[key] = value;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
result[key] = value;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
if (result.type === "ARRAY" && !result.items) {
|
|
102
|
-
result.items = { type: "STRING" };
|
|
103
|
-
}
|
|
104
|
-
return result;
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Check if a model is a Gemini model (not Claude).
|
|
108
|
-
*/
|
|
109
|
-
export function isGeminiModel(model) {
|
|
110
|
-
const lower = model.toLowerCase();
|
|
111
|
-
return lower.includes("gemini") && !lower.includes("claude");
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Check if a model is Gemini 3 (uses thinkingLevel string).
|
|
115
|
-
*/
|
|
116
|
-
export function isGemini3Model(model) {
|
|
117
|
-
return model.toLowerCase().includes("gemini-3");
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Check if a model is Gemini 2.5 (uses numeric thinkingBudget).
|
|
121
|
-
*/
|
|
122
|
-
export function isGemini25Model(model) {
|
|
123
|
-
return model.toLowerCase().includes("gemini-2.5");
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* Check if a model is an image generation model.
|
|
127
|
-
* Image models don't support thinking and require imageConfig.
|
|
128
|
-
*/
|
|
129
|
-
export function isImageGenerationModel(model) {
|
|
130
|
-
const lower = model.toLowerCase();
|
|
131
|
-
return (lower.includes("image") ||
|
|
132
|
-
lower.includes("imagen"));
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* Build Gemini 3 thinking config with thinkingLevel string.
|
|
136
|
-
*/
|
|
137
|
-
export function buildGemini3ThinkingConfig(includeThoughts, thinkingLevel) {
|
|
138
|
-
return {
|
|
139
|
-
includeThoughts,
|
|
140
|
-
thinkingLevel,
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Build Gemini 2.5 thinking config with numeric thinkingBudget.
|
|
145
|
-
*/
|
|
146
|
-
export function buildGemini25ThinkingConfig(includeThoughts, thinkingBudget) {
|
|
147
|
-
return {
|
|
148
|
-
includeThoughts,
|
|
149
|
-
...(typeof thinkingBudget === "number" && thinkingBudget > 0 ? { thinkingBudget } : {}),
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* Valid aspect ratios for image generation.
|
|
154
|
-
*/
|
|
155
|
-
const VALID_ASPECT_RATIOS = ["1:1", "2:3", "3:2", "3:4", "4:3", "4:5", "5:4", "9:16", "16:9", "21:9"];
|
|
156
|
-
/**
|
|
157
|
-
* Build image generation config for Gemini image models.
|
|
158
|
-
*
|
|
159
|
-
* Configuration is read from environment variables:
|
|
160
|
-
* - OPENCODE_IMAGE_ASPECT_RATIO: Aspect ratio (e.g., "16:9", "4:3")
|
|
161
|
-
*
|
|
162
|
-
* Defaults to 1:1 aspect ratio if not specified.
|
|
163
|
-
*
|
|
164
|
-
* Note: Resolution setting is not currently supported by the Antigravity API.
|
|
165
|
-
*/
|
|
166
|
-
export function buildImageGenerationConfig() {
|
|
167
|
-
const aspectRatio = process.env.OPENCODE_IMAGE_ASPECT_RATIO || "1:1";
|
|
168
|
-
if (VALID_ASPECT_RATIOS.includes(aspectRatio)) {
|
|
169
|
-
return { aspectRatio };
|
|
170
|
-
}
|
|
171
|
-
console.warn(`[gemini] Invalid aspect ratio "${aspectRatio}". Using default "1:1". Valid values: ${VALID_ASPECT_RATIOS.join(", ")}`);
|
|
172
|
-
return { aspectRatio: "1:1" };
|
|
173
|
-
}
|
|
174
|
-
/**
|
|
175
|
-
* Normalize tools for Gemini models.
|
|
176
|
-
* Ensures tools have proper function-style format.
|
|
177
|
-
*
|
|
178
|
-
* @returns Debug info about tool normalization
|
|
179
|
-
*/
|
|
180
|
-
export function normalizeGeminiTools(payload) {
|
|
181
|
-
let toolDebugMissing = 0;
|
|
182
|
-
const toolDebugSummaries = [];
|
|
183
|
-
if (!Array.isArray(payload.tools)) {
|
|
184
|
-
return { toolDebugMissing, toolDebugSummaries };
|
|
185
|
-
}
|
|
186
|
-
payload.tools = payload.tools.map((tool, toolIndex) => {
|
|
187
|
-
const t = tool;
|
|
188
|
-
if (t.googleSearch || t.googleSearchRetrieval) {
|
|
189
|
-
return t;
|
|
190
|
-
}
|
|
191
|
-
const newTool = { ...t };
|
|
192
|
-
const schemaCandidates = [
|
|
193
|
-
newTool.function?.input_schema,
|
|
194
|
-
newTool.function?.parameters,
|
|
195
|
-
newTool.function?.inputSchema,
|
|
196
|
-
newTool.custom?.input_schema,
|
|
197
|
-
newTool.custom?.parameters,
|
|
198
|
-
newTool.parameters,
|
|
199
|
-
newTool.input_schema,
|
|
200
|
-
newTool.inputSchema,
|
|
201
|
-
].filter(Boolean);
|
|
202
|
-
const placeholderSchema = {
|
|
203
|
-
type: "OBJECT",
|
|
204
|
-
properties: {
|
|
205
|
-
_placeholder: {
|
|
206
|
-
type: "BOOLEAN",
|
|
207
|
-
description: "Placeholder. Always pass true.",
|
|
208
|
-
},
|
|
209
|
-
},
|
|
210
|
-
required: ["_placeholder"],
|
|
211
|
-
};
|
|
212
|
-
let schema = schemaCandidates[0];
|
|
213
|
-
const schemaObjectOk = schema && typeof schema === "object" && !Array.isArray(schema);
|
|
214
|
-
if (!schemaObjectOk) {
|
|
215
|
-
schema = placeholderSchema;
|
|
216
|
-
toolDebugMissing += 1;
|
|
217
|
-
}
|
|
218
|
-
else {
|
|
219
|
-
schema = toGeminiSchema(schema);
|
|
220
|
-
}
|
|
221
|
-
const nameCandidate = newTool.name ||
|
|
222
|
-
newTool.function?.name ||
|
|
223
|
-
newTool.custom?.name ||
|
|
224
|
-
`tool-${toolIndex}`;
|
|
225
|
-
// Always update function.input_schema with transformed schema
|
|
226
|
-
if (newTool.function && schema) {
|
|
227
|
-
newTool.function.input_schema = schema;
|
|
228
|
-
}
|
|
229
|
-
// Always update custom.input_schema with transformed schema
|
|
230
|
-
if (newTool.custom && schema) {
|
|
231
|
-
newTool.custom.input_schema = schema;
|
|
232
|
-
}
|
|
233
|
-
if (!newTool.custom && newTool.function) {
|
|
234
|
-
const fn = newTool.function;
|
|
235
|
-
newTool.custom = {
|
|
236
|
-
name: fn.name || nameCandidate,
|
|
237
|
-
description: fn.description,
|
|
238
|
-
input_schema: schema,
|
|
239
|
-
};
|
|
240
|
-
}
|
|
241
|
-
if (!newTool.custom && !newTool.function) {
|
|
242
|
-
newTool.custom = {
|
|
243
|
-
name: nameCandidate,
|
|
244
|
-
description: newTool.description,
|
|
245
|
-
input_schema: schema,
|
|
246
|
-
};
|
|
247
|
-
if (!newTool.parameters && !newTool.input_schema && !newTool.inputSchema) {
|
|
248
|
-
newTool.parameters = schema;
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
if (newTool.custom && !newTool.custom.input_schema) {
|
|
252
|
-
newTool.custom.input_schema = {
|
|
253
|
-
type: "OBJECT",
|
|
254
|
-
properties: {},
|
|
255
|
-
};
|
|
256
|
-
toolDebugMissing += 1;
|
|
257
|
-
}
|
|
258
|
-
toolDebugSummaries.push(`idx=${toolIndex}, hasCustom=${!!newTool.custom}, customSchema=${!!newTool.custom?.input_schema}, hasFunction=${!!newTool.function}, functionSchema=${!!newTool.function?.input_schema}`);
|
|
259
|
-
if (newTool.custom) {
|
|
260
|
-
delete newTool.custom;
|
|
261
|
-
}
|
|
262
|
-
return newTool;
|
|
263
|
-
});
|
|
264
|
-
return { toolDebugMissing, toolDebugSummaries };
|
|
265
|
-
}
|
|
266
|
-
/**
|
|
267
|
-
* Apply all Gemini-specific transformations.
|
|
268
|
-
*/
|
|
269
|
-
export function applyGeminiTransforms(payload, options) {
|
|
270
|
-
const { model, tierThinkingBudget, tierThinkingLevel, normalizedThinking, googleSearch } = options;
|
|
271
|
-
// 1. Apply thinking config if needed
|
|
272
|
-
if (normalizedThinking) {
|
|
273
|
-
let thinkingConfig;
|
|
274
|
-
if (tierThinkingLevel && isGemini3Model(model)) {
|
|
275
|
-
thinkingConfig = buildGemini3ThinkingConfig(normalizedThinking.includeThoughts ?? true, tierThinkingLevel);
|
|
276
|
-
}
|
|
277
|
-
else {
|
|
278
|
-
const thinkingBudget = tierThinkingBudget ?? normalizedThinking.thinkingBudget;
|
|
279
|
-
thinkingConfig = buildGemini25ThinkingConfig(normalizedThinking.includeThoughts ?? true, thinkingBudget);
|
|
280
|
-
}
|
|
281
|
-
const generationConfig = (payload.generationConfig ?? {});
|
|
282
|
-
generationConfig.thinkingConfig = thinkingConfig;
|
|
283
|
-
payload.generationConfig = generationConfig;
|
|
284
|
-
}
|
|
285
|
-
// 2. Apply Google Search (Grounding) if enabled
|
|
286
|
-
if (googleSearch && googleSearch.mode === 'auto') {
|
|
287
|
-
const tools = payload.tools || [];
|
|
288
|
-
if (!payload.tools) {
|
|
289
|
-
payload.tools = tools;
|
|
290
|
-
}
|
|
291
|
-
payload.tools.push({
|
|
292
|
-
googleSearch: {},
|
|
293
|
-
});
|
|
294
|
-
}
|
|
295
|
-
// 3. Normalize tools
|
|
296
|
-
const result = normalizeGeminiTools(payload);
|
|
297
|
-
// 4. Wrap tools in functionDeclarations format (fixes #203, #206)
|
|
298
|
-
// Must be: [{ functionDeclarations: [{ name, description, parameters }] }]
|
|
299
|
-
const wrapResult = wrapToolsAsFunctionDeclarations(payload);
|
|
300
|
-
return {
|
|
301
|
-
...result,
|
|
302
|
-
wrappedFunctionCount: wrapResult.wrappedFunctionCount,
|
|
303
|
-
passthroughToolCount: wrapResult.passthroughToolCount,
|
|
304
|
-
};
|
|
305
|
-
}
|
|
306
|
-
/**
|
|
307
|
-
* Wrap tools array in Gemini's required functionDeclarations format.
|
|
308
|
-
*
|
|
309
|
-
* Gemini/Antigravity API expects:
|
|
310
|
-
* { tools: [{ functionDeclarations: [{ name, description, parameters }] }] }
|
|
311
|
-
*
|
|
312
|
-
* NOT:
|
|
313
|
-
* { tools: [{ function: {...}, parameters: {...} }] }
|
|
314
|
-
*
|
|
315
|
-
* The wrapper-level 'parameters' field causes:
|
|
316
|
-
* "Unknown name 'parameters' at 'request.tools[0]'"
|
|
317
|
-
*/
|
|
318
|
-
/**
|
|
319
|
-
* Detect if a tool is a web search tool in any of the supported formats:
|
|
320
|
-
* - Claude/Anthropic: { type: "web_search_20250305" } or { name: "web_search" }
|
|
321
|
-
* - Gemini native: { googleSearch: {} } or { googleSearchRetrieval: {} }
|
|
322
|
-
*/
|
|
323
|
-
function isWebSearchTool(tool) {
|
|
324
|
-
// 1. Gemini native format
|
|
325
|
-
if (tool.googleSearch || tool.googleSearchRetrieval) {
|
|
326
|
-
return true;
|
|
327
|
-
}
|
|
328
|
-
// 2. Claude/Anthropic format: { type: "web_search_20250305" }
|
|
329
|
-
if (tool.type === "web_search_20250305") {
|
|
330
|
-
return true;
|
|
331
|
-
}
|
|
332
|
-
// 3. Simple name-based format: { name: "web_search" | "google_search" }
|
|
333
|
-
const name = tool.name;
|
|
334
|
-
if (name === "web_search" || name === "google_search") {
|
|
335
|
-
return true;
|
|
336
|
-
}
|
|
337
|
-
return false;
|
|
338
|
-
}
|
|
339
|
-
export function wrapToolsAsFunctionDeclarations(payload) {
|
|
340
|
-
if (!Array.isArray(payload.tools) || payload.tools.length === 0) {
|
|
341
|
-
return { wrappedFunctionCount: 0, passthroughToolCount: 0 };
|
|
342
|
-
}
|
|
343
|
-
const functionDeclarations = [];
|
|
344
|
-
const passthroughTools = [];
|
|
345
|
-
let hasWebSearchTool = false;
|
|
346
|
-
for (const tool of payload.tools) {
|
|
347
|
-
if (tool.googleSearch || tool.googleSearchRetrieval || tool.codeExecution) {
|
|
348
|
-
passthroughTools.push(tool);
|
|
349
|
-
continue;
|
|
350
|
-
}
|
|
351
|
-
if (isWebSearchTool(tool)) {
|
|
352
|
-
hasWebSearchTool = true;
|
|
353
|
-
continue; // Will be added as { googleSearch: {} } at the end
|
|
354
|
-
}
|
|
355
|
-
if (tool.functionDeclarations) {
|
|
356
|
-
if (Array.isArray(tool.functionDeclarations)) {
|
|
357
|
-
for (const decl of tool.functionDeclarations) {
|
|
358
|
-
functionDeclarations.push({
|
|
359
|
-
name: String(decl.name || `tool-${functionDeclarations.length}`),
|
|
360
|
-
description: String(decl.description || ""),
|
|
361
|
-
parameters: decl.parameters || { type: "OBJECT", properties: {} },
|
|
362
|
-
});
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
continue;
|
|
366
|
-
}
|
|
367
|
-
const fn = tool.function;
|
|
368
|
-
const custom = tool.custom;
|
|
369
|
-
const name = String(tool.name ||
|
|
370
|
-
fn?.name ||
|
|
371
|
-
custom?.name ||
|
|
372
|
-
`tool-${functionDeclarations.length}`);
|
|
373
|
-
const description = String(tool.description ||
|
|
374
|
-
fn?.description ||
|
|
375
|
-
custom?.description ||
|
|
376
|
-
"");
|
|
377
|
-
const schema = (fn?.input_schema ||
|
|
378
|
-
fn?.parameters ||
|
|
379
|
-
fn?.inputSchema ||
|
|
380
|
-
custom?.input_schema ||
|
|
381
|
-
custom?.parameters ||
|
|
382
|
-
tool.parameters ||
|
|
383
|
-
tool.input_schema ||
|
|
384
|
-
tool.inputSchema ||
|
|
385
|
-
{ type: "OBJECT", properties: {} });
|
|
386
|
-
functionDeclarations.push({
|
|
387
|
-
name,
|
|
388
|
-
description,
|
|
389
|
-
parameters: schema,
|
|
390
|
-
});
|
|
391
|
-
}
|
|
392
|
-
const finalTools = [];
|
|
393
|
-
if (functionDeclarations.length > 0) {
|
|
394
|
-
finalTools.push({ functionDeclarations });
|
|
395
|
-
}
|
|
396
|
-
finalTools.push(...passthroughTools);
|
|
397
|
-
if (hasWebSearchTool && functionDeclarations.length === 0) {
|
|
398
|
-
finalTools.push({ googleSearch: {} });
|
|
399
|
-
}
|
|
400
|
-
else if (hasWebSearchTool && functionDeclarations.length > 0) {
|
|
401
|
-
console.warn("[gemini] web_search tool detected but cannot be combined with function declarations. " +
|
|
402
|
-
"Use the explicit google_search() tool call instead.");
|
|
403
|
-
}
|
|
404
|
-
payload.tools = finalTools;
|
|
405
|
-
return {
|
|
406
|
-
wrappedFunctionCount: functionDeclarations.length,
|
|
407
|
-
passthroughToolCount: passthroughTools.length + (hasWebSearchTool && functionDeclarations.length === 0 ? 1 : 0),
|
|
408
|
-
};
|
|
409
|
-
}
|
|
410
|
-
/**
|
|
411
|
-
* Separate parts into functionCall/functionResponse parts and other parts.
|
|
412
|
-
*/
|
|
413
|
-
function separateParts(parts) {
|
|
414
|
-
const functionCallParts = [];
|
|
415
|
-
const functionResponseParts = [];
|
|
416
|
-
const otherParts = [];
|
|
417
|
-
for (const part of parts) {
|
|
418
|
-
if (!part || typeof part !== "object") {
|
|
419
|
-
otherParts.push(part);
|
|
420
|
-
continue;
|
|
421
|
-
}
|
|
422
|
-
if (part.functionCall || part.function_call) {
|
|
423
|
-
functionCallParts.push(part);
|
|
424
|
-
}
|
|
425
|
-
else if (part.functionResponse || part.function_response) {
|
|
426
|
-
functionResponseParts.push(part);
|
|
427
|
-
}
|
|
428
|
-
else {
|
|
429
|
-
otherParts.push(part);
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
return { functionCallParts, functionResponseParts, otherParts };
|
|
433
|
-
}
|
|
434
|
-
/**
|
|
435
|
-
* Some Gemini / Antigravity backends reject a single model turn that contains
|
|
436
|
-
* multiple parallel functionCall parts, even when the following user turn has
|
|
437
|
-
* matching functionResponses. Expand to strict call → response → call → response.
|
|
438
|
-
*/
|
|
439
|
-
export function expandMultiFunctionCallModelTurns(contents) {
|
|
440
|
-
if (!Array.isArray(contents) || contents.length === 0) {
|
|
441
|
-
return contents;
|
|
442
|
-
}
|
|
443
|
-
const result = [];
|
|
444
|
-
for (let i = 0; i < contents.length; i++) {
|
|
445
|
-
const turn = contents[i];
|
|
446
|
-
if (!turn || typeof turn !== "object" || turn.role !== "model" || !Array.isArray(turn.parts)) {
|
|
447
|
-
result.push(turn);
|
|
448
|
-
continue;
|
|
449
|
-
}
|
|
450
|
-
const fcParts = turn.parts.filter((p) => p && typeof p === "object" && (p.functionCall || p.function_call));
|
|
451
|
-
if (fcParts.length <= 1) {
|
|
452
|
-
result.push(turn);
|
|
453
|
-
continue;
|
|
454
|
-
}
|
|
455
|
-
const next = contents[i + 1];
|
|
456
|
-
if (!next || next.role !== "user" || !Array.isArray(next.parts)) {
|
|
457
|
-
result.push(turn);
|
|
458
|
-
continue;
|
|
459
|
-
}
|
|
460
|
-
const frParts = next.parts.filter((p) => p && typeof p === "object" && (p.functionResponse || p.function_response));
|
|
461
|
-
if (frParts.length !== fcParts.length) {
|
|
462
|
-
result.push(turn);
|
|
463
|
-
continue;
|
|
464
|
-
}
|
|
465
|
-
const otherParts = turn.parts.filter((p) => !(p && typeof p === "object" && (p.functionCall || p.function_call)));
|
|
466
|
-
for (let j = 0; j < fcParts.length; j++) {
|
|
467
|
-
const modelParts = j === 0 && otherParts.length > 0 ? [...otherParts, fcParts[j]] : [fcParts[j]];
|
|
468
|
-
result.push({ ...turn, role: "model", parts: modelParts });
|
|
469
|
-
result.push({ role: "user", parts: [frParts[j]] });
|
|
470
|
-
}
|
|
471
|
-
i++;
|
|
472
|
-
}
|
|
473
|
-
return result;
|
|
474
|
-
}
|
|
475
|
-
/**
|
|
476
|
-
* Sanitize Gemini conversation contents to enforce strict turn ordering.
|
|
477
|
-
*
|
|
478
|
-
* Gemini API rules:
|
|
479
|
-
* 1. Strict user/model alternation (no consecutive same-role turns)
|
|
480
|
-
* 2. functionCall parts must be in "model" role turns
|
|
481
|
-
* 3. functionResponse parts must be in "user" role turns
|
|
482
|
-
* 4. Conversation must start with "user"
|
|
483
|
-
* 5. A function_call turn must come immediately after a user turn or
|
|
484
|
-
* after a function_response turn
|
|
485
|
-
*
|
|
486
|
-
* This function:
|
|
487
|
-
* - Normalizes roles ("assistant" to "model")
|
|
488
|
-
* - Moves misplaced functionCall/functionResponse parts to correct roles
|
|
489
|
-
* - Merges consecutive same-role turns
|
|
490
|
-
* - Inserts empty filler turns to maintain alternation
|
|
491
|
-
* - Ensures conversation starts with "user"
|
|
492
|
-
*/
|
|
493
|
-
export function sanitizeGeminiContents(contents) {
|
|
494
|
-
if (!Array.isArray(contents) || contents.length === 0) {
|
|
495
|
-
return contents;
|
|
496
|
-
}
|
|
497
|
-
contents = expandMultiFunctionCallModelTurns(contents);
|
|
498
|
-
const mergeTextParts = (parts) => {
|
|
499
|
-
const merged = [];
|
|
500
|
-
let currentText = "";
|
|
501
|
-
for (const part of parts) {
|
|
502
|
-
if (part && typeof part.text === "string") {
|
|
503
|
-
currentText += (currentText ? "\n\n" : "") + part.text;
|
|
504
|
-
}
|
|
505
|
-
else {
|
|
506
|
-
if (currentText) {
|
|
507
|
-
merged.push({ text: currentText });
|
|
508
|
-
currentText = "";
|
|
509
|
-
}
|
|
510
|
-
merged.push(part);
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
if (currentText) {
|
|
514
|
-
merged.push({ text: currentText });
|
|
515
|
-
}
|
|
516
|
-
return merged;
|
|
517
|
-
};
|
|
518
|
-
const normalized = [];
|
|
519
|
-
for (const content of contents) {
|
|
520
|
-
if (!content || typeof content !== "object")
|
|
521
|
-
continue;
|
|
522
|
-
let role = content.role;
|
|
523
|
-
const parts = Array.isArray(content.parts) ? mergeTextParts([...content.parts]) : [];
|
|
524
|
-
if (parts.length === 0)
|
|
525
|
-
continue;
|
|
526
|
-
if (role === "assistant") {
|
|
527
|
-
role = "model";
|
|
528
|
-
}
|
|
529
|
-
const { functionCallParts, functionResponseParts, otherParts } = separateParts(parts);
|
|
530
|
-
if (role === "model") {
|
|
531
|
-
const modelParts = [...otherParts, ...functionCallParts];
|
|
532
|
-
if (modelParts.length > 0) {
|
|
533
|
-
normalized.push({ ...content, role: "model", parts: modelParts });
|
|
534
|
-
}
|
|
535
|
-
if (functionResponseParts.length > 0) {
|
|
536
|
-
normalized.push({ role: "user", parts: functionResponseParts });
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
else {
|
|
540
|
-
if (functionCallParts.length > 0) {
|
|
541
|
-
normalized.push({ role: "model", parts: functionCallParts });
|
|
542
|
-
}
|
|
543
|
-
if (functionResponseParts.length > 0) {
|
|
544
|
-
normalized.push({ role: "user", parts: functionResponseParts });
|
|
545
|
-
}
|
|
546
|
-
if (otherParts.length > 0) {
|
|
547
|
-
normalized.push({ ...content, role: "user", parts: otherParts });
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
if (normalized.length === 0) {
|
|
552
|
-
return contents;
|
|
553
|
-
}
|
|
554
|
-
const merged = [normalized[0]];
|
|
555
|
-
for (let i = 1; i < normalized.length; i++) {
|
|
556
|
-
const current = normalized[i];
|
|
557
|
-
const previous = merged[merged.length - 1];
|
|
558
|
-
const hasFunc = (parts) => parts.some(p => p.functionCall || p.functionResponse || p.function_call || p.function_response);
|
|
559
|
-
const prevFunc = hasFunc(previous.parts);
|
|
560
|
-
const currFunc = hasFunc(current.parts);
|
|
561
|
-
if (current.role === previous.role && prevFunc === currFunc) {
|
|
562
|
-
previous.parts = [...previous.parts, ...current.parts];
|
|
563
|
-
}
|
|
564
|
-
else {
|
|
565
|
-
merged.push(current);
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
if (merged[0].role !== "user") {
|
|
569
|
-
merged.unshift({ role: "user", parts: [{ text: "acknowledged" }] });
|
|
570
|
-
}
|
|
571
|
-
const result = [merged[0]];
|
|
572
|
-
for (let i = 1; i < merged.length; i++) {
|
|
573
|
-
const current = merged[i];
|
|
574
|
-
const previous = result[result.length - 1];
|
|
575
|
-
if (current.role === previous.role) {
|
|
576
|
-
const fillerRole = current.role === "model" ? "user" : "model";
|
|
577
|
-
result.push({ role: fillerRole, parts: [{ text: "acknowledged" }] });
|
|
578
|
-
}
|
|
579
|
-
result.push(current);
|
|
580
|
-
}
|
|
581
|
-
return result.map(turn => ({
|
|
582
|
-
...turn,
|
|
583
|
-
parts: mergeTextParts(turn.parts)
|
|
584
|
-
}));
|
|
585
|
-
}
|
|
586
|
-
/**
|
|
587
|
-
* Fix Gemini tool call/response pairing.
|
|
588
|
-
*
|
|
589
|
-
* Ensures every functionCall in a model turn has a matching functionResponse
|
|
590
|
-
* in the immediately following user turn. If not, injects a placeholder
|
|
591
|
-
* response to prevent the API from rejecting the request.
|
|
592
|
-
*/
|
|
593
|
-
export function fixGeminiToolPairing(contents) {
|
|
594
|
-
if (!Array.isArray(contents) || contents.length === 0) {
|
|
595
|
-
return contents;
|
|
596
|
-
}
|
|
597
|
-
const result = contents.map((c) => ({
|
|
598
|
-
...c,
|
|
599
|
-
parts: Array.isArray(c.parts) ? [...c.parts] : [],
|
|
600
|
-
}));
|
|
601
|
-
const callsByModelIdx = new Map();
|
|
602
|
-
for (let i = 0; i < result.length; i++) {
|
|
603
|
-
const turn = result[i];
|
|
604
|
-
if (turn.role !== "model")
|
|
605
|
-
continue;
|
|
606
|
-
const calls = [];
|
|
607
|
-
for (const part of turn.parts) {
|
|
608
|
-
const fc = part?.functionCall || part?.function_call;
|
|
609
|
-
if (!fc)
|
|
610
|
-
continue;
|
|
611
|
-
calls.push({ name: fc.name || "unknown", id: fc.id || undefined });
|
|
612
|
-
}
|
|
613
|
-
if (calls.length > 0) {
|
|
614
|
-
callsByModelIdx.set(i, calls);
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
for (const [modelIdx, calls] of callsByModelIdx.entries()) {
|
|
618
|
-
const nextIdx = modelIdx + 1;
|
|
619
|
-
if (nextIdx >= result.length) {
|
|
620
|
-
const responseParts = calls.map((call) => ({
|
|
621
|
-
functionResponse: {
|
|
622
|
-
name: call.name,
|
|
623
|
-
...(call.id ? { id: call.id } : {}),
|
|
624
|
-
response: { result: "[pending]" },
|
|
625
|
-
},
|
|
626
|
-
}));
|
|
627
|
-
result.push({ role: "user", parts: responseParts });
|
|
628
|
-
continue;
|
|
629
|
-
}
|
|
630
|
-
const nextTurn = result[nextIdx];
|
|
631
|
-
if (nextTurn.role !== "user")
|
|
632
|
-
continue;
|
|
633
|
-
const existingResponseNames = new Set();
|
|
634
|
-
const existingResponseIds = new Set();
|
|
635
|
-
for (const part of nextTurn.parts) {
|
|
636
|
-
const fr = part?.functionResponse || part?.function_response;
|
|
637
|
-
if (!fr)
|
|
638
|
-
continue;
|
|
639
|
-
if (fr.name)
|
|
640
|
-
existingResponseNames.add(fr.name);
|
|
641
|
-
if (fr.id)
|
|
642
|
-
existingResponseIds.add(fr.id);
|
|
643
|
-
}
|
|
644
|
-
for (const call of calls) {
|
|
645
|
-
const hasMatchById = call.id && existingResponseIds.has(call.id);
|
|
646
|
-
const hasMatchByName = existingResponseNames.has(call.name);
|
|
647
|
-
if (!hasMatchById && !hasMatchByName) {
|
|
648
|
-
nextTurn.parts.push({
|
|
649
|
-
functionResponse: {
|
|
650
|
-
name: call.name,
|
|
651
|
-
...(call.id ? { id: call.id } : {}),
|
|
652
|
-
response: { result: "[no response received]" },
|
|
653
|
-
},
|
|
654
|
-
});
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
return result;
|
|
659
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Transform Module Index
|
|
3
|
-
*
|
|
4
|
-
* Re-exports transform functions and types for request transformation.
|
|
5
|
-
*/
|
|
6
|
-
export type { ModelFamily, ThinkingTier, TransformContext, TransformResult, TransformDebugInfo, RequestPayload, ThinkingConfig, ResolvedModel, GoogleSearchConfig, } from "./types";
|
|
7
|
-
export { resolveModelWithTier, resolveModelWithVariant, resolveModelForHeaderStyle, getModelFamily, MODEL_ALIASES, THINKING_TIER_BUDGETS, GEMINI_3_THINKING_LEVELS, } from "./model-resolver";
|
|
8
|
-
export type { VariantConfig } from "./model-resolver";
|
|
9
|
-
export { isClaudeModel, isClaudeThinkingModel, configureClaudeToolConfig, buildClaudeThinkingConfig, ensureClaudeMaxOutputTokens, appendClaudeThinkingHint, normalizeClaudeTools, applyClaudeTransforms, CLAUDE_THINKING_MAX_OUTPUT_TOKENS, CLAUDE_INTERLEAVED_THINKING_HINT, } from "./claude";
|
|
10
|
-
export type { ClaudeTransformOptions, ClaudeTransformResult } from "./claude";
|
|
11
|
-
export { isGeminiModel, isGemini3Model, isGemini25Model, isImageGenerationModel, buildGemini3ThinkingConfig, buildGemini25ThinkingConfig, buildImageGenerationConfig, normalizeGeminiTools, applyGeminiTransforms, sanitizeGeminiContents, fixGeminiToolPairing, expandMultiFunctionCallModelTurns, } from "./gemini";
|
|
12
|
-
export type { GeminiTransformOptions, GeminiTransformResult, ImageConfig } from "./gemini";
|
|
13
|
-
export { sanitizeCrossModelPayload, sanitizeCrossModelPayloadInPlace, getModelFamily as getCrossModelFamily, stripGeminiThinkingMetadata, stripClaudeThinkingFields, } from "./cross-model-sanitizer";
|
|
14
|
-
export type { SanitizerOptions } from "./cross-model-sanitizer";
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Transform Module Index
|
|
3
|
-
*
|
|
4
|
-
* Re-exports transform functions and types for request transformation.
|
|
5
|
-
*/
|
|
6
|
-
export { resolveModelWithTier, resolveModelWithVariant, resolveModelForHeaderStyle, getModelFamily, MODEL_ALIASES, THINKING_TIER_BUDGETS, GEMINI_3_THINKING_LEVELS, } from "./model-resolver";
|
|
7
|
-
export { isClaudeModel, isClaudeThinkingModel, configureClaudeToolConfig, buildClaudeThinkingConfig, ensureClaudeMaxOutputTokens, appendClaudeThinkingHint, normalizeClaudeTools, applyClaudeTransforms, CLAUDE_THINKING_MAX_OUTPUT_TOKENS, CLAUDE_INTERLEAVED_THINKING_HINT, } from "./claude";
|
|
8
|
-
export { isGeminiModel, isGemini3Model, isGemini25Model, isImageGenerationModel, buildGemini3ThinkingConfig, buildGemini25ThinkingConfig, buildImageGenerationConfig, normalizeGeminiTools, applyGeminiTransforms, sanitizeGeminiContents, fixGeminiToolPairing, expandMultiFunctionCallModelTurns, } from "./gemini";
|
|
9
|
-
export { sanitizeCrossModelPayload, sanitizeCrossModelPayloadInPlace, getModelFamily as getCrossModelFamily, stripGeminiThinkingMetadata, stripClaudeThinkingFields, } from "./cross-model-sanitizer";
|