Skip to content

Commit a027010

Browse files
authored
fix: handle vpc-sc violations in LoadCodeAssist method (google-gemini#7824)
1 parent ee1b395 commit a027010

File tree

3 files changed

+90
-7
lines changed

3 files changed

+90
-7
lines changed

packages/core/src/code_assist/server.test.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,4 +215,41 @@ describe('CodeAssistServer', () => {
215215
}),
216216
).rejects.toThrow();
217217
});
218+
219+
it('should handle VPC-SC errors when calling loadCodeAssist', async () => {
220+
const client = new OAuth2Client();
221+
const server = new CodeAssistServer(
222+
client,
223+
'test-project',
224+
{},
225+
'test-session',
226+
UserTierId.FREE,
227+
);
228+
const mockVpcScError = {
229+
response: {
230+
data: {
231+
error: {
232+
details: [
233+
{
234+
reason: 'SECURITY_POLICY_VIOLATED',
235+
},
236+
],
237+
},
238+
},
239+
},
240+
};
241+
vi.spyOn(server, 'requestPost').mockRejectedValue(mockVpcScError);
242+
243+
const response = await server.loadCodeAssist({
244+
metadata: {},
245+
});
246+
247+
expect(server.requestPost).toHaveBeenCalledWith(
248+
'loadCodeAssist',
249+
expect.any(Object),
250+
);
251+
expect(response).toEqual({
252+
currentTier: { id: UserTierId.STANDARD },
253+
});
254+
});
218255
});

packages/core/src/code_assist/server.ts

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import type { OAuth2Client } from 'google-auth-library';
88
import type {
99
CodeAssistGlobalUserSettingResponse,
10+
GoogleRpcResponse,
1011
LoadCodeAssistRequest,
1112
LoadCodeAssistResponse,
1213
LongRunningOperationResponse,
@@ -23,7 +24,7 @@ import type {
2324
} from '@google/genai';
2425
import * as readline from 'node:readline';
2526
import type { ContentGenerator } from '../core/contentGenerator.js';
26-
import type { UserTierId } from './types.js';
27+
import { UserTierId } from './types.js';
2728
import type {
2829
CaCountTokenResponse,
2930
CaGenerateContentResponse,
@@ -103,10 +104,20 @@ export class CodeAssistServer implements ContentGenerator {
103104
async loadCodeAssist(
104105
req: LoadCodeAssistRequest,
105106
): Promise<LoadCodeAssistResponse> {
106-
return await this.requestPost<LoadCodeAssistResponse>(
107-
'loadCodeAssist',
108-
req,
109-
);
107+
try {
108+
return await this.requestPost<LoadCodeAssistResponse>(
109+
'loadCodeAssist',
110+
req,
111+
);
112+
} catch (e) {
113+
if (isVpcScAffectedUser(e)) {
114+
return {
115+
currentTier: { id: UserTierId.STANDARD },
116+
};
117+
} else {
118+
throw e;
119+
}
120+
}
110121
}
111122

112123
async getCodeAssistGlobalUserSetting(): Promise<CodeAssistGlobalUserSettingResponse> {
@@ -221,3 +232,22 @@ export class CodeAssistServer implements ContentGenerator {
221232
return `${endpoint}/${CODE_ASSIST_API_VERSION}:${method}`;
222233
}
223234
}
235+
236+
function isVpcScAffectedUser(error: unknown): boolean {
237+
if (error && typeof error === 'object' && 'response' in error) {
238+
const gaxiosError = error as {
239+
response?: {
240+
data?: unknown;
241+
};
242+
};
243+
const response = gaxiosError.response?.data as
244+
| GoogleRpcResponse
245+
| undefined;
246+
if (Array.isArray(response?.error?.details)) {
247+
return response.error.details.some(
248+
(detail) => detail.reason === 'SECURITY_POLICY_VIOLATED',
249+
);
250+
}
251+
}
252+
return false;
253+
}

packages/core/src/code_assist/types.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ export interface LoadCodeAssistResponse {
5757
*/
5858
export interface GeminiUserTier {
5959
id: UserTierId;
60-
name: string;
61-
description: string;
60+
name?: string;
61+
description?: string;
6262
// This value is used to declare whether a given tier requires the user to configure the project setting on the IDE settings or not.
6363
userDefinedCloudaicompanionProject?: boolean | null;
6464
isDefault?: boolean;
@@ -183,3 +183,19 @@ export interface CodeAssistGlobalUserSettingResponse {
183183
cloudaicompanionProject?: string;
184184
freeTierDataCollectionOptin: boolean;
185185
}
186+
187+
/**
188+
* Relevant fields that can be returned from a Google RPC response
189+
*/
190+
export interface GoogleRpcResponse {
191+
error?: {
192+
details?: GoogleRpcErrorInfo[];
193+
};
194+
}
195+
196+
/**
197+
* Relevant fields that can be returned in the details of an error returned from GoogleRPCs
198+
*/
199+
interface GoogleRpcErrorInfo {
200+
reason?: string;
201+
}

0 commit comments

Comments
 (0)