Release v0.25.3

This commit is contained in:
Mario Zechner 2025-12-21 21:01:27 +01:00
parent d95a5c4186
commit 9c18439c4d
13 changed files with 133 additions and 871 deletions

178
package-lock.json generated
View file

@ -995,9 +995,9 @@
}
},
"node_modules/@napi-rs/canvas": {
"version": "0.1.85",
"resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-0.1.85.tgz",
"integrity": "sha512-q8VnfGv4i3/vo3hMhJQxqzy8bFQ8H6MEXyiO+a66p/Ci7HD++pRAaH1tpri3jgocHH24tJNAT59r6z04LG9VpQ==",
"version": "0.1.86",
"resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-0.1.86.tgz",
"integrity": "sha512-hOkywnrkdFdVpsuaNsZWfEY7kc96eROV2DuMTTvGF15AZfwobzdG2w0eDlU5UBx3Lg/XlWUnqVT5zLUWyo5h6A==",
"license": "MIT",
"optional": true,
"workspaces": [
@ -1011,23 +1011,23 @@
"url": "https://github.com/sponsors/Brooooooklyn"
},
"optionalDependencies": {
"@napi-rs/canvas-android-arm64": "0.1.85",
"@napi-rs/canvas-darwin-arm64": "0.1.85",
"@napi-rs/canvas-darwin-x64": "0.1.85",
"@napi-rs/canvas-linux-arm-gnueabihf": "0.1.85",
"@napi-rs/canvas-linux-arm64-gnu": "0.1.85",
"@napi-rs/canvas-linux-arm64-musl": "0.1.85",
"@napi-rs/canvas-linux-riscv64-gnu": "0.1.85",
"@napi-rs/canvas-linux-x64-gnu": "0.1.85",
"@napi-rs/canvas-linux-x64-musl": "0.1.85",
"@napi-rs/canvas-win32-arm64-msvc": "0.1.85",
"@napi-rs/canvas-win32-x64-msvc": "0.1.85"
"@napi-rs/canvas-android-arm64": "0.1.86",
"@napi-rs/canvas-darwin-arm64": "0.1.86",
"@napi-rs/canvas-darwin-x64": "0.1.86",
"@napi-rs/canvas-linux-arm-gnueabihf": "0.1.86",
"@napi-rs/canvas-linux-arm64-gnu": "0.1.86",
"@napi-rs/canvas-linux-arm64-musl": "0.1.86",
"@napi-rs/canvas-linux-riscv64-gnu": "0.1.86",
"@napi-rs/canvas-linux-x64-gnu": "0.1.86",
"@napi-rs/canvas-linux-x64-musl": "0.1.86",
"@napi-rs/canvas-win32-arm64-msvc": "0.1.86",
"@napi-rs/canvas-win32-x64-msvc": "0.1.86"
}
},
"node_modules/@napi-rs/canvas-android-arm64": {
"version": "0.1.85",
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-0.1.85.tgz",
"integrity": "sha512-+br7+cFkiZHTn9en+u3wtvGMW2Fn7TJE1Kru4QsOtCgIKZ9Lg9AeFCqCdkRNz/cW/0967s2pJT/B8t900pgvFQ==",
"version": "0.1.86",
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-0.1.86.tgz",
"integrity": "sha512-IjkZFKUr6GzMzzrawJaN3v+yY3Fvpa71e0DcbePfxWelFKnESIir+XUcdAbim29JOd0JE0/hQJdfUCb5t/Fjrw==",
"cpu": [
"arm64"
],
@ -1038,12 +1038,16 @@
],
"engines": {
"node": ">= 10"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/Brooooooklyn"
}
},
"node_modules/@napi-rs/canvas-darwin-arm64": {
"version": "0.1.85",
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-0.1.85.tgz",
"integrity": "sha512-YPJrbThQsUDfS4z69m0xhlarbJ3BRyYx1LsVw6dotjhHywz2d7KVeFUXlJvSf+knHBV+FgZtaGEQ39MJZXn5qw==",
"version": "0.1.86",
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-0.1.86.tgz",
"integrity": "sha512-PUCxDq0wSSJbtaOqoKj3+t5tyDbtxWumziOTykdn3T839hu6koMaBFpGk9lXpsGaPNgyFpPqjxhtsPljBGnDHg==",
"cpu": [
"arm64"
],
@ -1054,12 +1058,16 @@
],
"engines": {
"node": ">= 10"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/Brooooooklyn"
}
},
"node_modules/@napi-rs/canvas-darwin-x64": {
"version": "0.1.85",
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-0.1.85.tgz",
"integrity": "sha512-Ak/h0lf3S0Yv/AqYvTHwKoVeUsxzqC2L6ZLkcLBvsYWLOqMwdtlp6lAgz82ETtJcpsY6+g2Q9Ub25QWBQu8k0Q==",
"version": "0.1.86",
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-0.1.86.tgz",
"integrity": "sha512-rlCFLv4Rrg45qFZq7mysrKnsUbMhwdNg3YPuVfo9u4RkOqm7ooAJvdyDFxiqfSsJJTqupYqa9VQCUt8WKxKhNQ==",
"cpu": [
"x64"
],
@ -1070,12 +1078,16 @@
],
"engines": {
"node": ">= 10"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/Brooooooklyn"
}
},
"node_modules/@napi-rs/canvas-linux-arm-gnueabihf": {
"version": "0.1.85",
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-0.1.85.tgz",
"integrity": "sha512-TzOv8ZZoNJS/M374Si4jWO/CgUhceEhAwiv1hRS3rVoGuxzcAoeUVgrT0a5FiozwGvO7WavO/ewjfZaFbZ3B9w==",
"version": "0.1.86",
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-0.1.86.tgz",
"integrity": "sha512-6xWwyMc9BlDBt+9XHN/GzUo3MozHta/2fxQHMb80x0K2zpZuAdDKUYHmYzx9dFWDY3SbPYnx6iRlQl6wxnwS1w==",
"cpu": [
"arm"
],
@ -1086,12 +1098,16 @@
],
"engines": {
"node": ">= 10"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/Brooooooklyn"
}
},
"node_modules/@napi-rs/canvas-linux-arm64-gnu": {
"version": "0.1.85",
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-0.1.85.tgz",
"integrity": "sha512-EuWX5tDk3vzL7dthAVx767LptXL6X32oiH82WU/yj4WZx0Yl7wU4PEjLBJTgNvWaWr1a8k+GB6MCkJs8NmxvrA==",
"version": "0.1.86",
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-0.1.86.tgz",
"integrity": "sha512-r2OX3w50xHxrToTovOSQWwkVfSq752CUzH9dzlVXyr8UDKFV8dMjfa9hePXvAJhN3NBp4TkHcGx15QCdaCIwnA==",
"cpu": [
"arm64"
],
@ -1102,12 +1118,16 @@
],
"engines": {
"node": ">= 10"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/Brooooooklyn"
}
},
"node_modules/@napi-rs/canvas-linux-arm64-musl": {
"version": "0.1.85",
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-0.1.85.tgz",
"integrity": "sha512-rwqWTac7UQWBEvSaiRsfujo/N34JyP+SKnJM5rwzx1mEb3g1N6Qdatd2yAGAMFO2Ck7BM9hX0Q2+Rpag5z5Iqg==",
"version": "0.1.86",
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-0.1.86.tgz",
"integrity": "sha512-jbXuh8zVFUPw6a9SGpgc6EC+fRbGGyP1NFfeQiVqGLs6bN93ROtPLPL6MH9Bp6yt0CXUFallk2vgKdWDbmW+bw==",
"cpu": [
"arm64"
],
@ -1118,12 +1138,16 @@
],
"engines": {
"node": ">= 10"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/Brooooooklyn"
}
},
"node_modules/@napi-rs/canvas-linux-riscv64-gnu": {
"version": "0.1.85",
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-0.1.85.tgz",
"integrity": "sha512-PkpO9MhVwmG6ZLCdi3GJWlon/Qyj5qb+lB+u4RMGEfCfcaaniKBoqUoMRTb2GWWbxzZaF5eVTHTpxZF6sB8ivg==",
"version": "0.1.86",
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-0.1.86.tgz",
"integrity": "sha512-9IwHR2qbq2HceM9fgwyL7x37Jy3ptt1uxvikQEuWR0FisIx9QEdt7F3huljCky76aoouF2vSd0R2fHo3ESRoPw==",
"cpu": [
"riscv64"
],
@ -1134,12 +1158,16 @@
],
"engines": {
"node": ">= 10"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/Brooooooklyn"
}
},
"node_modules/@napi-rs/canvas-linux-x64-gnu": {
"version": "0.1.85",
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-0.1.85.tgz",
"integrity": "sha512-s/W7hh1n89kDIIJCAHP0PofsmfjP28QxWiEH9wEvoJAblx9u8obd6qyZf6jqh3WDoLm5Fx+upBXhA8O8GgpyDQ==",
"version": "0.1.86",
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-0.1.86.tgz",
"integrity": "sha512-Jor+rhRN6ubix+D2QkNn9XlPPVAYl+2qFrkZ4oZN9UgtqIUZ+n+HljxhlkkDFRaX1mlxXOXPQjxaZg17zDSFcQ==",
"cpu": [
"x64"
],
@ -1150,12 +1178,16 @@
],
"engines": {
"node": ">= 10"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/Brooooooklyn"
}
},
"node_modules/@napi-rs/canvas-linux-x64-musl": {
"version": "0.1.85",
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-0.1.85.tgz",
"integrity": "sha512-LEEkaaraB/bhKiVf7qXmyjrNXI/hRVKpBn1bQP6IQsypyJnB+Y2HmzLXAt6cht+4Lon8lGLacE76fU5hs9vUFw==",
"version": "0.1.86",
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-0.1.86.tgz",
"integrity": "sha512-A28VTy91DbclopSGZ2tIon3p8hcVI1JhnNpDpJ5N9rYlUnVz1WQo4waEMh+FICTZF07O3coxBNZc4Vu4doFw7A==",
"cpu": [
"x64"
],
@ -1166,12 +1198,16 @@
],
"engines": {
"node": ">= 10"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/Brooooooklyn"
}
},
"node_modules/@napi-rs/canvas-win32-arm64-msvc": {
"version": "0.1.85",
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-arm64-msvc/-/canvas-win32-arm64-msvc-0.1.85.tgz",
"integrity": "sha512-w3PVRv4suL/kErNg8Roz5f/Sow/hC7LxeOeo3jTp1iPHEnp6Gn7EvDvMPhJaI5piQqQ6i2BR/4LJHA/Mapf8vw==",
"version": "0.1.86",
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-arm64-msvc/-/canvas-win32-arm64-msvc-0.1.86.tgz",
"integrity": "sha512-q6G1YXUt3gBCAS2bcDMCaBL4y20di8eVVBi1XhjUqZSVyZZxxwIuRQHy31NlPJUCMiyNiMuc6zeI0uqgkWwAmA==",
"cpu": [
"arm64"
],
@ -1182,12 +1218,16 @@
],
"engines": {
"node": ">= 10"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/Brooooooklyn"
}
},
"node_modules/@napi-rs/canvas-win32-x64-msvc": {
"version": "0.1.85",
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-0.1.85.tgz",
"integrity": "sha512-6QqEBlJ5/rfb68ORlgNOsN+Wefx+kfMNmbzr2HxEM+M94hdBxkzvkLAfY/MxiLk3TCUBeGLFh9t0j8ZC5MKS1g==",
"version": "0.1.86",
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-0.1.86.tgz",
"integrity": "sha512-X0g46uRVgnvCM1cOjRXAOSFSG63ktUFIf/TIfbKCUc7QpmYUcHmSP9iR6DGOYfk+SggLsXoJCIhPTotYeZEAmg==",
"cpu": [
"x64"
],
@ -1198,6 +1238,10 @@
],
"engines": {
"node": ">= 10"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/Brooooooklyn"
}
},
"node_modules/@parcel/watcher": {
@ -6403,11 +6447,11 @@
},
"packages/agent": {
"name": "@mariozechner/pi-agent-core",
"version": "0.25.2",
"version": "0.25.3",
"license": "MIT",
"dependencies": {
"@mariozechner/pi-ai": "^0.25.2",
"@mariozechner/pi-tui": "^0.25.2"
"@mariozechner/pi-ai": "^0.25.3",
"@mariozechner/pi-tui": "^0.25.3"
},
"devDependencies": {
"@types/node": "^24.3.0",
@ -6437,7 +6481,7 @@
},
"packages/ai": {
"name": "@mariozechner/pi-ai",
"version": "0.25.2",
"version": "0.25.3",
"license": "MIT",
"dependencies": {
"@anthropic-ai/sdk": "0.71.2",
@ -6479,12 +6523,12 @@
},
"packages/coding-agent": {
"name": "@mariozechner/pi-coding-agent",
"version": "0.25.2",
"version": "0.25.3",
"license": "MIT",
"dependencies": {
"@mariozechner/pi-agent-core": "^0.25.2",
"@mariozechner/pi-ai": "^0.25.2",
"@mariozechner/pi-tui": "^0.25.2",
"@mariozechner/pi-agent-core": "^0.25.3",
"@mariozechner/pi-ai": "^0.25.3",
"@mariozechner/pi-tui": "^0.25.3",
"chalk": "^5.5.0",
"cli-highlight": "^2.1.11",
"diff": "^8.0.2",
@ -6524,13 +6568,13 @@
},
"packages/mom": {
"name": "@mariozechner/pi-mom",
"version": "0.25.2",
"version": "0.25.3",
"license": "MIT",
"dependencies": {
"@anthropic-ai/sandbox-runtime": "^0.0.16",
"@mariozechner/pi-agent-core": "^0.25.2",
"@mariozechner/pi-ai": "^0.25.2",
"@mariozechner/pi-coding-agent": "^0.25.2",
"@mariozechner/pi-agent-core": "^0.25.3",
"@mariozechner/pi-ai": "^0.25.3",
"@mariozechner/pi-coding-agent": "^0.25.3",
"@sinclair/typebox": "^0.34.0",
"@slack/socket-mode": "^2.0.0",
"@slack/web-api": "^7.0.0",
@ -6569,10 +6613,10 @@
},
"packages/pods": {
"name": "@mariozechner/pi",
"version": "0.25.2",
"version": "0.25.3",
"license": "MIT",
"dependencies": {
"@mariozechner/pi-agent-core": "^0.25.2",
"@mariozechner/pi-agent-core": "^0.25.3",
"chalk": "^5.5.0"
},
"bin": {
@ -6585,7 +6629,7 @@
},
"packages/proxy": {
"name": "@mariozechner/pi-proxy",
"version": "0.25.2",
"version": "0.25.3",
"dependencies": {
"@hono/node-server": "^1.14.0",
"hono": "^4.6.16"
@ -6601,7 +6645,7 @@
},
"packages/tui": {
"name": "@mariozechner/pi-tui",
"version": "0.25.2",
"version": "0.25.3",
"license": "MIT",
"dependencies": {
"@types/mime-types": "^2.1.4",
@ -6645,12 +6689,12 @@
},
"packages/web-ui": {
"name": "@mariozechner/pi-web-ui",
"version": "0.25.2",
"version": "0.25.3",
"license": "MIT",
"dependencies": {
"@lmstudio/sdk": "^1.5.0",
"@mariozechner/pi-ai": "^0.25.2",
"@mariozechner/pi-tui": "^0.25.2",
"@mariozechner/pi-ai": "^0.25.3",
"@mariozechner/pi-tui": "^0.25.3",
"docx-preview": "^0.3.7",
"jszip": "^3.10.1",
"lucide": "^0.544.0",
@ -6671,7 +6715,7 @@
},
"packages/web-ui/example": {
"name": "pi-web-ui-example",
"version": "1.13.2",
"version": "1.13.3",
"dependencies": {
"@mariozechner/mini-lit": "^0.2.0",
"@mariozechner/pi-ai": "file:../../ai",

View file

@ -1,6 +1,6 @@
{
"name": "@mariozechner/pi-agent-core",
"version": "0.25.2",
"version": "0.25.3",
"description": "General-purpose agent with transport abstraction, state management, and attachment support",
"type": "module",
"main": "./dist/index.js",
@ -18,8 +18,8 @@
"prepublishOnly": "npm run clean && npm run build"
},
"dependencies": {
"@mariozechner/pi-ai": "^0.25.2",
"@mariozechner/pi-tui": "^0.25.2"
"@mariozechner/pi-ai": "^0.25.3",
"@mariozechner/pi-tui": "^0.25.3"
},
"keywords": [
"ai",

View file

@ -1,6 +1,6 @@
{
"name": "@mariozechner/pi-ai",
"version": "0.25.2",
"version": "0.25.3",
"description": "Unified LLM API with automatic model discovery and provider configuration",
"type": "module",
"main": "./dist/index.js",

View file

@ -2,6 +2,8 @@
## [Unreleased]
## [0.25.3] - 2025-12-21
### Added
- **Gemini 3 preview models**: Added `gemini-3-pro-preview` and `gemini-3-flash-preview` to the google-gemini-cli provider. ([#264](https://github.com/badlogic/pi-mono/pull/264) by [@LukeFost](https://github.com/LukeFost))

View file

@ -1,6 +1,6 @@
{
"name": "@mariozechner/pi-coding-agent",
"version": "0.25.2",
"version": "0.25.3",
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
"type": "module",
"piConfig": {
@ -39,9 +39,9 @@
"prepublishOnly": "npm run clean && npm run build"
},
"dependencies": {
"@mariozechner/pi-agent-core": "^0.25.2",
"@mariozechner/pi-ai": "^0.25.2",
"@mariozechner/pi-tui": "^0.25.2",
"@mariozechner/pi-agent-core": "^0.25.3",
"@mariozechner/pi-ai": "^0.25.3",
"@mariozechner/pi-tui": "^0.25.3",
"chalk": "^5.5.0",
"cli-highlight": "^2.1.11",
"diff": "^8.0.2",

View file

@ -1,6 +1,6 @@
{
"name": "@mariozechner/pi-mom",
"version": "0.25.2",
"version": "0.25.3",
"description": "Slack bot that delegates messages to the pi coding agent",
"type": "module",
"bin": {
@ -21,9 +21,9 @@
},
"dependencies": {
"@anthropic-ai/sandbox-runtime": "^0.0.16",
"@mariozechner/pi-agent-core": "^0.25.2",
"@mariozechner/pi-ai": "^0.25.2",
"@mariozechner/pi-coding-agent": "^0.25.2",
"@mariozechner/pi-agent-core": "^0.25.3",
"@mariozechner/pi-ai": "^0.25.3",
"@mariozechner/pi-coding-agent": "^0.25.3",
"@sinclair/typebox": "^0.34.0",
"@slack/socket-mode": "^2.0.0",
"@slack/web-api": "^7.0.0",

View file

@ -1,6 +1,6 @@
{
"name": "@mariozechner/pi",
"version": "0.25.2",
"version": "0.25.3",
"description": "CLI tool for managing vLLM deployments on GPU pods",
"type": "module",
"bin": {
@ -34,7 +34,7 @@
"node": ">=20.0.0"
},
"dependencies": {
"@mariozechner/pi-agent-core": "^0.25.2",
"@mariozechner/pi-agent-core": "^0.25.3",
"chalk": "^5.5.0"
},
"devDependencies": {}

View file

@ -1,6 +1,6 @@
{
"name": "@mariozechner/pi-proxy",
"version": "0.25.2",
"version": "0.25.3",
"type": "module",
"description": "CORS and authentication proxy for pi-ai",
"main": "dist/index.js",

View file

@ -1,6 +1,6 @@
{
"name": "@mariozechner/pi-tui",
"version": "0.25.2",
"version": "0.25.3",
"description": "Terminal User Interface library with differential rendering for efficient text-based applications",
"type": "module",
"main": "dist/index.js",

View file

@ -1,6 +1,6 @@
{
"name": "pi-web-ui-example",
"version": "1.13.2",
"version": "1.13.3",
"private": true,
"type": "module",
"scripts": {

View file

@ -1,6 +1,6 @@
{
"name": "@mariozechner/pi-web-ui",
"version": "0.25.2",
"version": "0.25.3",
"description": "Reusable web UI components for AI chat interfaces powered by @mariozechner/pi-ai",
"type": "module",
"main": "dist/index.js",
@ -18,8 +18,8 @@
},
"dependencies": {
"@lmstudio/sdk": "^1.5.0",
"@mariozechner/pi-ai": "^0.25.2",
"@mariozechner/pi-tui": "^0.25.2",
"@mariozechner/pi-ai": "^0.25.3",
"@mariozechner/pi-tui": "^0.25.3",
"docx-preview": "^0.3.7",
"jszip": "^3.10.1",
"lucide": "^0.544.0",

321
plan.md
View file

@ -1,321 +0,0 @@
# Google Cloud Code Assist Provider Implementation Plan
## Overview
Add support for Gemini CLI / Antigravity authentication, which uses Google's Cloud Code Assist API (`cloudcode-pa.googleapis.com`) to access Gemini and Claude models through a unified gateway.
## References
- Antigravity API Spec: https://github.com/NoeFabris/opencode-antigravity-auth/blob/main/docs/ANTIGRAVITY_API_SPEC.md
- Gemini CLI Auth: https://github.com/jenslys/opencode-gemini-auth
- Antigravity Auth: https://github.com/NoeFabris/opencode-antigravity-auth
## Key Differences from Standard Google Provider
1. **Endpoint**: `cloudcode-pa.googleapis.com/v1internal:streamGenerateContent?alt=sse`
2. **Auth**: OAuth token (not API key)
3. **Request format**: Wrapped in `{ project, model, request: {...} }`
4. **Response format**: Wrapped in `{ response: {...} }` (needs unwrapping)
5. **Headers**: Requires `User-Agent`, `X-Goog-Api-Client`, `Client-Metadata`
## OAuth Details
- **Client ID**: `681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com`
- **Client Secret**: `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`
- **Redirect URI**: `http://localhost:8085/oauth2callback`
- **Scopes**: `cloud-platform`, `userinfo.email`, `userinfo.profile`
- **Token URL**: `https://oauth2.googleapis.com/token`
- **Auth URL**: `https://accounts.google.com/o/oauth2/v2/auth`
## Available Models
| Model ID | Type | Context | Output | Reasoning |
|----------|------|---------|--------|-----------|
| gemini-3-pro-high | Gemini | 1M | 64K | Yes |
| gemini-3-pro-low | Gemini | 1M | 64K | Yes |
| gemini-3-flash | Gemini | 1M | 64K | No |
| claude-sonnet-4-5 | Claude | 200K | 64K | No |
| claude-sonnet-4-5-thinking | Claude | 200K | 64K | Yes |
| claude-opus-4-5-thinking | Claude | 200K | 64K | Yes |
| gpt-oss-120b-medium | GPT-OSS | 128K | 32K | No |
All models support: text, image, pdf input; text output; cost is $0 (uses Google account quota)
---
## Implementation Steps
### Phase 1: AI Provider (COMPLETED)
Steps 1-8 completed. The provider is implemented in:
- `packages/ai/src/providers/google-cloud-code-assist.ts`
- `packages/ai/src/providers/google-shared.ts`
- Models added to `packages/ai/scripts/generate-models.ts`
---
### Step 1: Update types.ts
File: `packages/ai/src/types.ts`
Add new API type:
```typescript
export type Api = "openai-completions" | "openai-responses" | "anthropic-messages" | "google-generative-ai" | "google-cloud-code-assist";
```
### Step 2: Create google-shared.ts
File: `packages/ai/src/providers/google-shared.ts`
Extract from `google.ts`:
- `convertMessages()` - convert internal messages to Gemini Content[] format
- `convertTools()` - convert tools to Gemini function declarations
- `mapToolChoice()` - map tool choice to Gemini enum
- `mapStopReason()` - map Gemini finish reason to our stop reason
- Shared types and imports
Make functions generic to work with both `google-generative-ai` and `google-cloud-code-assist` API types.
### Step 3: Update google.ts
File: `packages/ai/src/providers/google.ts`
- Import shared functions from `google-shared.ts`
- Remove extracted functions
- Keep: `createClient()`, `buildParams()`, `streamGoogle()`
### Step 4: Create google-cloud-code-assist.ts
File: `packages/ai/src/providers/google-cloud-code-assist.ts`
Implement:
```typescript
export interface GoogleCloudCodeAssistOptions extends StreamOptions {
toolChoice?: "auto" | "none" | "any";
thinking?: {
enabled: boolean;
budgetTokens?: number;
};
projectId?: string; // Google Cloud project ID
}
export const streamGoogleCloudCodeAssist: StreamFunction<"google-cloud-code-assist"> = (
model: Model<"google-cloud-code-assist">,
context: Context,
options?: GoogleCloudCodeAssistOptions,
): AssistantMessageEventStream => {
// Implementation
};
```
Key implementation details:
1. **Build request body**:
```json
{
"project": "{projectId}",
"model": "{modelId}",
"request": {
"contents": [...],
"systemInstruction": { "parts": [{ "text": "..." }] },
"generationConfig": { ... },
"tools": [...]
}
}
```
2. **Headers**:
```
Authorization: Bearer {accessToken}
Content-Type: application/json
Accept: text/event-stream
User-Agent: google-api-nodejs-client/9.15.1
X-Goog-Api-Client: gl-node/22.17.0
Client-Metadata: ideType=IDE_UNSPECIFIED,platform=PLATFORM_UNSPECIFIED,pluginType=GEMINI
```
3. **Endpoint**: `https://cloudcode-pa.googleapis.com/v1internal:streamGenerateContent?alt=sse`
4. **Parse SSE response**:
- Each line: `data: {"response": {...}, "traceId": "..."}`
- Extract `response` object, which has same structure as standard Gemini response
- Handle thinking parts with `thought: true` and `thoughtSignature`
5. **Use shared functions** for message/tool conversion and stop reason mapping
### Step 5: Update stream.ts
File: `packages/ai/src/stream.ts`
Add case for new provider:
```typescript
import { streamGoogleCloudCodeAssist } from "./providers/google-cloud-code-assist.js";
// In the switch/case or if/else chain:
case "google-cloud-code-assist":
return streamGoogleCloudCodeAssist(model, context, {
...options,
// map reasoning to thinking config
});
```
### Step 6: Update models.ts
File: `packages/ai/src/models.ts`
Add to `xhighSupportedModels` if applicable (check if any models support xhigh).
### Step 7: Add models to generate-models.ts
File: `packages/ai/scripts/generate-models.ts`
Add hardcoded models:
```typescript
const googleCloudCodeAssistModels: Model<"google-cloud-code-assist">[] = [
{
id: "gemini-3-pro-high",
provider: "google-cloud-code-assist",
api: "google-cloud-code-assist",
name: "Gemini 3 Pro High",
contextWindow: 1048576,
maxOutputTokens: 65535,
pricing: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
input: ["text", "image", "pdf"],
output: ["text"],
reasoning: true,
},
// ... other models
];
```
### Step 8: Update index.ts exports
File: `packages/ai/src/index.ts`
Export new provider:
```typescript
export { streamGoogleCloudCodeAssist, type GoogleCloudCodeAssistOptions } from "./providers/google-cloud-code-assist.js";
```
---
## Phase 2: OAuth Flow in coding-agent
### Step 9: Create google-cloud.ts OAuth handler
File: `packages/coding-agent/src/core/oauth/google-cloud.ts`
Implement:
```typescript
import { createHash, randomBytes } from "crypto";
import { createServer } from "http";
import { type OAuthCredentials, saveOAuthCredentials } from "./storage.js";
const CLIENT_ID = "681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com";
const CLIENT_SECRET = "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";
const REDIRECT_URI = "http://localhost:8085/oauth2callback";
const SCOPES = [
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile",
];
const AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
const TOKEN_URL = "https://oauth2.googleapis.com/token";
export async function loginGoogleCloud(
onAuth: (info: { url: string; instructions?: string }) => void,
onProgress?: (message: string) => void,
): Promise<OAuthCredentials & { projectId?: string }> {
// 1. Generate PKCE
// 2. Start local server on port 8085
// 3. Build auth URL and call onAuth
// 4. Wait for callback with code
// 5. Exchange code for tokens
// 6. Discover/provision project via loadCodeAssist endpoint
// 7. Return credentials with projectId
}
export async function refreshGoogleCloudToken(refreshToken: string): Promise<OAuthCredentials> {
// Refresh token flow
}
// Project discovery
async function discoverProject(accessToken: string): Promise<string> {
// Call /v1internal:loadCodeAssist to get project ID
// Or /v1internal:onboardUser if needed
}
```
### Step 10: Update oauth/index.ts
File: `packages/coding-agent/src/core/oauth/index.ts`
- Add `"google-cloud"` to `SupportedOAuthProvider`
- Add to `getOAuthProviders()` list
- Add case in `login()` function
- Add case in `refreshToken()` function
### Step 11: Update oauth/storage.ts
File: `packages/coding-agent/src/core/oauth/storage.ts`
Extend `OAuthCredentials` to include optional `projectId`:
```typescript
export interface OAuthCredentials {
type: "oauth";
refresh: string;
access: string;
expires: number;
enterpriseUrl?: string;
projectId?: string; // For Google Cloud
}
```
### Step 12: Update model-config.ts
File: `packages/coding-agent/src/core/model-config.ts`
Add logic to get API key for `google-cloud-code-assist` provider:
- Check for OAuth token via `getOAuthToken("google-cloud")`
- Return the access token as the "API key"
---
## Phase 3: Testing
### Manual Testing
1. Run `pi` and use `/login` to authenticate with Google
2. Select a google-cloud-code-assist model
3. Send a message and verify streaming works
4. Test tool calling
5. Test thinking models
### Verification Points
- [ ] OAuth flow completes successfully
- [ ] Token refresh works
- [ ] Streaming text works
- [ ] Thinking blocks are parsed correctly
- [ ] Tool calls work
- [ ] Tool results are sent correctly
- [ ] Error handling works (rate limits, auth errors)
---
## Notes
### systemInstruction Format
Must be object with parts, NOT plain string:
```json
{
"systemInstruction": {
"parts": [{ "text": "You are a helpful assistant." }]
}
}
```
### Tool Name Rules
- Must start with letter or underscore
- Allowed: a-zA-Z0-9, underscores, dots, colons, dashes
- Max 64 chars
- No slashes or spaces
### Thinking Config
```json
{
"generationConfig": {
"thinkingConfig": {
"thinkingBudget": 8000,
"includeThoughts": true
}
}
}
```
### Response Unwrapping
SSE lines come as:
```
data: {"response": {...}, "traceId": "..."}
```
Need to extract `response` object which matches standard Gemini format.

File diff suppressed because one or more lines are too long