Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vertex-sdk: Cloudflare workers edge runtime not supported #508

Open
rxliuli opened this issue Aug 23, 2024 · 1 comment · May be fixed by #509
Open

vertex-sdk: Cloudflare workers edge runtime not supported #508

rxliuli opened this issue Aug 23, 2024 · 1 comment · May be fixed by #509

Comments

@rxliuli
Copy link

rxliuli commented Aug 23, 2024

At first I tried to use google-auth-libray for verification and found that it contained nodejs dependencies, so I implemented the logic of obtaining the access token myself, but errors still occurred, as follows

image
// src/index.ts
import { Hono } from 'hono'
import { AnthropicVertex } from '@anthropic-ai/vertex-sdk'
import { authenticate } from './authenticate'

const app = new Hono<{
  Bindings: {
    VERTEX_ANTROPIC_GOOGLE_SA_CLIENT_EMAIL: string
    VERTEX_ANTROPIC_GOOGLE_SA_PRIVATE_KEY: string
    VERTEX_ANTROPIC_REGION: string
    VERTEX_ANTROPIC_PROJECTID: string
    VERTEX_ANTROPIC_MODEL: string
  }
}>().get('/', async (c) => {
  const token = await authenticate({
    clientEmail: c.env.VERTEX_ANTROPIC_GOOGLE_SA_CLIENT_EMAIL!,
    privateKey: c.env.VERTEX_ANTROPIC_GOOGLE_SA_PRIVATE_KEY!,
  })
  const client = new AnthropicVertex({
    region: c.env.VERTEX_ANTROPIC_REGION,
    projectId: c.env.VERTEX_ANTROPIC_PROJECTID,
    accessToken: token.access_token,
  })
  const resp = await client.messages.create({
    model: c.env.VERTEX_ANTROPIC_MODEL,
    messages: [{ role: 'user', content: 'Hello!' }],
    max_tokens: 100,
  })
  return c.json(resp)
})

export default app
// src/authenticate.ts
import { SignJWT, importPKCS8 } from 'jose'

type Token = {
  access_token: string
  expires_in: number
  token_type: string
}

type TokenWithExpiration = Token & {
  expires_at: number
}

let token: TokenWithExpiration | null = null

async function createToken(options: {
  clientEmail: string
  privateKey: string
}) {
  const rawPrivateKey = options.privateKey.replace(/\\n/g, '\n')
  const privateKey = await importPKCS8(rawPrivateKey, 'RS256')

  const payload = {
    iss: options.clientEmail,
    scope: 'https://www.googleapis.com/auth/cloud-platform',
    aud: 'https://www.googleapis.com/oauth2/v4/token',
    exp: Math.floor(Date.now() / 1000) + 60 * 60,
    iat: Math.floor(Date.now() / 1000),
  }
  const token = await new SignJWT(payload)
    .setProtectedHeader({ alg: 'RS256' })
    .setIssuedAt()
    .setIssuer(options.clientEmail)
    .setAudience('https://www.googleapis.com/oauth2/v4/token')
    .setExpirationTime('1h')
    .sign(privateKey)

  // Form data for the token request
  const form = {
    grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
    assertion: token,
  }

  // Make the token request
  const tokenResponse = await fetch(
    'https://www.googleapis.com/oauth2/v4/token',
    {
      method: 'POST',
      body: JSON.stringify(form),
      headers: { 'Content-Type': 'application/json' },
    },
  )

  const json = (await tokenResponse.json()) as Token

  return {
    ...json,
    expires_at: Math.floor(Date.now() / 1000) + json.expires_in,
  }
}

export async function authenticate(options: {
  clientEmail: string
  privateKey: string
}): Promise<Token> {
  if (token === null) {
    token = await createToken(options)
  } else if (token.expires_at < Math.floor(Date.now() / 1000)) {
    token = await createToken(options)
  }
  return token
}
@rxliuli rxliuli linked a pull request Aug 23, 2024 that will close this issue
@RobertCraigie
Copy link
Collaborator

Thanks for the report. Have you opened an issue / is there an existing issue with google-auth-library for supporting cloudflare workers? Ideally this would be fixed upstream.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants