@ssweens/pi-vertex 1.0.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/LICENSE +21 -0
- package/README.md +226 -0
- package/auth.ts +108 -0
- package/config.ts +63 -0
- package/index.ts +134 -0
- package/models/claude.ts +246 -0
- package/models/gemini.ts +162 -0
- package/models/index.ts +24 -0
- package/models/maas.ts +462 -0
- package/package.json +47 -0
- package/screenshot.png +0 -0
- package/streaming/gemini.ts +164 -0
- package/streaming/index.ts +25 -0
- package/streaming/maas.ts +97 -0
- package/types.ts +76 -0
- package/utils.ts +194 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ssweens
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# pi-vertex
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@ssweens/pi-vertex)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
pi install @ssweens/pi-vertex
|
|
10
|
+
export GOOGLE_CLOUD_PROJECT=your-project-id
|
|
11
|
+
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/key.json
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Set your GCP project and credentials. Vertex AI models (Gemini, Claude, Llama, DeepSeek, Qwen, Mistral, and others) appear in pi's model selector, billed through your GCP project.
|
|
15
|
+
|
|
16
|
+
## Features
|
|
17
|
+
|
|
18
|
+
- **43 models** across 4 categories:
|
|
19
|
+
- **Gemini** (8): 3.1 Pro, 3 Pro, 3 Flash, 2.5 Pro, 2.5 Flash, 2.0 Flash, and more
|
|
20
|
+
- **Claude** (12): Opus 4.6, Sonnet 4.6, 4.5, 4.1, 4, 3.7 Sonnet, 3.5 Sonnet v2, 3.5 Sonnet, 3 Haiku
|
|
21
|
+
- **Llama** (3): 4 Maverick, 4 Scout, 3.3 70B
|
|
22
|
+
- **Other MaaS** (20): AI21 Jamba, Mistral, DeepSeek, Qwen, OpenAI GPT-OSS, Kimi, MiniMax, GLM
|
|
23
|
+
|
|
24
|
+
- **Unified streaming**: Single provider, multiple model families
|
|
25
|
+
- **Full tool calling support**: All models marked with tools support
|
|
26
|
+
- **Automatic auth**: Uses Google Application Default Credentials
|
|
27
|
+
- **Region awareness**: Global endpoints where supported, regional where required
|
|
28
|
+
- **Pricing tracking**: Built-in cost per token for all models
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Via pi (recommended)
|
|
34
|
+
pi install @ssweens/pi-vertex
|
|
35
|
+
|
|
36
|
+
# Or via npm
|
|
37
|
+
npm install @ssweens/pi-vertex
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Setup
|
|
41
|
+
|
|
42
|
+
### 1. Authenticate with Google Cloud
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# Option A: User credentials (development)
|
|
46
|
+
gcloud auth application-default login
|
|
47
|
+
|
|
48
|
+
# Option B: Service account (production)
|
|
49
|
+
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account-key.json
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 2. Set environment variables
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# Required: Your GCP project ID
|
|
56
|
+
export GOOGLE_CLOUD_PROJECT=your-project-id
|
|
57
|
+
|
|
58
|
+
# Optional: Override default region
|
|
59
|
+
export GOOGLE_CLOUD_LOCATION=us-central1
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 3. Configuration file (optional)
|
|
63
|
+
|
|
64
|
+
For persistent settings, create `~/.pi/agent/settings/pi-vertex.json`:
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"googleCloudProject": "my-gcp-project",
|
|
69
|
+
"googleCloudLocation": "us-central1",
|
|
70
|
+
"googleApplicationCredentials": "/path/to/service-account.json"
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Config file values take priority over environment variables.
|
|
75
|
+
|
|
76
|
+
### 4. Verify setup
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
pi --provider vertex --model gemini-2.5-pro --version
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Usage
|
|
83
|
+
|
|
84
|
+
### Command line
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# Use any supported model
|
|
88
|
+
pi --provider vertex --model claude-opus-4-6
|
|
89
|
+
pi --provider vertex --model gemini-2.5-pro
|
|
90
|
+
pi --provider vertex --model llama-4-maverick
|
|
91
|
+
pi --provider vertex --model deepseek-v3.2
|
|
92
|
+
|
|
93
|
+
# With options
|
|
94
|
+
pi --provider vertex --model claude-sonnet-4-6 --reasoning high
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Shell alias (recommended)
|
|
98
|
+
|
|
99
|
+
Add to `~/.bashrc` or `~/.zshrc`:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
# Claude 4.6 Opus
|
|
103
|
+
alias pic="GOOGLE_CLOUD_PROJECT=your-project pi --provider vertex --model claude-opus-4-6"
|
|
104
|
+
|
|
105
|
+
# Gemini 2.5 Pro
|
|
106
|
+
alias pig="GOOGLE_CLOUD_PROJECT=your-project pi --provider vertex --model gemini-2.5-pro"
|
|
107
|
+
|
|
108
|
+
# Llama 4 Maverick
|
|
109
|
+
alias pil="GOOGLE_CLOUD_PROJECT=your-project pi --provider vertex --model llama-4-maverick"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Model Reference
|
|
113
|
+
|
|
114
|
+
### Gemini Models
|
|
115
|
+
|
|
116
|
+
| Model | Context | Max Tokens | Input | Reasoning | Price (in/out) |
|
|
117
|
+
|-------|---------|------------|-------|-----------|----------------|
|
|
118
|
+
| gemini-3.1-pro | 1M | 64,000 | text, image | ✅ | $2.00/$12.00 |
|
|
119
|
+
| gemini-3-pro | 2M | 8,192 | text, image | ✅ | $1.25/$10.00 |
|
|
120
|
+
| gemini-3-flash | 1M | 8,192 | text, image | ✅ | $0.15/$0.60 |
|
|
121
|
+
| gemini-2.5-pro | 1M | 64,000 | text, image | ✅ | $1.25/$10.00 |
|
|
122
|
+
| gemini-2.5-flash | 1M | 64,000 | text, image | ✅ | $0.30/$2.50 |
|
|
123
|
+
| gemini-2.5-flash-lite | 1M | 64,000 | text, image | ✅ | $0.10/$0.40 |
|
|
124
|
+
| gemini-2.0-flash | 1M | 8,192 | text, image | ❌ | $0.15/$0.60 |
|
|
125
|
+
| gemini-2.0-flash-lite | 1M | 8,192 | text | ❌ | $0.075/$0.30 |
|
|
126
|
+
|
|
127
|
+
### Claude Models
|
|
128
|
+
|
|
129
|
+
| Model | Context | Max Tokens | Input | Reasoning | Price (in/out) | Region |
|
|
130
|
+
|-------|---------|------------|-------|-----------|----------------|--------|
|
|
131
|
+
| claude-opus-4-6 | 200K | 32,000 | text, image | ✅ | $5.00/$25.00 | global |
|
|
132
|
+
| claude-sonnet-4-6 | 200K | 64,000 | text, image | ✅ | $3.00/$15.00 | global |
|
|
133
|
+
| claude-opus-4-5 | 200K | 32,000 | text, image | ✅ | $5.00/$25.00 | global |
|
|
134
|
+
| claude-sonnet-4-5 | 200K | 64,000 | text, image | ✅ | $3.00/$15.00 | global |
|
|
135
|
+
| claude-haiku-4-5 | 200K | 64,000 | text, image | ✅ | $1.00/$5.00 | global |
|
|
136
|
+
| claude-opus-4-1 | 200K | 32,000 | text, image | ✅ | $15.00/$75.00 | us-east5 |
|
|
137
|
+
| claude-opus-4 | 200K | 32,000 | text, image | ✅ | $15.00/$75.00 | us-east5 |
|
|
138
|
+
| claude-sonnet-4 | 200K | 64,000 | text, image | ✅ | $3.00/$15.00 | us-east5 |
|
|
139
|
+
| claude-3-7-sonnet | 200K | 64,000 | text, image | ✅ | $3.00/$15.00 | us-east5 |
|
|
140
|
+
| claude-3-5-sonnet-v2 | 200K | 8,192 | text, image | ❌ | $3.00/$15.00 | us-east5 |
|
|
141
|
+
| claude-3-5-sonnet | 200K | 8,192 | text, image | ❌ | $3.00/$15.00 | us-east5 |
|
|
142
|
+
| claude-3-haiku | 200K | 4,096 | text | ❌ | $0.25/$1.25 | us-east5 |
|
|
143
|
+
|
|
144
|
+
### Llama Models
|
|
145
|
+
|
|
146
|
+
| Model | Context | Max Tokens | Input | Reasoning | Price (in/out) | Region |
|
|
147
|
+
|-------|---------|------------|-------|-----------|----------------|--------|
|
|
148
|
+
| llama-4-maverick | 524K | 32,000 | text | ✅ | $0.35/$1.15 | global |
|
|
149
|
+
| llama-4-scout | 1,310K | 32,000 | text | ✅ | $0.25/$0.70 | global |
|
|
150
|
+
| llama-3.3-70b | 128K | 8,192 | text | ❌ | $0.72/$0.72 | global |
|
|
151
|
+
|
|
152
|
+
### Other MaaS Models
|
|
153
|
+
|
|
154
|
+
| Model | Context | Publisher | Price (in/out) | Region |
|
|
155
|
+
|-------|---------|-----------|----------------|--------|
|
|
156
|
+
| jamba-1.5-large | 256K | ai21 | $2.00/$8.00 | global |
|
|
157
|
+
| jamba-1.5-mini | 256K | ai21 | $0.20/$0.40 | global |
|
|
158
|
+
| mistral-medium-3 | 128K | mistralai | $0.40/$2.00 | global |
|
|
159
|
+
| mistral-small-3.1 | 128K | mistralai | $0.10/$0.30 | global |
|
|
160
|
+
| mistral-ocr | 30 pages | mistralai | $0.0005/page | global |
|
|
161
|
+
| codestral-2 | 128K | mistralai | $0.30/$0.90 | global |
|
|
162
|
+
| deepseek-v3.2 | 163K | deepseek-ai | $0.56/$1.68 | global |
|
|
163
|
+
| deepseek-v3.1 | 163K | deepseek-ai | $0.60/$1.70 | global |
|
|
164
|
+
| deepseek-r1 | 163K | deepseek-ai | $1.35/$5.40 | global |
|
|
165
|
+
| deepseek-ocr | Varies | deepseek-ai | $0.0003/page | global |
|
|
166
|
+
| qwen3-235b | 262K | qwen | $0.22/$0.88 | global |
|
|
167
|
+
| qwen3-next-instruct | 262K | qwen | $0.15/$1.20 | global |
|
|
168
|
+
| qwen3-next-thinking | 262K | qwen | $0.15/$1.20 | global |
|
|
169
|
+
| qwen3-coder | 262K | qwen | $0.22/$1.80 | global |
|
|
170
|
+
| gpt-oss-120b | 131K | openai | $0.09/$0.36 | global |
|
|
171
|
+
| gpt-oss-20b | 131K | openai | $0.07/$0.25 | global |
|
|
172
|
+
| kimi-k2-thinking | 262K | moonshotai | $0.60/$2.50 | global |
|
|
173
|
+
| minimax-m2 | 196K | minimaxai | $0.30/$1.20 | global |
|
|
174
|
+
| glm-5 | 200K | zai-org | $1.00/$3.20 | global |
|
|
175
|
+
| glm-4.7 | 200K | zai-org | $0.60/$2.20 | global |
|
|
176
|
+
|
|
177
|
+
## Regional Endpoints
|
|
178
|
+
|
|
179
|
+
Models use different endpoints based on availability:
|
|
180
|
+
|
|
181
|
+
- **Global** (most models): `aiplatform.googleapis.com`
|
|
182
|
+
- **Regional** (older Claude models): `{region}-aiplatform.googleapis.com`
|
|
183
|
+
|
|
184
|
+
Default regions by model:
|
|
185
|
+
- Gemini: `global`
|
|
186
|
+
- Claude 4.6/4.5: `global`
|
|
187
|
+
- Claude 4/4.1/3.7/3.5/3: `us-east5`
|
|
188
|
+
- MaaS: `global`
|
|
189
|
+
|
|
190
|
+
Override with:
|
|
191
|
+
```bash
|
|
192
|
+
export GOOGLE_CLOUD_LOCATION=us-central1
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Architecture
|
|
196
|
+
|
|
197
|
+
```
|
|
198
|
+
┌─────────────┐
|
|
199
|
+
│ Pi │
|
|
200
|
+
└──────┬──────┘
|
|
201
|
+
│ registerProvider("vertex")
|
|
202
|
+
▼
|
|
203
|
+
┌─────────────┐
|
|
204
|
+
│ pi-vertex │
|
|
205
|
+
└──────┬──────┘
|
|
206
|
+
│ streamSimple(model, context, options)
|
|
207
|
+
▼
|
|
208
|
+
┌─────────────────────────────────────┐
|
|
209
|
+
│ Handler Dispatch │
|
|
210
|
+
├──────────────┬──────────────────────┤
|
|
211
|
+
│ Gemini │ MaaS │
|
|
212
|
+
│ (@google/ │ (OpenAI-compatible │
|
|
213
|
+
│ genai) │ endpoint) │
|
|
214
|
+
└──────────────┴──────────────────────┘
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Dependencies
|
|
218
|
+
|
|
219
|
+
- `@google/genai`: Google GenAI SDK for Gemini models
|
|
220
|
+
- `google-auth-library`: ADC authentication for all models
|
|
221
|
+
- `@mariozechner/pi-ai`: Peer dependency
|
|
222
|
+
- `@mariozechner/pi-coding-agent`: Peer dependency
|
|
223
|
+
|
|
224
|
+
## License
|
|
225
|
+
|
|
226
|
+
MIT
|
package/auth.ts
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication utilities for Vertex AI
|
|
3
|
+
* Uses Google Application Default Credentials (ADC)
|
|
4
|
+
*
|
|
5
|
+
* Resolution order for each value: config file → env var → default
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { GoogleAuth } from "google-auth-library";
|
|
9
|
+
import { existsSync } from "fs";
|
|
10
|
+
import { join } from "path";
|
|
11
|
+
import { homedir } from "os";
|
|
12
|
+
import type { AuthConfig } from "./types.js";
|
|
13
|
+
import { loadConfig, getConfigPath } from "./config.js";
|
|
14
|
+
|
|
15
|
+
const DEFAULT_ADC_PATH = join(homedir(), ".config", "gcloud", "application_default_credentials.json");
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Check if ADC credentials exist.
|
|
19
|
+
* Checks config credentialsFile → GOOGLE_APPLICATION_CREDENTIALS → default ADC path.
|
|
20
|
+
*/
|
|
21
|
+
export function hasAdcCredentials(): boolean {
|
|
22
|
+
const config = loadConfig();
|
|
23
|
+
const adcPath =
|
|
24
|
+
config.googleApplicationCredentials ||
|
|
25
|
+
process.env.GOOGLE_APPLICATION_CREDENTIALS ||
|
|
26
|
+
DEFAULT_ADC_PATH;
|
|
27
|
+
return existsSync(adcPath);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Resolve project ID.
|
|
32
|
+
* Checks config.googleCloudProject → GOOGLE_CLOUD_PROJECT → GCLOUD_PROJECT.
|
|
33
|
+
*/
|
|
34
|
+
export function resolveProjectId(): string | undefined {
|
|
35
|
+
const config = loadConfig();
|
|
36
|
+
return config.googleCloudProject || process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Resolve location/region.
|
|
41
|
+
* Checks config.googleCloudLocation → GOOGLE_CLOUD_LOCATION → CLOUD_ML_REGION → defaultLocation.
|
|
42
|
+
*/
|
|
43
|
+
export function resolveLocation(defaultLocation: string = "us-central1"): string {
|
|
44
|
+
const config = loadConfig();
|
|
45
|
+
return (
|
|
46
|
+
config.googleCloudLocation ||
|
|
47
|
+
process.env.GOOGLE_CLOUD_LOCATION ||
|
|
48
|
+
process.env.CLOUD_ML_REGION ||
|
|
49
|
+
defaultLocation
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Get authentication configuration.
|
|
55
|
+
*/
|
|
56
|
+
export function getAuthConfig(preferredRegion?: string): AuthConfig {
|
|
57
|
+
const projectId = resolveProjectId();
|
|
58
|
+
if (!projectId) {
|
|
59
|
+
throw new Error(
|
|
60
|
+
"Vertex AI requires a project ID.\n" +
|
|
61
|
+
` Config file: set "project" in ${getConfigPath()}\n` +
|
|
62
|
+
" Env var: export GOOGLE_CLOUD_PROJECT=your-project-id\n" +
|
|
63
|
+
" Also ensure you've run: gcloud auth application-default login"
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (!hasAdcCredentials()) {
|
|
68
|
+
throw new Error(
|
|
69
|
+
"Vertex AI requires Application Default Credentials.\n" +
|
|
70
|
+
" Run: gcloud auth application-default login\n" +
|
|
71
|
+
` Or set "credentialsFile" in ${getConfigPath()}`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
projectId,
|
|
77
|
+
location: preferredRegion || resolveLocation(),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Get access token for HTTP requests.
|
|
83
|
+
* Uses credentialsFile from config if set, otherwise relies on ADC.
|
|
84
|
+
*/
|
|
85
|
+
export async function getAccessToken(): Promise<string> {
|
|
86
|
+
const config = loadConfig();
|
|
87
|
+
const auth = new GoogleAuth({
|
|
88
|
+
scopes: ["https://www.googleapis.com/auth/cloud-platform"],
|
|
89
|
+
...(config.googleApplicationCredentials ? { keyFile: config.googleApplicationCredentials } : {}),
|
|
90
|
+
});
|
|
91
|
+
const client = await auth.getClient();
|
|
92
|
+
const token = await client.getAccessToken();
|
|
93
|
+
if (!token.token) {
|
|
94
|
+
throw new Error("Failed to get access token from ADC");
|
|
95
|
+
}
|
|
96
|
+
return token.token;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Build the base URL for Vertex AI endpoints
|
|
101
|
+
*/
|
|
102
|
+
export function buildBaseUrl(projectId: string, location: string): string {
|
|
103
|
+
// Global endpoint uses aiplatform.googleapis.com without region prefix
|
|
104
|
+
if (location === "global") {
|
|
105
|
+
return `https://aiplatform.googleapis.com/v1/projects/${projectId}/locations/global`;
|
|
106
|
+
}
|
|
107
|
+
return `https://${location}-aiplatform.googleapis.com/v1/projects/${projectId}/locations/${location}`;
|
|
108
|
+
}
|
package/config.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config loader for pi-vertex
|
|
3
|
+
*
|
|
4
|
+
* Reads ~/.pi/agent/settings/pi-vertex.json (if present).
|
|
5
|
+
* All fields are optional — env vars remain a supported fallback.
|
|
6
|
+
*
|
|
7
|
+
* Config keys are camelCase versions of the corresponding env var names:
|
|
8
|
+
*
|
|
9
|
+
* {
|
|
10
|
+
* "googleCloudProject": "my-gcp-project",
|
|
11
|
+
* "googleCloudLocation": "us-central1",
|
|
12
|
+
* "googleApplicationCredentials": "/path/to/service-account.json"
|
|
13
|
+
* }
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { getAgentDir } from "@mariozechner/pi-coding-agent";
|
|
17
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
18
|
+
import { join } from "node:path";
|
|
19
|
+
|
|
20
|
+
export function getConfigPath(): string {
|
|
21
|
+
return join(getAgentDir(), "settings", "pi-vertex.json");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface VertexConfig {
|
|
25
|
+
/** GCP project ID. Equivalent to GOOGLE_CLOUD_PROJECT. */
|
|
26
|
+
googleCloudProject?: string;
|
|
27
|
+
/** Default region/location. Equivalent to GOOGLE_CLOUD_LOCATION. */
|
|
28
|
+
googleCloudLocation?: string;
|
|
29
|
+
/** Path to a service account JSON key. Equivalent to GOOGLE_APPLICATION_CREDENTIALS. */
|
|
30
|
+
googleApplicationCredentials?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let _cachedPath: string | null = null;
|
|
34
|
+
let _globalCached: VertexConfig | null = null;
|
|
35
|
+
|
|
36
|
+
function loadGlobalConfig(): VertexConfig {
|
|
37
|
+
const configPath = getConfigPath();
|
|
38
|
+
// Bust cache if agentDir changed (e.g. different process env)
|
|
39
|
+
if (_cachedPath !== configPath) {
|
|
40
|
+
_cachedPath = configPath;
|
|
41
|
+
_globalCached = null;
|
|
42
|
+
}
|
|
43
|
+
if (_globalCached !== null) return _globalCached;
|
|
44
|
+
|
|
45
|
+
if (!existsSync(configPath)) {
|
|
46
|
+
_globalCached = {};
|
|
47
|
+
return _globalCached;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
_globalCached = JSON.parse(readFileSync(configPath, "utf-8")) as VertexConfig;
|
|
52
|
+
return _globalCached;
|
|
53
|
+
} catch (err) {
|
|
54
|
+
console.warn(`[pi-vertex] Failed to parse ${configPath}: ${err}`);
|
|
55
|
+
_globalCached = {};
|
|
56
|
+
return _globalCached;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Load config from global settings. */
|
|
61
|
+
export function loadConfig(): VertexConfig {
|
|
62
|
+
return loadGlobalConfig();
|
|
63
|
+
}
|
package/index.ts
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pi-vertex - Google Vertex AI provider for Pi coding agent
|
|
3
|
+
*
|
|
4
|
+
* Supports:
|
|
5
|
+
* - Gemini models (via @google/genai)
|
|
6
|
+
* - Claude models (via OpenAI-compatible endpoint)
|
|
7
|
+
* - All MaaS models (Llama, Mistral, DeepSeek, etc. via OpenAI-compatible endpoint)
|
|
8
|
+
*
|
|
9
|
+
* Configuration (resolution order: config file → env var):
|
|
10
|
+
*
|
|
11
|
+
* Config file: ~/.pi/agent/config/pi-vertex.json
|
|
12
|
+
* {
|
|
13
|
+
* "project": "my-gcp-project",
|
|
14
|
+
* "location": "us-central1",
|
|
15
|
+
* "credentialsFile": "/path/to/service-account.json"
|
|
16
|
+
* }
|
|
17
|
+
*
|
|
18
|
+
* Env vars (fallback):
|
|
19
|
+
* GOOGLE_CLOUD_PROJECT or GCLOUD_PROJECT (required)
|
|
20
|
+
* GOOGLE_CLOUD_LOCATION (optional, default: model region or us-central1)
|
|
21
|
+
* GOOGLE_APPLICATION_CREDENTIALS (optional, for service account auth)
|
|
22
|
+
*
|
|
23
|
+
* Usage:
|
|
24
|
+
* pi --provider vertex --model claude-opus-4-6
|
|
25
|
+
* pi --provider vertex --model gemini-2.5-pro
|
|
26
|
+
* pi --provider vertex --model llama-4-maverick
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
30
|
+
import type { Model, Api } from "@mariozechner/pi-ai";
|
|
31
|
+
import { ALL_MODELS, getModelById } from "./models/index.js";
|
|
32
|
+
import { hasAdcCredentials, resolveProjectId } from "./auth.js";
|
|
33
|
+
import { loadConfig, getConfigPath } from "./config.js";
|
|
34
|
+
import { streamVertex } from "./streaming/index.js";
|
|
35
|
+
import type { VertexModelConfig } from "./types.js";
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Convert Vertex model config to Pi model format
|
|
39
|
+
*/
|
|
40
|
+
function toPiModel(config: VertexModelConfig): Model<Api> {
|
|
41
|
+
return {
|
|
42
|
+
id: config.id,
|
|
43
|
+
name: config.name,
|
|
44
|
+
api: "vertex-unified",
|
|
45
|
+
provider: "vertex",
|
|
46
|
+
baseUrl: "", // Will be set dynamically
|
|
47
|
+
reasoning: config.reasoning,
|
|
48
|
+
input: config.input,
|
|
49
|
+
cost: config.cost,
|
|
50
|
+
contextWindow: config.contextWindow,
|
|
51
|
+
maxTokens: config.maxTokens,
|
|
52
|
+
headers: {},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Extension entry point
|
|
58
|
+
*/
|
|
59
|
+
export default function (pi: ExtensionAPI) {
|
|
60
|
+
const config = loadConfig();
|
|
61
|
+
|
|
62
|
+
// Apply credentialsFile to environment so all Google SDKs pick it up.
|
|
63
|
+
// Only set if not already overridden by env var.
|
|
64
|
+
if (config.googleApplicationCredentials && !process.env.GOOGLE_APPLICATION_CREDENTIALS) {
|
|
65
|
+
process.env.GOOGLE_APPLICATION_CREDENTIALS = config.googleApplicationCredentials;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const projectId = resolveProjectId();
|
|
69
|
+
|
|
70
|
+
if (!projectId) {
|
|
71
|
+
console.log(
|
|
72
|
+
`[pi-vertex] Skipping: no project ID found.\n` +
|
|
73
|
+
` Config file: set "project" in ${getConfigPath()}\n` +
|
|
74
|
+
` Env var: export GOOGLE_CLOUD_PROJECT=your-project-id`
|
|
75
|
+
);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (!hasAdcCredentials()) {
|
|
80
|
+
console.log(
|
|
81
|
+
`[pi-vertex] Skipping: ADC credentials not found.\n` +
|
|
82
|
+
` Run: gcloud auth application-default login\n` +
|
|
83
|
+
` Or set "credentialsFile" in ${getConfigPath()}`
|
|
84
|
+
);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Register the provider
|
|
89
|
+
pi.registerProvider("vertex", {
|
|
90
|
+
// Use a placeholder baseUrl (actual URLs built per-request based on model region)
|
|
91
|
+
baseUrl: "https://aiplatform.googleapis.com",
|
|
92
|
+
|
|
93
|
+
// Use env var name for detection
|
|
94
|
+
apiKey: "GOOGLE_CLOUD_PROJECT",
|
|
95
|
+
|
|
96
|
+
// API type varies by model
|
|
97
|
+
api: "vertex-unified",
|
|
98
|
+
|
|
99
|
+
// Register all models
|
|
100
|
+
models: ALL_MODELS.map(toPiModel),
|
|
101
|
+
|
|
102
|
+
// Custom streaming implementation
|
|
103
|
+
streamSimple: (model: Model<Api>, context: any, options?: any) => {
|
|
104
|
+
const vertexModel = getModelById(model.id);
|
|
105
|
+
if (!vertexModel) {
|
|
106
|
+
throw new Error(`Unknown Vertex model: ${model.id}`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return streamVertex(vertexModel, context, options);
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Show startup info as a widget that clears on first user input
|
|
114
|
+
const vertexStartupLines = [
|
|
115
|
+
`[pi-vertex] Initializing with project: ${projectId}`,
|
|
116
|
+
`[pi-vertex] Registered ${ALL_MODELS.length} models`,
|
|
117
|
+
];
|
|
118
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
119
|
+
ctx.ui.setWidget("pi-vertex-startup", (_tui, theme) => ({
|
|
120
|
+
render: () => [...vertexStartupLines.map(l => theme.fg("muted", l)), ""],
|
|
121
|
+
invalidate: () => {},
|
|
122
|
+
}));
|
|
123
|
+
});
|
|
124
|
+
pi.on("input", async (_event, ctx) => {
|
|
125
|
+
ctx.ui.setWidget("pi-vertex-startup", undefined);
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Export types and utilities for advanced usage
|
|
130
|
+
export * from "./types.js";
|
|
131
|
+
export * from "./models/index.js";
|
|
132
|
+
export * from "./auth.js";
|
|
133
|
+
export * from "./config.js";
|
|
134
|
+
export * from "./streaming/index.js";
|