Files
openclaw/extensions/anthropic-vertex/region.ts
2026-04-05 08:33:54 +01:00

137 lines
4.2 KiB
TypeScript

import { readFileSync } from "node:fs";
import { homedir, platform } from "node:os";
import { join } from "node:path";
import { resolveProviderEndpoint } from "openclaw/plugin-sdk/provider-http";
const ANTHROPIC_VERTEX_DEFAULT_REGION = "global";
const ANTHROPIC_VERTEX_REGION_RE = /^[a-z0-9-]+$/;
const GCP_VERTEX_CREDENTIALS_MARKER = "gcp-vertex-credentials";
const GCLOUD_DEFAULT_ADC_PATH = join(
homedir(),
".config",
"gcloud",
"application_default_credentials.json",
);
type AdcProjectFile = {
project_id?: unknown;
quota_project_id?: unknown;
};
function normalizeOptionalSecretInput(value: unknown): string | undefined {
if (typeof value !== "string") {
return undefined;
}
const trimmed = value.trim();
return trimmed || undefined;
}
export function resolveAnthropicVertexRegion(env: NodeJS.ProcessEnv = process.env): string {
const region =
normalizeOptionalSecretInput(env.GOOGLE_CLOUD_LOCATION) ||
normalizeOptionalSecretInput(env.CLOUD_ML_REGION);
return region && ANTHROPIC_VERTEX_REGION_RE.test(region)
? region
: ANTHROPIC_VERTEX_DEFAULT_REGION;
}
export function resolveAnthropicVertexProjectId(
env: NodeJS.ProcessEnv = process.env,
): string | undefined {
return (
normalizeOptionalSecretInput(env.ANTHROPIC_VERTEX_PROJECT_ID) ||
normalizeOptionalSecretInput(env.GOOGLE_CLOUD_PROJECT) ||
normalizeOptionalSecretInput(env.GOOGLE_CLOUD_PROJECT_ID) ||
resolveAnthropicVertexProjectIdFromAdc(env)
);
}
export function resolveAnthropicVertexRegionFromBaseUrl(baseUrl?: string): string | undefined {
const endpoint = resolveProviderEndpoint(baseUrl);
return endpoint.endpointClass === "google-vertex" ? endpoint.googleVertexRegion : undefined;
}
export function resolveAnthropicVertexClientRegion(params?: {
baseUrl?: string;
env?: NodeJS.ProcessEnv;
}): string {
return (
resolveAnthropicVertexRegionFromBaseUrl(params?.baseUrl) ||
resolveAnthropicVertexRegion(params?.env)
);
}
function hasAnthropicVertexMetadataServerAdc(env: NodeJS.ProcessEnv = process.env): boolean {
const explicitMetadataOptIn = normalizeOptionalSecretInput(env.ANTHROPIC_VERTEX_USE_GCP_METADATA);
return explicitMetadataOptIn === "1" || explicitMetadataOptIn?.toLowerCase() === "true";
}
function resolveAnthropicVertexDefaultAdcPath(env: NodeJS.ProcessEnv = process.env): string {
return platform() === "win32"
? join(
env.APPDATA ?? join(homedir(), "AppData", "Roaming"),
"gcloud",
"application_default_credentials.json",
)
: GCLOUD_DEFAULT_ADC_PATH;
}
function resolveAnthropicVertexAdcCredentialsPathCandidate(
env: NodeJS.ProcessEnv = process.env,
): string | undefined {
const explicit = normalizeOptionalSecretInput(env.GOOGLE_APPLICATION_CREDENTIALS);
if (explicit) {
return explicit;
}
if (env !== process.env) {
return undefined;
}
return resolveAnthropicVertexDefaultAdcPath(env);
}
function canReadAnthropicVertexAdc(env: NodeJS.ProcessEnv = process.env): boolean {
const credentialsPath = resolveAnthropicVertexAdcCredentialsPathCandidate(env);
if (!credentialsPath) {
return false;
}
try {
readFileSync(credentialsPath, "utf8");
return true;
} catch {
return false;
}
}
function resolveAnthropicVertexProjectIdFromAdc(
env: NodeJS.ProcessEnv = process.env,
): string | undefined {
const credentialsPath = resolveAnthropicVertexAdcCredentialsPathCandidate(env);
if (!credentialsPath) {
return undefined;
}
try {
const parsed = JSON.parse(readFileSync(credentialsPath, "utf8")) as AdcProjectFile;
return (
normalizeOptionalSecretInput(parsed.project_id) ||
normalizeOptionalSecretInput(parsed.quota_project_id)
);
} catch {
return undefined;
}
}
export function hasAnthropicVertexCredentials(env: NodeJS.ProcessEnv = process.env): boolean {
return hasAnthropicVertexMetadataServerAdc(env) || canReadAnthropicVertexAdc(env);
}
export function hasAnthropicVertexAvailableAuth(env: NodeJS.ProcessEnv = process.env): boolean {
return hasAnthropicVertexCredentials(env);
}
export function resolveAnthropicVertexConfigApiKey(
env: NodeJS.ProcessEnv = process.env,
): string | undefined {
return hasAnthropicVertexAvailableAuth(env) ? GCP_VERTEX_CREDENTIALS_MARKER : undefined;
}