Merge pull request #135 from weijiafu14/fix/gemini-thought-signature-tool-calls
fix: inject thoughtSignature into functionCall parts for OpenAI→Gemini conversion
This commit is contained in:
Generated
+18
-29
@@ -226,7 +226,6 @@
|
|||||||
"integrity": "sha512-Nt9hri7nbOo0RipAsGjIssHkpLMHHN/P7QqENywAq5TLsoYDzUyJGny8FEiD/9KJUxtGH8blGpMedilI6kK3rA==",
|
"integrity": "sha512-Nt9hri7nbOo0RipAsGjIssHkpLMHHN/P7QqENywAq5TLsoYDzUyJGny8FEiD/9KJUxtGH8blGpMedilI6kK3rA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@algolia/client-common": "5.49.1",
|
"@algolia/client-common": "5.49.1",
|
||||||
"@algolia/requester-browser-xhr": "5.49.1",
|
"@algolia/requester-browser-xhr": "5.49.1",
|
||||||
@@ -379,7 +378,6 @@
|
|||||||
"integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
|
"integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.29.0",
|
"@babel/code-frame": "^7.29.0",
|
||||||
"@babel/generator": "^7.29.0",
|
"@babel/generator": "^7.29.0",
|
||||||
@@ -706,7 +704,6 @@
|
|||||||
"integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==",
|
"integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fast-deep-equal": "^3.1.1",
|
"fast-deep-equal": "^3.1.1",
|
||||||
"fast-json-stable-stringify": "^2.0.0",
|
"fast-json-stable-stringify": "^2.0.0",
|
||||||
@@ -752,7 +749,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz",
|
||||||
"integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==",
|
"integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@dnd-kit/accessibility": "^3.1.1",
|
"@dnd-kit/accessibility": "^3.1.1",
|
||||||
"@dnd-kit/utilities": "^3.2.2",
|
"@dnd-kit/utilities": "^3.2.2",
|
||||||
@@ -1242,6 +1238,7 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cross-dirname": "^0.1.0",
|
"cross-dirname": "^0.1.0",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
@@ -1263,6 +1260,7 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"graceful-fs": "^4.2.0",
|
"graceful-fs": "^4.2.0",
|
||||||
"jsonfile": "^6.0.1",
|
"jsonfile": "^6.0.1",
|
||||||
@@ -1279,6 +1277,7 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"universalify": "^2.0.0"
|
"universalify": "^2.0.0"
|
||||||
},
|
},
|
||||||
@@ -1293,6 +1292,7 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 10.0.0"
|
"node": ">= 10.0.0"
|
||||||
}
|
}
|
||||||
@@ -4443,7 +4443,6 @@
|
|||||||
"integrity": "sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==",
|
"integrity": "sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
@@ -4853,7 +4852,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.11.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.11.tgz",
|
||||||
"integrity": "sha512-BH7YwL6rA93ReqeQS1c4bsPpcfOmJasG+Fkr6Y59q83f9M1WcBRHR2vM+P9eOisYRcN3ujQoiZY8uk5W+1WL8w==",
|
"integrity": "sha512-BH7YwL6rA93ReqeQS1c4bsPpcfOmJasG+Fkr6Y59q83f9M1WcBRHR2vM+P9eOisYRcN3ujQoiZY8uk5W+1WL8w==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"undici-types": "~6.21.0"
|
"undici-types": "~6.21.0"
|
||||||
}
|
}
|
||||||
@@ -4881,7 +4879,6 @@
|
|||||||
"integrity": "sha512-gT+oueVQkqnj6ajGJXblFR4iavIXWsGAFCk3dP4Kki5+a9R4NMt0JARdk6s8cUKcfUoqP5dAtDSLU8xYUTFV+Q==",
|
"integrity": "sha512-gT+oueVQkqnj6ajGJXblFR4iavIXWsGAFCk3dP4Kki5+a9R4NMt0JARdk6s8cUKcfUoqP5dAtDSLU8xYUTFV+Q==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "*",
|
"@types/node": "*",
|
||||||
"pg-protocol": "*",
|
"pg-protocol": "*",
|
||||||
@@ -4913,7 +4910,6 @@
|
|||||||
"integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==",
|
"integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/prop-types": "*",
|
"@types/prop-types": "*",
|
||||||
"csstype": "^3.2.2"
|
"csstype": "^3.2.2"
|
||||||
@@ -5640,7 +5636,6 @@
|
|||||||
"integrity": "sha512-X3Pp2aRQhg4xUC6PQtkubn5NpRKuUPQ9FPDQlx36SmpFwwH2N0/tw4c+NXV3nw3PsgeUs+BuWGP0gjz3TvENLQ==",
|
"integrity": "sha512-X3Pp2aRQhg4xUC6PQtkubn5NpRKuUPQ9FPDQlx36SmpFwwH2N0/tw4c+NXV3nw3PsgeUs+BuWGP0gjz3TvENLQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@algolia/abtesting": "1.15.1",
|
"@algolia/abtesting": "1.15.1",
|
||||||
"@algolia/client-abtesting": "5.49.1",
|
"@algolia/client-abtesting": "5.49.1",
|
||||||
@@ -6075,7 +6070,6 @@
|
|||||||
"integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==",
|
"integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"follow-redirects": "^1.15.11",
|
"follow-redirects": "^1.15.11",
|
||||||
"form-data": "^4.0.5",
|
"form-data": "^4.0.5",
|
||||||
@@ -6130,7 +6124,6 @@
|
|||||||
"integrity": "sha512-RxD2Vd96sQDjQr20kdP+F+dK/1OUNiVOl200vKBZY8u0vTwysfolF6Hq+3ZK2+h8My9YvZhHsF+RSGZW2VYrPQ==",
|
"integrity": "sha512-RxD2Vd96sQDjQr20kdP+F+dK/1OUNiVOl200vKBZY8u0vTwysfolF6Hq+3ZK2+h8My9YvZhHsF+RSGZW2VYrPQ==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bindings": "^1.5.0",
|
"bindings": "^1.5.0",
|
||||||
"prebuild-install": "^7.1.1"
|
"prebuild-install": "^7.1.1"
|
||||||
@@ -6210,7 +6203,6 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"baseline-browser-mapping": "^2.9.0",
|
"baseline-browser-mapping": "^2.9.0",
|
||||||
"caniuse-lite": "^1.0.30001759",
|
"caniuse-lite": "^1.0.30001759",
|
||||||
@@ -6614,7 +6606,6 @@
|
|||||||
"integrity": "sha512-opLQzEVriiH1uUQ4Kctsd49bRoFDXGGSC4GUqj7pGyxM3RehRhvTlZJc1FL/Flew2p5uwxa1tUDWKzI4wNM8pg==",
|
"integrity": "sha512-opLQzEVriiH1uUQ4Kctsd49bRoFDXGGSC4GUqj7pGyxM3RehRhvTlZJc1FL/Flew2p5uwxa1tUDWKzI4wNM8pg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@chevrotain/cst-dts-gen": "11.1.2",
|
"@chevrotain/cst-dts-gen": "11.1.2",
|
||||||
"@chevrotain/gast": "11.1.2",
|
"@chevrotain/gast": "11.1.2",
|
||||||
@@ -6970,7 +6961,8 @@
|
|||||||
"integrity": "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==",
|
"integrity": "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true
|
"optional": true,
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/cross-env": {
|
"node_modules/cross-env": {
|
||||||
"version": "7.0.3",
|
"version": "7.0.3",
|
||||||
@@ -7019,7 +7011,6 @@
|
|||||||
"integrity": "sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ==",
|
"integrity": "sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10"
|
"node": ">=0.10"
|
||||||
}
|
}
|
||||||
@@ -7453,7 +7444,6 @@
|
|||||||
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
|
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
@@ -7888,7 +7878,6 @@
|
|||||||
"integrity": "sha512-glMJgnTreo8CFINujtAhCgN96QAqApDMZ8Vl1r8f0QT8QprvC1UCltV4CcWj20YoIyLZx6IUskaJZ0NV8fokcg==",
|
"integrity": "sha512-glMJgnTreo8CFINujtAhCgN96QAqApDMZ8Vl1r8f0QT8QprvC1UCltV4CcWj20YoIyLZx6IUskaJZ0NV8fokcg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"app-builder-lib": "26.8.1",
|
"app-builder-lib": "26.8.1",
|
||||||
"builder-util": "26.8.1",
|
"builder-util": "26.8.1",
|
||||||
@@ -8484,6 +8473,7 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@electron/asar": "^3.2.1",
|
"@electron/asar": "^3.2.1",
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
@@ -8504,6 +8494,7 @@
|
|||||||
"integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
|
"integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"graceful-fs": "^4.1.2",
|
"graceful-fs": "^4.1.2",
|
||||||
"jsonfile": "^4.0.0",
|
"jsonfile": "^4.0.0",
|
||||||
@@ -8693,7 +8684,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"esbuild": "bin/esbuild"
|
"esbuild": "bin/esbuild"
|
||||||
},
|
},
|
||||||
@@ -9084,7 +9074,6 @@
|
|||||||
"integrity": "sha512-/yNdlIkpWbM0ptxno3ONTuf+2g318kh2ez3KSeZN5dZ8YC6AAmgeWz+GasYYiBJPFaYcSAPeu4GfhUaChzIJXA==",
|
"integrity": "sha512-/yNdlIkpWbM0ptxno3ONTuf+2g318kh2ez3KSeZN5dZ8YC6AAmgeWz+GasYYiBJPFaYcSAPeu4GfhUaChzIJXA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tabbable": "^6.4.0"
|
"tabbable": "^6.4.0"
|
||||||
}
|
}
|
||||||
@@ -11078,6 +11067,7 @@
|
|||||||
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
|
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"minimist": "^1.2.6"
|
"minimist": "^1.2.6"
|
||||||
},
|
},
|
||||||
@@ -11122,7 +11112,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.18.2.tgz",
|
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.18.2.tgz",
|
||||||
"integrity": "sha512-UfEShBFAZZEAKjySnTUuE7BgqkYT4mx+RjoJ5aqtmwSSvNcJ/QxQPXz/y3jSxNiVRedPfgccmuBtiPCSiEEytw==",
|
"integrity": "sha512-UfEShBFAZZEAKjySnTUuE7BgqkYT4mx+RjoJ5aqtmwSSvNcJ/QxQPXz/y3jSxNiVRedPfgccmuBtiPCSiEEytw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"aws-ssl-profiles": "^1.1.2",
|
"aws-ssl-profiles": "^1.1.2",
|
||||||
"denque": "^2.1.0",
|
"denque": "^2.1.0",
|
||||||
@@ -11665,7 +11654,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/pg/-/pg-8.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/pg/-/pg-8.20.0.tgz",
|
||||||
"integrity": "sha512-ldhMxz2r8fl/6QkXnBD3CR9/xg694oT6DZQ2s6c/RI28OjtSOpxnPrUCGOBJ46RCUxcWdx3p6kw/xnDHjKvaRA==",
|
"integrity": "sha512-ldhMxz2r8fl/6QkXnBD3CR9/xg694oT6DZQ2s6c/RI28OjtSOpxnPrUCGOBJ46RCUxcWdx3p6kw/xnDHjKvaRA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"pg-connection-string": "^2.12.0",
|
"pg-connection-string": "^2.12.0",
|
||||||
"pg-pool": "^3.13.0",
|
"pg-pool": "^3.13.0",
|
||||||
@@ -11763,7 +11751,6 @@
|
|||||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
@@ -11944,6 +11931,7 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"commander": "^9.4.0"
|
"commander": "^9.4.0"
|
||||||
},
|
},
|
||||||
@@ -11961,6 +11949,7 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^12.20.0 || >=14"
|
"node": "^12.20.0 || >=14"
|
||||||
}
|
}
|
||||||
@@ -12148,7 +12137,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
||||||
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
|
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.1.0"
|
"loose-envify": "^1.1.0"
|
||||||
},
|
},
|
||||||
@@ -12161,7 +12149,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
||||||
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
|
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.1.0",
|
"loose-envify": "^1.1.0",
|
||||||
"scheduler": "^0.23.2"
|
"scheduler": "^0.23.2"
|
||||||
@@ -12450,6 +12437,7 @@
|
|||||||
"deprecated": "Rimraf versions prior to v4 are no longer supported",
|
"deprecated": "Rimraf versions prior to v4 are no longer supported",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"glob": "^7.1.3"
|
"glob": "^7.1.3"
|
||||||
},
|
},
|
||||||
@@ -12462,7 +12450,8 @@
|
|||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/rimraf/node_modules/brace-expansion": {
|
"node_modules/rimraf/node_modules/brace-expansion": {
|
||||||
"version": "1.1.12",
|
"version": "1.1.12",
|
||||||
@@ -12470,6 +12459,7 @@
|
|||||||
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@@ -12482,6 +12472,7 @@
|
|||||||
"deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
|
"deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fs.realpath": "^1.0.0",
|
"fs.realpath": "^1.0.0",
|
||||||
"inflight": "^1.0.4",
|
"inflight": "^1.0.4",
|
||||||
@@ -12503,6 +12494,7 @@
|
|||||||
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
},
|
},
|
||||||
@@ -13484,6 +13476,7 @@
|
|||||||
"integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==",
|
"integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"mkdirp": "^0.5.1",
|
"mkdirp": "^0.5.1",
|
||||||
"rimraf": "~2.6.2"
|
"rimraf": "~2.6.2"
|
||||||
@@ -14249,7 +14242,6 @@
|
|||||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
"tsserver": "bin/tsserver"
|
"tsserver": "bin/tsserver"
|
||||||
@@ -14503,7 +14495,6 @@
|
|||||||
"integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==",
|
"integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.25.0",
|
"esbuild": "^0.25.0",
|
||||||
"fdir": "^6.4.4",
|
"fdir": "^6.4.4",
|
||||||
@@ -16645,7 +16636,6 @@
|
|||||||
"integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",
|
"integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.21.3",
|
"esbuild": "^0.21.3",
|
||||||
"postcss": "^8.4.43",
|
"postcss": "^8.4.43",
|
||||||
@@ -16761,7 +16751,6 @@
|
|||||||
"integrity": "sha512-BZqN4Ze6mDQVNAni0IHeMJ5mwr8VAJ3MQC9FmprRhcBYENw+wOAAjRj8jfmN6FLl0j96OXbR+CjWhmAmM+QGnA==",
|
"integrity": "sha512-BZqN4Ze6mDQVNAni0IHeMJ5mwr8VAJ3MQC9FmprRhcBYENw+wOAAjRj8jfmN6FLl0j96OXbR+CjWhmAmM+QGnA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vue/compiler-dom": "3.5.29",
|
"@vue/compiler-dom": "3.5.29",
|
||||||
"@vue/compiler-sfc": "3.5.29",
|
"@vue/compiler-sfc": "3.5.29",
|
||||||
|
|||||||
@@ -0,0 +1,196 @@
|
|||||||
|
import { describe, it, expect } from 'vitest';
|
||||||
|
import { buildGeminiGenerateContentRequestFromOpenAi } from './geminiCliCompat.js';
|
||||||
|
|
||||||
|
describe('thoughtSignature injection in OpenAI→Gemini conversion', () => {
|
||||||
|
it('injects thoughtSignature from provider_specific_fields into functionCall parts', () => {
|
||||||
|
const result = buildGeminiGenerateContentRequestFromOpenAi({
|
||||||
|
body: {
|
||||||
|
model: 'gemini-3-flash-preview',
|
||||||
|
messages: [
|
||||||
|
{ role: 'user', content: 'What is the weather?' },
|
||||||
|
{
|
||||||
|
role: 'assistant',
|
||||||
|
content: 'Let me check.',
|
||||||
|
tool_calls: [
|
||||||
|
{
|
||||||
|
id: 'call_123',
|
||||||
|
type: 'function',
|
||||||
|
function: { name: 'get_weather', arguments: '{"city":"Tokyo"}' },
|
||||||
|
provider_specific_fields: { thought_signature: 'real_sig_abc' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ role: 'tool', tool_call_id: 'call_123', content: '{"temp":"22C"}' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
modelName: 'gemini-3-flash-preview',
|
||||||
|
}) as Record<string, unknown>;
|
||||||
|
|
||||||
|
const contents = result.contents as Array<Record<string, unknown>>;
|
||||||
|
// Find the model message with functionCall
|
||||||
|
const modelMsgs = contents.filter((c) => c.role === 'model');
|
||||||
|
const fcParts = modelMsgs
|
||||||
|
.flatMap((m) => (m.parts as Array<Record<string, unknown>>))
|
||||||
|
.filter((p) => 'functionCall' in p);
|
||||||
|
|
||||||
|
expect(fcParts.length).toBe(1);
|
||||||
|
expect(fcParts[0].thoughtSignature).toBe('real_sig_abc');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('splits text and signed functionCall parts into separate model messages', () => {
|
||||||
|
const result = buildGeminiGenerateContentRequestFromOpenAi({
|
||||||
|
body: {
|
||||||
|
model: 'gemini-3-flash-preview',
|
||||||
|
messages: [
|
||||||
|
{ role: 'user', content: 'Read the file.' },
|
||||||
|
{
|
||||||
|
role: 'assistant',
|
||||||
|
content: 'I will read it.',
|
||||||
|
tool_calls: [
|
||||||
|
{
|
||||||
|
id: 'call_456',
|
||||||
|
type: 'function',
|
||||||
|
function: { name: 'Read', arguments: '{"path":"/tmp/x"}' },
|
||||||
|
provider_specific_fields: { thought_signature: 'sig_split_test' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ role: 'tool', tool_call_id: 'call_456', content: 'file content here' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
modelName: 'gemini-3-flash-preview',
|
||||||
|
}) as Record<string, unknown>;
|
||||||
|
|
||||||
|
const contents = result.contents as Array<Record<string, unknown>>;
|
||||||
|
const modelMsgs = contents.filter((c) => c.role === 'model');
|
||||||
|
|
||||||
|
// Should be 2 model messages: text (unsigned) + functionCall (signed)
|
||||||
|
expect(modelMsgs.length).toBe(2);
|
||||||
|
|
||||||
|
const firstParts = modelMsgs[0].parts as Array<Record<string, unknown>>;
|
||||||
|
const secondParts = modelMsgs[1].parts as Array<Record<string, unknown>>;
|
||||||
|
|
||||||
|
// First: text only, no thoughtSignature
|
||||||
|
expect(firstParts.every((p) => 'text' in p)).toBe(true);
|
||||||
|
expect(firstParts.every((p) => !('thoughtSignature' in p))).toBe(true);
|
||||||
|
|
||||||
|
// Second: functionCall with thoughtSignature
|
||||||
|
expect(secondParts.every((p) => 'functionCall' in p)).toBe(true);
|
||||||
|
expect(secondParts[0].thoughtSignature).toBe('sig_split_test');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('injects dummy sentinel when thinking enabled but no signature available', () => {
|
||||||
|
const result = buildGeminiGenerateContentRequestFromOpenAi({
|
||||||
|
body: {
|
||||||
|
model: 'gemini-3-flash-preview',
|
||||||
|
reasoning_effort: 'high',
|
||||||
|
messages: [
|
||||||
|
{ role: 'user', content: 'Do something.' },
|
||||||
|
{
|
||||||
|
role: 'assistant',
|
||||||
|
tool_calls: [
|
||||||
|
{
|
||||||
|
id: 'call_no_sig',
|
||||||
|
type: 'function',
|
||||||
|
function: { name: 'Bash', arguments: '{"command":"ls"}' },
|
||||||
|
// No provider_specific_fields — signature missing
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ role: 'tool', tool_call_id: 'call_no_sig', content: 'file1\nfile2' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
modelName: 'gemini-3-flash-preview',
|
||||||
|
}) as Record<string, unknown>;
|
||||||
|
|
||||||
|
const contents = result.contents as Array<Record<string, unknown>>;
|
||||||
|
const modelMsgs = contents.filter((c) => c.role === 'model');
|
||||||
|
const fcParts = modelMsgs
|
||||||
|
.flatMap((m) => (m.parts as Array<Record<string, unknown>>))
|
||||||
|
.filter((p) => 'functionCall' in p);
|
||||||
|
|
||||||
|
expect(fcParts.length).toBe(1);
|
||||||
|
// Should have a dummy sentinel, not be missing
|
||||||
|
expect(typeof fcParts[0].thoughtSignature).toBe('string');
|
||||||
|
expect((fcParts[0].thoughtSignature as string).length).toBeGreaterThan(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not inject thoughtSignature when thinking is not enabled', () => {
|
||||||
|
const result = buildGeminiGenerateContentRequestFromOpenAi({
|
||||||
|
body: {
|
||||||
|
model: 'gemini-2.5-flash',
|
||||||
|
messages: [
|
||||||
|
{ role: 'user', content: 'Hello' },
|
||||||
|
{
|
||||||
|
role: 'assistant',
|
||||||
|
tool_calls: [
|
||||||
|
{
|
||||||
|
id: 'call_no_think',
|
||||||
|
type: 'function',
|
||||||
|
function: { name: 'Read', arguments: '{"path":"/x"}' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ role: 'tool', tool_call_id: 'call_no_think', content: 'data' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
modelName: 'gemini-2.5-flash',
|
||||||
|
}) as Record<string, unknown>;
|
||||||
|
|
||||||
|
const contents = result.contents as Array<Record<string, unknown>>;
|
||||||
|
const modelMsgs = contents.filter((c) => c.role === 'model');
|
||||||
|
const fcParts = modelMsgs
|
||||||
|
.flatMap((m) => (m.parts as Array<Record<string, unknown>>))
|
||||||
|
.filter((p) => 'functionCall' in p);
|
||||||
|
|
||||||
|
expect(fcParts.length).toBe(1);
|
||||||
|
// No thinking → no signature injected
|
||||||
|
expect(fcParts[0].thoughtSignature).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('preserves functionResponse count matching functionCall count', () => {
|
||||||
|
const result = buildGeminiGenerateContentRequestFromOpenAi({
|
||||||
|
body: {
|
||||||
|
model: 'gemini-3-flash-preview',
|
||||||
|
messages: [
|
||||||
|
{ role: 'user', content: 'Read two files.' },
|
||||||
|
{
|
||||||
|
role: 'assistant',
|
||||||
|
tool_calls: [
|
||||||
|
{
|
||||||
|
id: 'call_a',
|
||||||
|
type: 'function',
|
||||||
|
function: { name: 'Read', arguments: '{"path":"/a"}' },
|
||||||
|
provider_specific_fields: { thought_signature: 'sig_a' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'call_b',
|
||||||
|
type: 'function',
|
||||||
|
function: { name: 'Read', arguments: '{"path":"/b"}' },
|
||||||
|
provider_specific_fields: { thought_signature: 'sig_b' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ role: 'tool', tool_call_id: 'call_a', content: 'content a' },
|
||||||
|
{ role: 'tool', tool_call_id: 'call_b', content: 'content b' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
modelName: 'gemini-3-flash-preview',
|
||||||
|
}) as Record<string, unknown>;
|
||||||
|
|
||||||
|
const contents = result.contents as Array<Record<string, unknown>>;
|
||||||
|
|
||||||
|
// Count functionCall and functionResponse parts
|
||||||
|
let fcCount = 0;
|
||||||
|
let frCount = 0;
|
||||||
|
for (const content of contents) {
|
||||||
|
for (const part of (content.parts as Array<Record<string, unknown>>)) {
|
||||||
|
if ('functionCall' in part) fcCount++;
|
||||||
|
if ('functionResponse' in part) frCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(fcCount).toBe(2);
|
||||||
|
expect(frCount).toBe(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
import { TextDecoder, TextEncoder } from 'node:util';
|
import { TextDecoder, TextEncoder } from 'node:util';
|
||||||
import { resolveGeminiThinkingConfigFromRequest } from '../../transformers/gemini/generate-content/convert.js';
|
import { resolveGeminiThinkingConfigFromRequest } from '../../transformers/gemini/generate-content/convert.js';
|
||||||
|
|
||||||
|
// Dummy sentinel used when no real thoughtSignature is available but thinking
|
||||||
|
// mode is enabled. Gemini accepts any base64 string and won't reject this.
|
||||||
|
const DUMMY_THOUGHT_SIGNATURE = 'c2tpcF90aG91Z2h0X3NpZ25hdHVyZV92YWxpZGF0b3I=';
|
||||||
|
|
||||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||||
return !!value && typeof value === 'object' && !Array.isArray(value);
|
return !!value && typeof value === 'object' && !Array.isArray(value);
|
||||||
}
|
}
|
||||||
@@ -143,6 +147,27 @@ export function buildGeminiGenerateContentRequestFromOpenAi(input: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Detect if thinking mode is enabled (needed for dummy signature fallback)
|
||||||
|
const hasThinkingEnabled = !!resolveGeminiThinkingConfigFromRequest(input.modelName, input.body);
|
||||||
|
|
||||||
|
// Collect thoughtSignatures from assistant tool_calls for injection.
|
||||||
|
// OpenAI format stores signatures in provider_specific_fields or encoded in tool call IDs.
|
||||||
|
const thoughtSignatureById = new Map<string, string>();
|
||||||
|
for (const message of messages) {
|
||||||
|
if (!isRecord(message) || asTrimmedString(message.role) !== 'assistant') continue;
|
||||||
|
const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : [];
|
||||||
|
for (const toolCall of toolCalls) {
|
||||||
|
if (!isRecord(toolCall)) continue;
|
||||||
|
const id = asTrimmedString(toolCall.id);
|
||||||
|
if (!id) continue;
|
||||||
|
// Check provider_specific_fields first
|
||||||
|
const providerFields = isRecord(toolCall.provider_specific_fields) ? toolCall.provider_specific_fields : null;
|
||||||
|
if (providerFields && typeof providerFields.thought_signature === 'string') {
|
||||||
|
thoughtSignatureById.set(id, providerFields.thought_signature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const systemParts: Array<Record<string, unknown>> = [];
|
const systemParts: Array<Record<string, unknown>> = [];
|
||||||
if (typeof input.instructions === 'string' && input.instructions.trim()) {
|
if (typeof input.instructions === 'string' && input.instructions.trim()) {
|
||||||
systemParts.push({ text: input.instructions.trim() });
|
systemParts.push({ text: input.instructions.trim() });
|
||||||
@@ -176,7 +201,8 @@ export function buildGeminiGenerateContentRequestFromOpenAi(input: {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const parts = convertContentToGeminiParts(message.content);
|
const textParts = convertContentToGeminiParts(message.content);
|
||||||
|
const fcParts: Array<Record<string, unknown>> = [];
|
||||||
const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : [];
|
const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : [];
|
||||||
for (const toolCall of toolCalls) {
|
for (const toolCall of toolCalls) {
|
||||||
if (!isRecord(toolCall) || !isRecord(toolCall.function)) continue;
|
if (!isRecord(toolCall) || !isRecord(toolCall.function)) continue;
|
||||||
@@ -193,21 +219,45 @@ export function buildGeminiGenerateContentRequestFromOpenAi(input: {
|
|||||||
} else if (isRecord(rawArguments)) {
|
} else if (isRecord(rawArguments)) {
|
||||||
args = rawArguments;
|
args = rawArguments;
|
||||||
}
|
}
|
||||||
parts.push({
|
const fcPart: Record<string, unknown> = {
|
||||||
functionCall: {
|
functionCall: { name, args },
|
||||||
name,
|
};
|
||||||
args,
|
// Inject thoughtSignature if available from provider_specific_fields.
|
||||||
},
|
// If no signature is found, use a dummy sentinel so Gemini doesn't reject
|
||||||
});
|
// the request outright. Gemini 3+ requires thoughtSignature on all
|
||||||
|
// functionCall parts when thinking is enabled.
|
||||||
|
// Ref: https://ai.google.dev/gemini-api/docs/thought-signatures
|
||||||
|
const id = asTrimmedString(toolCall.id);
|
||||||
|
const signature = thoughtSignatureById.get(id);
|
||||||
|
if (signature) {
|
||||||
|
fcPart.thoughtSignature = signature;
|
||||||
|
} else if (hasThinkingEnabled) {
|
||||||
|
fcPart.thoughtSignature = DUMMY_THOUGHT_SIGNATURE;
|
||||||
}
|
}
|
||||||
if (parts.length <= 0) continue;
|
fcParts.push(fcPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
const geminiRole = role === 'assistant' ? 'model' : 'user';
|
||||||
|
|
||||||
|
// Gemini requires that parts WITH thoughtSignature and parts WITHOUT
|
||||||
|
// are not mixed in the same message. Split if needed.
|
||||||
|
// Ref: https://ai.google.dev/gemini-api/docs/thought-signatures
|
||||||
|
const hasSigned = fcParts.some((p) => 'thoughtSignature' in p);
|
||||||
|
if (hasSigned && textParts.length > 0 && fcParts.length > 0) {
|
||||||
|
// Emit text parts first, then functionCall parts in a separate message
|
||||||
request.contents = [
|
request.contents = [
|
||||||
...(Array.isArray(request.contents) ? request.contents : []),
|
...(Array.isArray(request.contents) ? request.contents : []),
|
||||||
{
|
{ role: geminiRole, parts: textParts },
|
||||||
role: role === 'assistant' ? 'model' : 'user',
|
{ role: geminiRole, parts: fcParts },
|
||||||
parts,
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
} else {
|
||||||
|
const allParts = [...textParts, ...fcParts];
|
||||||
|
if (allParts.length <= 0) continue;
|
||||||
|
request.contents = [
|
||||||
|
...(Array.isArray(request.contents) ? request.contents : []),
|
||||||
|
{ role: geminiRole, parts: allParts },
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (systemParts.length > 0) {
|
if (systemParts.length > 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user