Skip to content
Merged
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
15 changes: 12 additions & 3 deletions packages/core/src/code_assist/converter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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[]
Expand All @@ -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,
Expand All @@ -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)],
};
}

Expand Down
5 changes: 2 additions & 3 deletions packages/core/src/code_assist/experiments/experiments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE: JSON.parse() is also not type-safe because it returns any. I will follow up by disallowing unsafe-assignment as well in eslint config.

if (
(response.flags && !Array.isArray(response.flags)) ||
(response.experimentIds && !Array.isArray(response.experimentIds))
Expand All @@ -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);
}
Expand Down
3 changes: 1 addition & 2 deletions packages/core/src/code_assist/oauth-credential-storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
13 changes: 7 additions & 6 deletions packages/core/src/code_assist/oauth2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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();
Expand Down
64 changes: 40 additions & 24 deletions packages/core/src/code_assist/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import type { AuthClient } from 'google-auth-library';
import type {
CodeAssistGlobalUserSettingResponse,
GoogleRpcResponse,
LoadCodeAssistRequest,
LoadCodeAssistResponse,
LongRunningOperationResponse,
Expand Down Expand Up @@ -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: {
Expand All @@ -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: {
Expand All @@ -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> {
Expand Down Expand Up @@ -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
Expand All @@ -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;
}
Loading