Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/core/lib/v3/types/public/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,8 @@ export type AgentType =
| "anthropic"
| "google"
| "microsoft"
| "bedrock";
| "bedrock"
| "vertex";

export const AVAILABLE_CUA_MODELS = [
"openai/gpt-5.4",
Expand Down
52 changes: 51 additions & 1 deletion packages/core/lib/v3/types/public/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,48 @@ export const LocalBrowserLaunchOptionsSchema = z
.meta({ id: "LocalBrowserLaunchOptions" });
Comment thread
monadoid marked this conversation as resolved.

/** Detailed model configuration object */
export const GoogleServiceAccountCredentialsSchema = z
.object({
type: z.literal("service_account").optional(),
project_id: z.string().optional(),
private_key_id: z.string().optional(),
private_key: z.string(),
client_email: z.string(),
client_id: z.string().optional(),
auth_uri: z.url().optional(),
token_uri: z.url().optional(),
auth_provider_x509_cert_url: z.url().optional(),
client_x509_cert_url: z.url().optional(),
universe_domain: z.string().optional(),
})
.strict()
.meta({ id: "GoogleServiceAccountCredentials" });

export const GoogleAuthOptionsSchema = z
.object({
credentials: GoogleServiceAccountCredentialsSchema.optional().meta({
description: "Google Cloud service account credentials",
}),
scopes: z
.union([z.string(), z.array(z.string())])
.optional()
.meta({
description: "Google auth scopes for the desired API request",
}),
projectId: z.string().optional().meta({
description: "Google Cloud project ID used by google-auth-library",
}),
universeDomain: z.string().optional().meta({
description: "Google Cloud universe domain",
}),
})
.strict()
.meta({ id: "GoogleAuthOptions" });

export const ModelConfigObjectSchema = z
.object({
provider: z
.enum(["openai", "anthropic", "google", "microsoft", "bedrock"])
.enum(["openai", "anthropic", "google", "microsoft", "bedrock", "vertex"])
.optional()
.meta({
description:
Expand All @@ -83,6 +121,18 @@ export const ModelConfigObjectSchema = z
description:
"Custom headers sent with every request to the model provider",
}),
project: z.string().optional().meta({
description: "Google Cloud project ID for Vertex AI models",
example: "my-gcp-project",
}),
location: z.string().optional().meta({
description: "Google Cloud location for Vertex AI models",
example: "us-central1",
}),
googleAuthOptions: GoogleAuthOptionsSchema.optional().meta({
description:
"google-auth-library options used to authenticate Vertex AI models",
}),
})
.meta({ id: "ModelConfigObject" });

Expand Down
19 changes: 12 additions & 7 deletions packages/core/lib/v3/types/public/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ export type AnthropicClientOptions = Pick<
>;

export interface GoogleServiceAccountCredentials {
type?: string;
type?: "service_account";
project_id?: string;
private_key_id?: string;
private_key?: string;
client_email?: string;
private_key: string;
client_email: string;
client_id?: string;
auth_uri?: string;
token_uri?: string;
Expand All @@ -31,13 +31,18 @@ export interface GoogleServiceAccountCredentials {
universe_domain?: string;
}

export interface GoogleVertexAuthOptions {
credentials?: GoogleServiceAccountCredentials;
scopes?: string | string[];
projectId?: string;
universeDomain?: string;
}

export type GoogleVertexProviderSettings = Pick<
GoogleVertexProviderSettingsBase,
"project" | "location" | "headers"
"project" | "location" | "headers" | "baseURL"
> & {
googleAuthOptions?: {
credentials?: GoogleServiceAccountCredentials;
};
googleAuthOptions?: GoogleVertexAuthOptions;
};

export type AnthropicJsonSchemaObject = {
Expand Down
130 changes: 130 additions & 0 deletions packages/core/tests/unit/api-variables-schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,133 @@ describe("API variable schemas", () => {
});
});
});

describe("API model config schemas", () => {
const vertexModel = {
provider: "vertex",
modelName: "vertex/gemini-2.5-flash",
project: "test-gcp-project",
location: "us-central1",
googleAuthOptions: {
credentials: {
type: "service_account",
project_id: "test-gcp-project",
private_key_id: "test-key-id",
client_email: "vertex@example.iam.gserviceaccount.com",
private_key:
"-----BEGIN PRIVATE KEY-----\\ntest\\n-----END PRIVATE KEY-----",
token_uri: "https://oauth2.googleapis.com/token",
},
scopes: ["https://www.googleapis.com/auth/cloud-platform"],
projectId: "test-gcp-project",
universeDomain: "googleapis.com",
},
};

it("preserves Vertex auth params for act requests", () => {
const result = Api.ActRequestSchema.safeParse({
input: "click the search button",
options: {
model: vertexModel,
},
});

expect(result.success).toBe(true);
if (!result.success) throw result.error;
expect(result.data.options?.model).toEqual(vertexModel);
});

it("accepts minimal Vertex service account credentials", () => {
const result = Api.ActRequestSchema.safeParse({
input: "click the search button",
options: {
model: {
provider: "vertex",
modelName: "vertex/gemini-2.5-flash",
project: "test-gcp-project",
location: "us-central1",
googleAuthOptions: {
credentials: {
client_email: "vertex@example.iam.gserviceaccount.com",
private_key:
"-----BEGIN PRIVATE KEY-----\\ntest\\n-----END PRIVATE KEY-----",
},
},
},
},
});

expect(result.success).toBe(true);
if (!result.success) throw result.error;
const parsedModel = result.data.options?.model;
expect(typeof parsedModel).toBe("object");
if (typeof parsedModel !== "object" || parsedModel === null) {
throw new Error("Expected object model config");
}
expect(parsedModel.googleAuthOptions).toEqual({
credentials: {
client_email: "vertex@example.iam.gserviceaccount.com",
private_key:
"-----BEGIN PRIVATE KEY-----\\ntest\\n-----END PRIVATE KEY-----",
},
});
});

it("preserves Vertex auth params for agent model configs", () => {
const result = Api.AgentExecuteRequestSchema.safeParse({
agentConfig: {
model: vertexModel,
executionModel: vertexModel,
},
executeOptions: {
instruction: "find the search box",
},
});

expect(result.success).toBe(true);
if (!result.success) throw result.error;
expect(result.data.agentConfig.model).toEqual(vertexModel);
expect(result.data.agentConfig.executionModel).toEqual(vertexModel);
});

it("rejects Vertex key file paths and external credential sources", () => {
for (const blockedAuthOptions of [
{ keyFilename: "/etc/passwd" },
{ keyFile: "/etc/passwd" },
{ apiKey: "vertex-express-key" },
]) {
const result = Api.ActRequestSchema.safeParse({
input: "click the search button",
options: {
model: {
provider: "vertex",
modelName: "vertex/gemini-2.5-flash",
googleAuthOptions: blockedAuthOptions,
},
},
});

expect(result.success).toBe(false);
}

const externalAccountResult = Api.ActRequestSchema.safeParse({
input: "click the search button",
options: {
model: {
provider: "vertex",
modelName: "vertex/gemini-2.5-flash",
googleAuthOptions: {
credentials: {
type: "external_account",
credential_source: {
file: "/etc/passwd",
},
},
},
},
},
});

expect(externalAccountResult.success).toBe(false);
});
});
78 changes: 78 additions & 0 deletions packages/server-v3/openapi.v3.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,60 @@ components:
acceptDownloads:
type: boolean
additionalProperties: false
GoogleServiceAccountCredentials:
type: object
properties:
type:
type: string
const: service_account
project_id:
type: string
private_key_id:
type: string
private_key:
type: string
client_email:
type: string
client_id:
type: string
auth_uri:
type: string
format: uri
token_uri:
type: string
format: uri
auth_provider_x509_cert_url:
type: string
format: uri
client_x509_cert_url:
type: string
format: uri
universe_domain:
type: string
required:
- private_key
- client_email
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
additionalProperties: false
GoogleAuthOptions:
type: object
properties:
credentials:
description: Google Cloud service account credentials
$ref: "#/components/schemas/GoogleServiceAccountCredentials"
scopes:
description: Google auth scopes for the desired API request
anyOf:
- type: string
- type: array
items:
type: string
projectId:
description: Google Cloud project ID used by google-auth-library
type: string
universeDomain:
description: Google Cloud universe domain
type: string
additionalProperties: false
ModelConfigObject:
type: object
properties:
Expand All @@ -181,6 +235,7 @@ components:
- google
- microsoft
- bedrock
- vertex
modelName:
description: Model name string with provider prefix (e.g., 'openai/gpt-5-nano')
example: openai/gpt-5.4-mini
Expand All @@ -201,6 +256,17 @@ components:
type: string
additionalProperties:
type: string
project:
description: Google Cloud project ID for Vertex AI models
example: my-gcp-project
type: string
location:
description: Google Cloud location for Vertex AI models
example: us-central1
type: string
googleAuthOptions:
description: google-auth-library options used to authenticate Vertex AI models
$ref: "#/components/schemas/GoogleAuthOptions"
required:
- modelName
ModelConfig:
Expand Down Expand Up @@ -1251,6 +1317,7 @@ components:
- google
- microsoft
- bedrock
- vertex
modelName:
description: Model name string with provider prefix (e.g., 'openai/gpt-5-nano')
example: openai/gpt-5.4-mini
Expand All @@ -1271,6 +1338,17 @@ components:
type: string
additionalProperties:
type: string
project:
description: Google Cloud project ID for Vertex AI models
example: my-gcp-project
type: string
location:
description: Google Cloud location for Vertex AI models
example: us-central1
type: string
googleAuthOptions:
description: google-auth-library options used to authenticate Vertex AI models
$ref: "#/components/schemas/GoogleAuthOptions"
Comment thread
monadoid marked this conversation as resolved.
required:
- modelName
additionalProperties: false
Expand Down
3 changes: 3 additions & 0 deletions packages/server-v3/scripts/gen-openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ async function main() {
BrowserbaseRegion: Api.BrowserbaseRegionSchema,
// Shared components
LocalBrowserLaunchOptions: Api.LocalBrowserLaunchOptionsSchema,
GoogleServiceAccountCredentials:
Api.GoogleServiceAccountCredentialsSchema,
GoogleAuthOptions: Api.GoogleAuthOptionsSchema,
ModelConfigObject: Api.ModelConfigObjectSchema,
ModelConfig: Api.ModelConfigSchema,
Action: Api.ActionSchema,
Expand Down
Loading