From 4880b68d969ed426072c5849bc0d5ee3f371b928 Mon Sep 17 00:00:00 2001 From: Austin Mangelson Date: Wed, 12 Aug 2026 13:07:06 -0600 Subject: [PATCH] feat: enable AI features with Google Vertex AI service account support --- .env.example | 7 +++++++ cloudbuild.yaml | 1 + packages/lib/constants/app.ts | 6 +++++- packages/lib/server-only/ai/google.ts | 7 +++++++ 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index d69d5a64e9c..5a8bb9865f6 100644 --- a/.env.example +++ b/.env.example @@ -211,6 +211,13 @@ GOOGLE_VERTEX_LOCATION="global" # OPTIONAL: API key for Google Vertex AI (Gemini). Get your key from: # https://console.cloud.google.com/vertex-ai/studio/settings/api-keys GOOGLE_VERTEX_API_KEY="" +# OPTIONAL: Service account credentials for Google Vertex AI, +# as a JSON string (the contents of a downloaded service account key file). +# Used instead of GOOGLE_VERTEX_API_KEY. +GOOGLE_VERTEX_SERVICE_ACCOUNT_JSON="" +# OPTIONAL: Set to "true" to rely on Application Default Credentials instead of an +# API key or service account JSON +GOOGLE_VERTEX_USE_ADC="" # [[CLOUDFLARE TURNSTILE]] # OPTIONAL: Cloudflare Turnstile site key (public). When configured, Turnstile challenges diff --git a/cloudbuild.yaml b/cloudbuild.yaml index 1b8d18f4656..191d6663a66 100644 --- a/cloudbuild.yaml +++ b/cloudbuild.yaml @@ -25,6 +25,7 @@ steps: - --image=${_IMAGE} - --region=us-west1 - --project=$PROJECT_ID + - --service-account=keepcontracts-vertex-ai@keepcontracts.iam.gserviceaccount.com images: - ${_IMAGE} diff --git a/packages/lib/constants/app.ts b/packages/lib/constants/app.ts index 67d2b09c34b..36e2e40e2e6 100644 --- a/packages/lib/constants/app.ts +++ b/packages/lib/constants/app.ts @@ -24,7 +24,11 @@ export const SUPPORT_EMAIL = env('NEXT_PUBLIC_SUPPORT_EMAIL') ?? 'mangelsona@dat export const USE_INTERNAL_URL_BROWSERLESS = () => env('NEXT_PUBLIC_USE_INTERNAL_URL_BROWSERLESS') === 'true'; -export const IS_AI_FEATURES_CONFIGURED = () => !!env('GOOGLE_VERTEX_PROJECT_ID') && !!env('GOOGLE_VERTEX_API_KEY'); +export const IS_AI_FEATURES_CONFIGURED = () => + !!env('GOOGLE_VERTEX_PROJECT_ID') && + (!!env('GOOGLE_VERTEX_API_KEY') || + !!env('GOOGLE_VERTEX_SERVICE_ACCOUNT_JSON') || + env('GOOGLE_VERTEX_USE_ADC') === 'true'); /** * Temporary flag to toggle between Playwright-based and Konva-based PDF generation diff --git a/packages/lib/server-only/ai/google.ts b/packages/lib/server-only/ai/google.ts index bf78e3c0f37..21133423b32 100644 --- a/packages/lib/server-only/ai/google.ts +++ b/packages/lib/server-only/ai/google.ts @@ -2,8 +2,15 @@ import { createVertex } from '@ai-sdk/google-vertex'; import { env } from '../../utils/env'; +const serviceAccountJson = env('GOOGLE_VERTEX_SERVICE_ACCOUNT_JSON'); + +// Auth resolution order (handled by the SDK, see createVertex2 in +// @ai-sdk/google-vertex): an explicit apiKey wins if set; otherwise it uses +// googleAuthOptions.credentials if we provide them; otherwise it falls back to +// Application Default Credentials export const vertex = createVertex({ project: env('GOOGLE_VERTEX_PROJECT_ID'), location: env('GOOGLE_VERTEX_LOCATION') || 'global', apiKey: env('GOOGLE_VERTEX_API_KEY'), + googleAuthOptions: serviceAccountJson ? { credentials: JSON.parse(serviceAccountJson) } : undefined, });