Skip to content

Commit

Permalink
feat: Add GoogleApi error in ClientError.cause
Browse files Browse the repository at this point in the history
Co-authored-by: tjenkinson
FUTURE_COPYBARA_INTEGRATE_REVIEW=#418 from googleapis:release-please--branches--main--components--vertexai ac43919
PiperOrigin-RevId: 668992333
  • Loading branch information
happy-qiao authored and copybara-github committed Aug 29, 2024
1 parent 5d80976 commit 9eb82c3
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 15 deletions.
17 changes: 15 additions & 2 deletions src/functions/post_fetch_processing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ import {
StreamGenerateContentResult,
} from '../types/content';
import {constants} from '../util';
import {ClientError, GoogleGenerativeAIError} from '../types/errors';
import {
ClientError,
GoogleApiError,
GoogleGenerativeAIError,
} from '../types/errors';

export async function throwErrorIfNotOK(response: Response | undefined) {
if (response === undefined) {
Expand All @@ -40,7 +44,16 @@ export async function throwErrorIfNotOK(response: Response | undefined) {
errorBody
)}`;
if (status >= 400 && status < 500) {
throw new ClientError(errorMessage);
const error = new ClientError(
errorMessage,
new GoogleApiError(
errorBody.error.message,
errorBody.error.code,
errorBody.error.status,
errorBody.error.details
)
);
throw error;
}
throw new GoogleGenerativeAIError(errorMessage);
}
Expand Down
33 changes: 20 additions & 13 deletions src/functions/test/functions_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@
*/

import {
ClientError,
CountTokensRequest,
FinishReason,
FunctionDeclarationSchemaType,
GenerateContentRequest,
GenerateContentResponse,
GenerateContentResponseHandler,
GenerateContentResult,
GoogleApiError,
HarmBlockThreshold,
HarmCategory,
HarmProbability,
Expand All @@ -31,7 +33,6 @@ import {
SafetySetting,
StreamGenerateContentResult,
Tool,
ToolConfig,
} from '../../types';
import {constants} from '../../util';
import {countTokens} from '../count_tokens';
Expand Down Expand Up @@ -194,8 +195,6 @@ const TEST_MULTIPART_MESSAGE_BASE64 = [

const TEST_EMPTY_TOOLS: Tool[] = [];

const TEST_EMPTY_TOOL_CONFIG: ToolConfig = {};

const TEST_TOOLS_WITH_FUNCTION_DECLARATION: Tool[] = [
{
functionDeclarations: [
Expand Down Expand Up @@ -317,29 +316,39 @@ describe('countTokens', () => {
).toBeRejected();
});

it('throw ClientError when not OK and 4XX', async () => {
it('throw ApiClientError when not OK and 4XX', async () => {
const fetch400Obj = {
status: 400,
statusText: 'Bad Request',
ok: false,
};
const body = {
code: 400,
message: 'request is invalid',
status: 'INVALID_ARGUMENT',
error: {
code: 400,
message: 'request is invalid',
status: 'INVALID_ARGUMENT',
},
};
const response = new Response(JSON.stringify(body), fetch400Obj);
spyOn(global, 'fetch').and.resolveTo(response);

await expectAsync(
countTokens(
let error: any;
try {
await countTokens(
TEST_LOCATION,
TEST_RESOURCE_PATH,
TEST_TOKEN_PROMISE,
req,
TEST_API_ENDPOINT
)
).toBeRejected();
);
} catch (e) {
error = e;
}

expect(error).toBeInstanceOf(ClientError);
expect(error.cause).toBeInstanceOf(GoogleApiError);
expect(error.cause.code).toBe(400);
expect(error.cause.status).toEqual('INVALID_ARGUMENT');
});
});

Expand Down Expand Up @@ -369,7 +378,6 @@ describe('generateContent', () => {
TEST_GENERATION_CONFIG,
TEST_SAFETY_SETTINGS,
TEST_EMPTY_TOOLS,
TEST_EMPTY_TOOL_CONFIG,
TEST_REQUEST_OPTIONS
)
).toBeRejected();
Expand Down Expand Up @@ -688,7 +696,6 @@ describe('generateContentStream', () => {
TEST_GENERATION_CONFIG,
TEST_SAFETY_SETTINGS,
TEST_EMPTY_TOOLS,
TEST_EMPTY_TOOL_CONFIG,
TEST_REQUEST_OPTIONS
)
).toBeRejected();
Expand Down
29 changes: 29 additions & 0 deletions src/types/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,34 @@ class ClientError extends Error {
}
}

/**
* Google API Error Details object that may be included in an error response.
* See https://cloud.google.com/apis/design/errors
* @public
*/
export declare interface ErrorDetails {
'@type'?: string;
reason?: string;
domain?: string;
metadata?: Record<string, unknown>;
[key: string]: unknown;
}

/**
* GoogleApiError is thrown when http 4XX status is received.
* See https://cloud.google.com/apis/design/errors
*/
class GoogleApiError extends Error {
constructor(
message: string,
public code?: number,
public status?: string,
public errorDetails?: ErrorDetails[]
) {
super(message);
}
}

/**
* GoogleGenerativeAIError is thrown when http response is not ok and status code is not 4XX
* For details please refer to https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
Expand Down Expand Up @@ -78,6 +106,7 @@ function constructErrorMessage(

export {
ClientError,
GoogleApiError,
GoogleAuthError,
GoogleGenerativeAIError,
IllegalArgumentError,
Expand Down
54 changes: 54 additions & 0 deletions system_test/end_to_end_sample_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,9 @@ describe('generateContentStream', () => {
`sys test failure on generateContentStream when having bad request
got wrong error message: ${e.message}`
);
expect(e.cause.status).toBe(400);
expect(e.cause.statusText).toBe('INVALID_ARGUMENT');
expect(e.cause.message).toBeInstanceOf(String);
});
});
it('in preview should throw ClientError when having invalid input', async () => {
Expand All @@ -368,6 +371,9 @@ describe('generateContentStream', () => {
`sys test failure on generateContentStream in preview when having bad request
got wrong error message: ${e.message}`
);
expect(e.cause.status).toBe(400);
expect(e.cause.statusText).toBe('INVALID_ARGUMENT');
expect(e.cause.message).toBeInstanceOf(String);
});
});

Expand Down Expand Up @@ -535,6 +541,9 @@ describe('generateContentStream', () => {
`sys test failure on generateContentStream for grounding metadata: ${groundingMetadata}`
);
if (groundingMetadata) {
expect(!!groundingMetadata.groundingAttributions).toBeTruthy(
`sys test failure on generateContentStream for grounding attributions: ${groundingMetadata.groundingAttributions}`
);
expect(!!groundingMetadata.webSearchQueries).toBeTruthy(
`sys test failure on generateContentStream for web search queries: ${groundingMetadata.webSearchQueries}`
);
Expand All @@ -554,6 +563,9 @@ describe('generateContentStream', () => {
`sys test failure on generateContentStream for grounding metadata: ${groundingMetadata}`
);
if (groundingMetadata) {
expect(!!groundingMetadata.groundingAttributions).toBeTruthy(
`sys test failure on generateContentStream for grounding attributions: ${groundingMetadata.groundingAttributions}`
);
expect(!!groundingMetadata.webSearchQueries).toBeTruthy(
`sys test failure on generateContentStream for web search queries: ${groundingMetadata.webSearchQueries}`
);
Expand All @@ -573,6 +585,9 @@ describe('generateContentStream', () => {
`sys test failure on generateContentStream in preview for grounding metadata: ${groundingMetadata}`
);
if (groundingMetadata) {
expect(!!groundingMetadata.groundingAttributions).toBeTruthy(
`sys test failure on generateContentStream in preview for grounding attributions: ${groundingMetadata.groundingAttributions}`
);
expect(!!groundingMetadata.webSearchQueries).toBeTruthy(
`sys test failure on generateContentStream in preview for web search queries: ${groundingMetadata.webSearchQueries}`
);
Expand All @@ -592,6 +607,9 @@ describe('generateContentStream', () => {
`sys test failure on generateContentStream in preview for grounding metadata: ${groundingMetadata}`
);
if (groundingMetadata) {
expect(!!groundingMetadata.groundingAttributions).toBeTruthy(
`sys test failure on generateContentStream in preview for grounding attributions: ${groundingMetadata.groundingAttributions}`
);
expect(!!groundingMetadata.webSearchQueries).toBeTruthy(
`sys test failure on generateContentStream in preview for web search queries: ${groundingMetadata.webSearchQueries}`
);
Expand Down Expand Up @@ -669,6 +687,9 @@ describe('generateContent', () => {
`sys test failure on generateContent for grounding metadata: ${groundingMetadata}`
);
if (groundingMetadata) {
expect(!!groundingMetadata.groundingAttributions).toBeTruthy(
`sys test failure on generateContent for grounding attributions: ${groundingMetadata.groundingAttributions}`
);
expect(!!groundingMetadata.webSearchQueries).toBeTruthy(
`sys test failure on generateContent for web search queries: ${groundingMetadata.webSearchQueries}`
);
Expand All @@ -688,6 +709,9 @@ describe('generateContent', () => {
`sys test failure on generateContent for grounding metadata: ${groundingMetadata}`
);
if (groundingMetadata) {
expect(!!groundingMetadata.groundingAttributions).toBeTruthy(
`sys test failure on generateContent for grounding attributions: ${groundingMetadata.groundingAttributions}`
);
expect(!!groundingMetadata.webSearchQueries).toBeTruthy(
`sys test failure on generateContent for web search queries: ${groundingMetadata.webSearchQueries}`
);
Expand All @@ -707,6 +731,9 @@ describe('generateContent', () => {
`sys test failure on generateContent in preview for grounding metadata: ${groundingMetadata}`
);
if (groundingMetadata) {
expect(!!groundingMetadata.groundingAttributions).toBeTruthy(
`sys test failure on generateContent in preview for grounding attributions: ${groundingMetadata.groundingAttributions}`
);
expect(!!groundingMetadata.webSearchQueries).toBeTruthy(
`sys test failure on generateContent in preview for web search queries: ${groundingMetadata.webSearchQueries}`
);
Expand All @@ -726,6 +753,9 @@ describe('generateContent', () => {
`sys test failure on generateContent in preview for grounding metadata: ${groundingMetadata}`
);
if (groundingMetadata) {
expect(!!groundingMetadata.groundingAttributions).toBeTruthy(
`sys test failure on generateContent in preview for grounding attributions: ${groundingMetadata.groundingAttributions}`
);
expect(!!groundingMetadata.webSearchQueries).toBeTruthy(
`sys test failure on generateContent in preview for web search queries: ${groundingMetadata.webSearchQueries}`
);
Expand Down Expand Up @@ -894,6 +924,9 @@ describe('sendMessage', () => {
`sys test failure on sendMessage for grounding metadata: ${groundingMetadata}`
);
if (groundingMetadata) {
expect(!!groundingMetadata.groundingAttributions).toBeTruthy(
`sys test failure on sendMessage for grounding attributions: ${groundingMetadata.groundingAttributions}`
);
expect(!!groundingMetadata.webSearchQueries).toBeTruthy(
`sys test failure on sendMessage for web search queries: ${groundingMetadata.webSearchQueries}`
);
Expand All @@ -913,6 +946,9 @@ describe('sendMessage', () => {
`sys test failure on sendMessage for grounding metadata: ${groundingMetadata}`
);
if (groundingMetadata) {
expect(!!groundingMetadata.groundingAttributions).toBeTruthy(
`sys test failure on sendMessage for grounding attributions: ${groundingMetadata.groundingAttributions}`
);
expect(!!groundingMetadata.webSearchQueries).toBeTruthy(
`sys test failure on sendMessage for web search queries: ${groundingMetadata.webSearchQueries}`
);
Expand All @@ -931,6 +967,9 @@ describe('sendMessage', () => {
`sys test failure on sendMessage in preview for grounding metadata: ${groundingMetadata}`
);
if (groundingMetadata) {
expect(!!groundingMetadata.groundingAttributions).toBeTruthy(
`sys test failure on sendMessage in preview for grounding attributions: ${groundingMetadata.groundingAttributions}`
);
expect(!!groundingMetadata.webSearchQueries).toBeTruthy(
`sys test failure on sendMessage in preview for web search queries: ${groundingMetadata.webSearchQueries}`
);
Expand All @@ -950,6 +989,9 @@ describe('sendMessage', () => {
`sys test failure on sendMessage in preview for grounding metadata: ${groundingMetadata}`
);
if (groundingMetadata) {
expect(!!groundingMetadata.groundingAttributions).toBeTruthy(
`sys test failure on sendMessage in preview for grounding attributions: ${groundingMetadata.groundingAttributions}`
);
expect(!!groundingMetadata.webSearchQueries).toBeTruthy(
`sys test failure on sendMessage in preview for web search queries: ${groundingMetadata.webSearchQueries}`
);
Expand Down Expand Up @@ -1153,6 +1195,9 @@ describe('sendMessageStream', () => {
`sys test failure on groundingMetadata, ${groundingMetadata}`
);
if (groundingMetadata) {
expect(!!groundingMetadata.groundingAttributions).toBeTruthy(
`sys test failure on groundingMetadata.groundingAttributions, ${groundingMetadata.groundingAttributions}`
);
expect(!!groundingMetadata.webSearchQueries).toBeTruthy(
`sys test failure on groundingMetadata.webSearchQueries, ${groundingMetadata.webSearchQueries}`
);
Expand All @@ -1172,6 +1217,9 @@ describe('sendMessageStream', () => {
`sys test failure on groundingMetadata, ${groundingMetadata}`
);
if (groundingMetadata) {
expect(!!groundingMetadata.groundingAttributions).toBeTruthy(
`sys test failure on groundingMetadata.groundingAttributions, ${groundingMetadata.groundingAttributions}`
);
expect(!!groundingMetadata.webSearchQueries).toBeTruthy(
`sys test failure on groundingMetadata.webSearchQueries, ${groundingMetadata.webSearchQueries}`
);
Expand All @@ -1190,6 +1238,9 @@ describe('sendMessageStream', () => {
`sys test failure on groundingMetadata in preview, ${groundingMetadata}`
);
if (groundingMetadata) {
expect(!!groundingMetadata.groundingAttributions).toBeTruthy(
`sys test failure on groundingMetadata.groundingAttributions in preview, ${groundingMetadata.groundingAttributions}`
);
expect(!!groundingMetadata.webSearchQueries).toBeTruthy(
`sys test failure on groundingMetadata.webSearchQueries in preview, ${groundingMetadata.webSearchQueries}`
);
Expand All @@ -1209,6 +1260,9 @@ describe('sendMessageStream', () => {
`sys test failure on groundingMetadata in preview, ${groundingMetadata}`
);
if (groundingMetadata) {
expect(!!groundingMetadata.groundingAttributions).toBeTruthy(
`sys test failure on groundingMetadata.groundingAttributions in preview, ${groundingMetadata.groundingAttributions}`
);
expect(!!groundingMetadata.webSearchQueries).toBeTruthy(
`sys test failure on groundingMetadata.webSearchQueries in preview, ${groundingMetadata.webSearchQueries}`
);
Expand Down

0 comments on commit 9eb82c3

Please sign in to comment.