@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 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
+ [![npm version](https://img.shields.io/npm/v/@ssweens/pi-vertex)](https://www.npmjs.com/package/@ssweens/pi-vertex)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
5
+
6
+ ![pi-vertex model selector](screenshot.png)
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";