chore: support Node >=18, add optional @google/genai peer dependency and API key fallback

This commit is contained in:
MrAvalonApple 2026-04-04 22:12:28 +03:00
parent 944918d5ae
commit 553bf24e61
5 changed files with 210 additions and 42 deletions

View File

@ -2,7 +2,7 @@
* Quick smoke test for the Gemini adapter. * Quick smoke test for the Gemini adapter.
* *
* Run: * Run:
* npx tsx examples/08-gemini-test.ts * npx tsx examples/13-gemini.ts
* *
* If GEMINI_API_KEY is not set, the adapter will not work. * If GEMINI_API_KEY is not set, the adapter will not work.
*/ */

120
package-lock.json generated
View File

@ -1,16 +1,15 @@
{ {
"name": "@jackchen_me/open-multi-agent", "name": "@jackchen_me/open-multi-agent",
"version": "0.1.0", "version": "0.2.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@jackchen_me/open-multi-agent", "name": "@jackchen_me/open-multi-agent",
"version": "0.1.0", "version": "0.2.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@anthropic-ai/sdk": "^0.52.0", "@anthropic-ai/sdk": "^0.52.0",
"@google/genai": "^1.48.0",
"openai": "^4.73.0", "openai": "^4.73.0",
"zod": "^3.23.0" "zod": "^3.23.0"
}, },
@ -21,7 +20,15 @@
"vitest": "^2.1.0" "vitest": "^2.1.0"
}, },
"engines": { "engines": {
"node": ">=20.0.0" "node": ">=18.0.0"
},
"peerDependencies": {
"@google/genai": "^1.48.0"
},
"peerDependenciesMeta": {
"@google/genai": {
"optional": true
}
} }
}, },
"node_modules/@anthropic-ai/sdk": { "node_modules/@anthropic-ai/sdk": {
@ -480,6 +487,8 @@
"resolved": "https://registry.npmjs.org/@google/genai/-/genai-1.48.0.tgz", "resolved": "https://registry.npmjs.org/@google/genai/-/genai-1.48.0.tgz",
"integrity": "sha512-plonYK4ML2PrxsRD9SeqmFt76eREWkQdPCglOA6aYDzL1AAbE+7PUnT54SvpWGfws13L0AZEqGSpL7+1IPnTxQ==", "integrity": "sha512-plonYK4ML2PrxsRD9SeqmFt76eREWkQdPCglOA6aYDzL1AAbE+7PUnT54SvpWGfws13L0AZEqGSpL7+1IPnTxQ==",
"license": "Apache-2.0", "license": "Apache-2.0",
"optional": true,
"peer": true,
"dependencies": { "dependencies": {
"google-auth-library": "^10.3.0", "google-auth-library": "^10.3.0",
"p-retry": "^4.6.2", "p-retry": "^4.6.2",
@ -509,31 +518,41 @@
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
"integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==",
"license": "BSD-3-Clause" "license": "BSD-3-Clause",
"optional": true,
"peer": true
}, },
"node_modules/@protobufjs/base64": { "node_modules/@protobufjs/base64": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
"integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==",
"license": "BSD-3-Clause" "license": "BSD-3-Clause",
"optional": true,
"peer": true
}, },
"node_modules/@protobufjs/codegen": { "node_modules/@protobufjs/codegen": {
"version": "2.0.4", "version": "2.0.4",
"resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
"integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==",
"license": "BSD-3-Clause" "license": "BSD-3-Clause",
"optional": true,
"peer": true
}, },
"node_modules/@protobufjs/eventemitter": { "node_modules/@protobufjs/eventemitter": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
"integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==",
"license": "BSD-3-Clause" "license": "BSD-3-Clause",
"optional": true,
"peer": true
}, },
"node_modules/@protobufjs/fetch": { "node_modules/@protobufjs/fetch": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
"integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"optional": true,
"peer": true,
"dependencies": { "dependencies": {
"@protobufjs/aspromise": "^1.1.1", "@protobufjs/aspromise": "^1.1.1",
"@protobufjs/inquire": "^1.1.0" "@protobufjs/inquire": "^1.1.0"
@ -543,31 +562,41 @@
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
"integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==",
"license": "BSD-3-Clause" "license": "BSD-3-Clause",
"optional": true,
"peer": true
}, },
"node_modules/@protobufjs/inquire": { "node_modules/@protobufjs/inquire": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
"integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==",
"license": "BSD-3-Clause" "license": "BSD-3-Clause",
"optional": true,
"peer": true
}, },
"node_modules/@protobufjs/path": { "node_modules/@protobufjs/path": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
"integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==",
"license": "BSD-3-Clause" "license": "BSD-3-Clause",
"optional": true,
"peer": true
}, },
"node_modules/@protobufjs/pool": { "node_modules/@protobufjs/pool": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
"integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==",
"license": "BSD-3-Clause" "license": "BSD-3-Clause",
"optional": true,
"peer": true
}, },
"node_modules/@protobufjs/utf8": { "node_modules/@protobufjs/utf8": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
"integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==",
"license": "BSD-3-Clause" "license": "BSD-3-Clause",
"optional": true,
"peer": true
}, },
"node_modules/@rollup/rollup-darwin-arm64": { "node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.60.1", "version": "4.60.1",
@ -613,7 +642,9 @@
"version": "0.12.0", "version": "0.12.0",
"resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz",
"integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==",
"license": "MIT" "license": "MIT",
"optional": true,
"peer": true
}, },
"node_modules/@vitest/expect": { "node_modules/@vitest/expect": {
"version": "2.1.9", "version": "2.1.9",
@ -745,6 +776,8 @@
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
"integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
"license": "MIT", "license": "MIT",
"optional": true,
"peer": true,
"engines": { "engines": {
"node": ">= 14" "node": ">= 14"
} }
@ -795,13 +828,17 @@
"url": "https://feross.org/support" "url": "https://feross.org/support"
} }
], ],
"license": "MIT" "license": "MIT",
"optional": true,
"peer": true
}, },
"node_modules/bignumber.js": { "node_modules/bignumber.js": {
"version": "9.3.1", "version": "9.3.1",
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz",
"integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==",
"license": "MIT", "license": "MIT",
"optional": true,
"peer": true,
"engines": { "engines": {
"node": "*" "node": "*"
} }
@ -810,7 +847,9 @@
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
"license": "BSD-3-Clause" "license": "BSD-3-Clause",
"optional": true,
"peer": true
}, },
"node_modules/cac": { "node_modules/cac": {
"version": "6.7.14", "version": "6.7.14",
@ -879,6 +918,8 @@
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
"integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
"license": "MIT", "license": "MIT",
"optional": true,
"peer": true,
"engines": { "engines": {
"node": ">= 12" "node": ">= 12"
} }
@ -887,6 +928,7 @@
"version": "4.4.3", "version": "4.4.3",
"resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz", "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz",
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"devOptional": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"ms": "^2.1.3" "ms": "^2.1.3"
@ -938,6 +980,8 @@
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
"license": "Apache-2.0", "license": "Apache-2.0",
"optional": true,
"peer": true,
"dependencies": { "dependencies": {
"safe-buffer": "^5.0.1" "safe-buffer": "^5.0.1"
} }
@ -1440,7 +1484,9 @@
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
"license": "MIT" "license": "MIT",
"optional": true,
"peer": true
}, },
"node_modules/fetch-blob": { "node_modules/fetch-blob": {
"version": "3.2.0", "version": "3.2.0",
@ -1457,6 +1503,8 @@
} }
], ],
"license": "MIT", "license": "MIT",
"optional": true,
"peer": true,
"dependencies": { "dependencies": {
"node-domexception": "^1.0.0", "node-domexception": "^1.0.0",
"web-streams-polyfill": "^3.0.3" "web-streams-polyfill": "^3.0.3"
@ -1470,6 +1518,8 @@
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
"integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
"license": "MIT", "license": "MIT",
"optional": true,
"peer": true,
"engines": { "engines": {
"node": ">= 8" "node": ">= 8"
} }
@ -1514,6 +1564,8 @@
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
"integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
"license": "MIT", "license": "MIT",
"optional": true,
"peer": true,
"dependencies": { "dependencies": {
"fetch-blob": "^3.1.2" "fetch-blob": "^3.1.2"
}, },
@ -1550,6 +1602,8 @@
"resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.4.tgz", "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.4.tgz",
"integrity": "sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA==", "integrity": "sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA==",
"license": "Apache-2.0", "license": "Apache-2.0",
"optional": true,
"peer": true,
"dependencies": { "dependencies": {
"extend": "^3.0.2", "extend": "^3.0.2",
"https-proxy-agent": "^7.0.1", "https-proxy-agent": "^7.0.1",
@ -1564,6 +1618,8 @@
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
"integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
"license": "MIT", "license": "MIT",
"optional": true,
"peer": true,
"dependencies": { "dependencies": {
"data-uri-to-buffer": "^4.0.0", "data-uri-to-buffer": "^4.0.0",
"fetch-blob": "^3.1.4", "fetch-blob": "^3.1.4",
@ -1582,6 +1638,8 @@
"resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz", "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz",
"integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==",
"license": "Apache-2.0", "license": "Apache-2.0",
"optional": true,
"peer": true,
"dependencies": { "dependencies": {
"gaxios": "^7.0.0", "gaxios": "^7.0.0",
"google-logging-utils": "^1.0.0", "google-logging-utils": "^1.0.0",
@ -1646,6 +1704,8 @@
"resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.6.2.tgz", "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.6.2.tgz",
"integrity": "sha512-e27Z6EThmVNNvtYASwQxose/G57rkRuaRbQyxM2bvYLLX/GqWZ5chWq2EBoUchJbCc57eC9ArzO5wMsEmWftCw==", "integrity": "sha512-e27Z6EThmVNNvtYASwQxose/G57rkRuaRbQyxM2bvYLLX/GqWZ5chWq2EBoUchJbCc57eC9ArzO5wMsEmWftCw==",
"license": "Apache-2.0", "license": "Apache-2.0",
"optional": true,
"peer": true,
"dependencies": { "dependencies": {
"base64-js": "^1.3.0", "base64-js": "^1.3.0",
"ecdsa-sig-formatter": "^1.0.11", "ecdsa-sig-formatter": "^1.0.11",
@ -1663,6 +1723,8 @@
"resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz", "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz",
"integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==",
"license": "Apache-2.0", "license": "Apache-2.0",
"optional": true,
"peer": true,
"engines": { "engines": {
"node": ">=14" "node": ">=14"
} }
@ -1723,6 +1785,8 @@
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
"integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
"license": "MIT", "license": "MIT",
"optional": true,
"peer": true,
"dependencies": { "dependencies": {
"agent-base": "^7.1.2", "agent-base": "^7.1.2",
"debug": "4" "debug": "4"
@ -1745,6 +1809,8 @@
"resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz",
"integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
"license": "MIT", "license": "MIT",
"optional": true,
"peer": true,
"dependencies": { "dependencies": {
"bignumber.js": "^9.0.0" "bignumber.js": "^9.0.0"
} }
@ -1754,6 +1820,8 @@
"resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz",
"integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==",
"license": "MIT", "license": "MIT",
"optional": true,
"peer": true,
"dependencies": { "dependencies": {
"buffer-equal-constant-time": "^1.0.1", "buffer-equal-constant-time": "^1.0.1",
"ecdsa-sig-formatter": "1.0.11", "ecdsa-sig-formatter": "1.0.11",
@ -1765,6 +1833,8 @@
"resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz",
"integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==",
"license": "MIT", "license": "MIT",
"optional": true,
"peer": true,
"dependencies": { "dependencies": {
"jwa": "^2.0.1", "jwa": "^2.0.1",
"safe-buffer": "^5.0.1" "safe-buffer": "^5.0.1"
@ -1774,7 +1844,9 @@
"version": "5.3.2", "version": "5.3.2",
"resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
"integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
"license": "Apache-2.0" "license": "Apache-2.0",
"optional": true,
"peer": true
}, },
"node_modules/loupe": { "node_modules/loupe": {
"version": "3.2.1", "version": "3.2.1",
@ -1938,6 +2010,8 @@
"resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz",
"integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==",
"license": "MIT", "license": "MIT",
"optional": true,
"peer": true,
"dependencies": { "dependencies": {
"@types/retry": "0.12.0", "@types/retry": "0.12.0",
"retry": "^0.13.1" "retry": "^0.13.1"
@ -2005,6 +2079,8 @@
"integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==",
"hasInstallScript": true, "hasInstallScript": true,
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"optional": true,
"peer": true,
"dependencies": { "dependencies": {
"@protobufjs/aspromise": "^1.1.2", "@protobufjs/aspromise": "^1.1.2",
"@protobufjs/base64": "^1.1.2", "@protobufjs/base64": "^1.1.2",
@ -2038,6 +2114,8 @@
"resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
"integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==",
"license": "MIT", "license": "MIT",
"optional": true,
"peer": true,
"engines": { "engines": {
"node": ">= 4" "node": ">= 4"
} }
@ -2105,7 +2183,9 @@
"url": "https://feross.org/support" "url": "https://feross.org/support"
} }
], ],
"license": "MIT" "license": "MIT",
"optional": true,
"peer": true
}, },
"node_modules/siginfo": { "node_modules/siginfo": {
"version": "2.0.0", "version": "2.0.0",
@ -2483,6 +2563,8 @@
"resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz",
"integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==",
"license": "MIT", "license": "MIT",
"optional": true,
"peer": true,
"engines": { "engines": {
"node": ">=10.0.0" "node": ">=10.0.0"
}, },

View File

@ -34,14 +34,21 @@
"author": "", "author": "",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=20.0.0" "node": ">=18.0.0"
}, },
"dependencies": { "dependencies": {
"@anthropic-ai/sdk": "^0.52.0", "@anthropic-ai/sdk": "^0.52.0",
"@google/genai": "^1.48.0",
"openai": "^4.73.0", "openai": "^4.73.0",
"zod": "^3.23.0" "zod": "^3.23.0"
}, },
"peerDependencies": {
"@google/genai": "^1.48.0"
},
"peerDependenciesMeta": {
"@google/genai": {
"optional": true
}
},
"devDependencies": { "devDependencies": {
"@types/node": "^22.0.0", "@types/node": "^22.0.0",
"tsx": "^4.21.0", "tsx": "^4.21.0",

View File

@ -11,6 +11,7 @@
* API key resolution order: * API key resolution order:
* 1. `apiKey` constructor argument * 1. `apiKey` constructor argument
* 2. `GEMINI_API_KEY` environment variable * 2. `GEMINI_API_KEY` environment variable
* 3. `GOOGLE_API_KEY` environment variable
* *
* @example * @example
* ```ts * ```ts
@ -37,7 +38,6 @@ import {
import type { import type {
ContentBlock, ContentBlock,
ImageBlock,
LLMAdapter, LLMAdapter,
LLMChatOptions, LLMChatOptions,
LLMMessage, LLMMessage,
@ -45,8 +45,6 @@ import type {
LLMStreamOptions, LLMStreamOptions,
LLMToolDef, LLMToolDef,
StreamEvent, StreamEvent,
TextBlock,
ToolResultBlock,
ToolUseBlock, ToolUseBlock,
} from '../types.js' } from '../types.js'
@ -255,7 +253,7 @@ export class GeminiAdapter implements LLMAdapter {
constructor(apiKey?: string) { constructor(apiKey?: string) {
this.#client = new GoogleGenAI({ this.#client = new GoogleGenAI({
apiKey: apiKey ?? process.env['GEMINI_API_KEY'], apiKey: apiKey ?? process.env['GEMINI_API_KEY'] ?? process.env['GOOGLE_API_KEY'],
}) })
} }
@ -378,19 +376,3 @@ export class GeminiAdapter implements LLMAdapter {
} }
} }
} }
// Re-export types that consumers of this module commonly need alongside the adapter.
export type {
ContentBlock,
ImageBlock,
LLMAdapter,
LLMChatOptions,
LLMMessage,
LLMResponse,
LLMStreamOptions,
LLMToolDef,
StreamEvent,
TextBlock,
ToolResultBlock,
ToolUseBlock,
}

View File

@ -0,0 +1,97 @@
import { describe, it, expect, vi, beforeEach } from 'vitest'
// ---------------------------------------------------------------------------
// Mock GoogleGenAI constructor (must be hoisted for Vitest)
// ---------------------------------------------------------------------------
const GoogleGenAIMock = vi.hoisted(() => vi.fn())
vi.mock('@google/genai', () => ({
GoogleGenAI: GoogleGenAIMock,
FunctionCallingConfigMode: { AUTO: 'AUTO' },
}))
import { GeminiAdapter } from '../src/llm/gemini.js'
import { createAdapter } from '../src/llm/adapter.js'
// ---------------------------------------------------------------------------
// GeminiAdapter tests
// ---------------------------------------------------------------------------
describe('GeminiAdapter', () => {
beforeEach(() => {
GoogleGenAIMock.mockClear()
})
it('has name "gemini"', () => {
const adapter = new GeminiAdapter()
expect(adapter.name).toBe('gemini')
})
it('uses GEMINI_API_KEY by default', () => {
const originalGemini = process.env['GEMINI_API_KEY']
const originalGoogle = process.env['GOOGLE_API_KEY']
process.env['GEMINI_API_KEY'] = 'gemini-env-key'
delete process.env['GOOGLE_API_KEY']
try {
new GeminiAdapter()
expect(GoogleGenAIMock).toHaveBeenCalledWith(
expect.objectContaining({
apiKey: 'gemini-env-key',
}),
)
} finally {
if (originalGemini === undefined) {
delete process.env['GEMINI_API_KEY']
} else {
process.env['GEMINI_API_KEY'] = originalGemini
}
if (originalGoogle === undefined) {
delete process.env['GOOGLE_API_KEY']
} else {
process.env['GOOGLE_API_KEY'] = originalGoogle
}
}
})
it('falls back to GOOGLE_API_KEY when GEMINI_API_KEY is unset', () => {
const originalGemini = process.env['GEMINI_API_KEY']
const originalGoogle = process.env['GOOGLE_API_KEY']
delete process.env['GEMINI_API_KEY']
process.env['GOOGLE_API_KEY'] = 'google-env-key'
try {
new GeminiAdapter()
expect(GoogleGenAIMock).toHaveBeenCalledWith(
expect.objectContaining({
apiKey: 'google-env-key',
}),
)
} finally {
if (originalGemini === undefined) {
delete process.env['GEMINI_API_KEY']
} else {
process.env['GEMINI_API_KEY'] = originalGemini
}
if (originalGoogle === undefined) {
delete process.env['GOOGLE_API_KEY']
} else {
process.env['GOOGLE_API_KEY'] = originalGoogle
}
}
})
it('allows overriding apiKey explicitly', () => {
new GeminiAdapter('explicit-key')
expect(GoogleGenAIMock).toHaveBeenCalledWith(
expect.objectContaining({
apiKey: 'explicit-key',
}),
)
})
it('createAdapter("gemini") returns GeminiAdapter instance', async () => {
const adapter = await createAdapter('gemini')
expect(adapter).toBeInstanceOf(GeminiAdapter)
})
})