Fix unsafe assertions in code_assist folder. (#19706)

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
This commit is contained in:
Christian Gunderman
2026-02-20 20:44:23 +00:00
committed by GitHub
parent c04602f209
commit b7555ab1e1
5 changed files with 62 additions and 38 deletions

View File

@@ -181,6 +181,16 @@ function maybeToContent(content?: ContentUnion): Content | undefined {
return toContent(content);
}
function isPart(c: ContentUnion): c is PartUnion {
return (
typeof c === 'object' &&
c !== null &&
!Array.isArray(c) &&
!('parts' in c) &&
!('role' in c)
);
}
function toContent(content: ContentUnion): Content {
if (Array.isArray(content)) {
// it's a PartsUnion[]
@@ -196,7 +206,7 @@ function toContent(content: ContentUnion): Content {
parts: [{ text: content }],
};
}
if ('parts' in content) {
if (!isPart(content)) {
// it's a Content - process parts to handle thought filtering
return {
...content,
@@ -208,8 +218,7 @@ function toContent(content: ContentUnion): Content {
// it's a Part
return {
role: 'user',
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
parts: [toPart(content as Part)],
parts: [toPart(content)],
};
}

View File

@@ -35,7 +35,7 @@ export async function getExperiments(
const expPath = process.env['GEMINI_EXP'];
debugLogger.debug('Reading experiments from', expPath);
const content = await fs.promises.readFile(expPath, 'utf8');
const response = JSON.parse(content);
const response: ListExperimentsResponse = JSON.parse(content);
if (
(response.flags && !Array.isArray(response.flags)) ||
(response.experimentIds && !Array.isArray(response.experimentIds))
@@ -44,8 +44,7 @@ export async function getExperiments(
'Invalid format for experiments file: `flags` and `experimentIds` must be arrays if present.',
);
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
return parseExperiments(response as ListExperimentsResponse);
return parseExperiments(response);
} catch (e) {
debugLogger.debug('Failed to read experiments from GEMINI_EXP', e);
}

View File

@@ -125,8 +125,7 @@ export class OAuthCredentialStorage {
throw error;
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
const credentials = JSON.parse(credsJson) as Credentials;
const credentials: Credentials = JSON.parse(credsJson);
// Save to new storage
await this.saveCredentials(credentials);

View File

@@ -115,9 +115,9 @@ async function initOauthClient(
if (
credentials &&
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
(credentials as { type?: string }).type ===
'external_account_authorized_user'
typeof credentials === 'object' &&
'type' in credentials &&
credentials.type === 'external_account_authorized_user'
) {
const auth = new GoogleAuth({
scopes: OAUTH_SCOPE,
@@ -603,9 +603,10 @@ export function getAvailablePort(): Promise<number> {
}
const server = net.createServer();
server.listen(0, () => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
const address = server.address()! as net.AddressInfo;
port = address.port;
const address = server.address();
if (address && typeof address === 'object') {
port = address.port;
}
});
server.on('listening', () => {
server.close();

View File

@@ -7,7 +7,6 @@
import type { AuthClient } from 'google-auth-library';
import type {
CodeAssistGlobalUserSettingResponse,
GoogleRpcResponse,
LoadCodeAssistRequest,
LoadCodeAssistResponse,
LongRunningOperationResponse,
@@ -296,7 +295,7 @@ export class CodeAssistServer implements ContentGenerator {
req: object,
signal?: AbortSignal,
): Promise<T> {
const res = await this.client.request({
const res = await this.client.request<T>({
url: this.getMethodUrl(method),
method: 'POST',
headers: {
@@ -307,15 +306,14 @@ export class CodeAssistServer implements ContentGenerator {
body: JSON.stringify(req),
signal,
});
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
return res.data as T;
return res.data;
}
private async makeGetRequest<T>(
url: string,
signal?: AbortSignal,
): Promise<T> {
const res = await this.client.request({
const res = await this.client.request<T>({
url,
method: 'GET',
headers: {
@@ -325,8 +323,7 @@ export class CodeAssistServer implements ContentGenerator {
responseType: 'json',
signal,
});
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
return res.data as T;
return res.data;
}
async requestGet<T>(method: string, signal?: AbortSignal): Promise<T> {
@@ -371,8 +368,7 @@ export class CodeAssistServer implements ContentGenerator {
if (bufferedLines.length === 0) {
continue; // no data to yield
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
yield JSON.parse(bufferedLines.join('\n')) as T;
yield JSON.parse(bufferedLines.join('\n'));
bufferedLines = []; // Reset the buffer after yielding
}
// Ignore other lines like comments or id fields
@@ -397,23 +393,43 @@ export class CodeAssistServer implements ContentGenerator {
}
}
function isVpcScAffectedUser(error: unknown): boolean {
if (error && typeof error === 'object' && 'response' in error) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
const gaxiosError = error as {
response?: {
data?: unknown;
interface VpcScErrorResponse {
response: {
data: {
error: {
details: unknown[];
};
};
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
const response = gaxiosError.response?.data as
| GoogleRpcResponse
| undefined;
if (Array.isArray(response?.error?.details)) {
return response.error.details.some(
(detail) => detail.reason === 'SECURITY_POLICY_VIOLATED',
);
}
};
}
function isVpcScErrorResponse(error: unknown): error is VpcScErrorResponse {
return (
!!error &&
typeof error === 'object' &&
'response' in error &&
!!error.response &&
typeof error.response === 'object' &&
'data' in error.response &&
!!error.response.data &&
typeof error.response.data === 'object' &&
'error' in error.response.data &&
!!error.response.data.error &&
typeof error.response.data.error === 'object' &&
'details' in error.response.data.error &&
Array.isArray(error.response.data.error.details)
);
}
function isVpcScAffectedUser(error: unknown): boolean {
if (isVpcScErrorResponse(error)) {
return error.response.data.error.details.some(
(detail: unknown) =>
detail &&
typeof detail === 'object' &&
'reason' in detail &&
detail.reason === 'SECURITY_POLICY_VIOLATED',
);
}
return false;
}