mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-12 12:54:07 -07:00
fix(core): handle optional response fields from code assist API (#20345)
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
|||||||
type CodeAssistServer,
|
type CodeAssistServer,
|
||||||
UserTierId,
|
UserTierId,
|
||||||
getCodeAssistServer,
|
getCodeAssistServer,
|
||||||
|
debugLogger,
|
||||||
} from '@google/gemini-cli-core';
|
} from '@google/gemini-cli-core';
|
||||||
|
|
||||||
export interface PrivacyState {
|
export interface PrivacyState {
|
||||||
@@ -103,7 +104,12 @@ async function getRemoteDataCollectionOptIn(
|
|||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
const resp = await server.getCodeAssistGlobalUserSetting();
|
const resp = await server.getCodeAssistGlobalUserSetting();
|
||||||
return resp.freeTierDataCollectionOptin;
|
if (resp.freeTierDataCollectionOptin === undefined) {
|
||||||
|
debugLogger.warn(
|
||||||
|
'Warning: Code Assist API did not return freeTierDataCollectionOptin. Defaulting to true.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return resp.freeTierDataCollectionOptin ?? true;
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
if (error && typeof error === 'object' && 'response' in error) {
|
if (error && typeof error === 'object' && 'response' in error) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||||
@@ -128,5 +134,10 @@ async function setRemoteDataCollectionOptIn(
|
|||||||
cloudaicompanionProject: server.projectId,
|
cloudaicompanionProject: server.projectId,
|
||||||
freeTierDataCollectionOptin: optIn,
|
freeTierDataCollectionOptin: optIn,
|
||||||
});
|
});
|
||||||
return resp.freeTierDataCollectionOptin;
|
if (resp.freeTierDataCollectionOptin === undefined) {
|
||||||
|
debugLogger.warn(
|
||||||
|
`Warning: Code Assist API did not return freeTierDataCollectionOptin. Defaulting to ${optIn}.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return resp.freeTierDataCollectionOptin ?? optIn;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -246,7 +246,7 @@ describe('converter', () => {
|
|||||||
};
|
};
|
||||||
const genaiRes = fromGenerateContentResponse(codeAssistRes);
|
const genaiRes = fromGenerateContentResponse(codeAssistRes);
|
||||||
expect(genaiRes).toBeInstanceOf(GenerateContentResponse);
|
expect(genaiRes).toBeInstanceOf(GenerateContentResponse);
|
||||||
expect(genaiRes.candidates).toEqual(codeAssistRes.response.candidates);
|
expect(genaiRes.candidates).toEqual(codeAssistRes.response!.candidates);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle prompt feedback and usage metadata', () => {
|
it('should handle prompt feedback and usage metadata', () => {
|
||||||
@@ -266,10 +266,10 @@ describe('converter', () => {
|
|||||||
};
|
};
|
||||||
const genaiRes = fromGenerateContentResponse(codeAssistRes);
|
const genaiRes = fromGenerateContentResponse(codeAssistRes);
|
||||||
expect(genaiRes.promptFeedback).toEqual(
|
expect(genaiRes.promptFeedback).toEqual(
|
||||||
codeAssistRes.response.promptFeedback,
|
codeAssistRes.response!.promptFeedback,
|
||||||
);
|
);
|
||||||
expect(genaiRes.usageMetadata).toEqual(
|
expect(genaiRes.usageMetadata).toEqual(
|
||||||
codeAssistRes.response.usageMetadata,
|
codeAssistRes.response!.usageMetadata,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -296,7 +296,7 @@ describe('converter', () => {
|
|||||||
};
|
};
|
||||||
const genaiRes = fromGenerateContentResponse(codeAssistRes);
|
const genaiRes = fromGenerateContentResponse(codeAssistRes);
|
||||||
expect(genaiRes.automaticFunctionCallingHistory).toEqual(
|
expect(genaiRes.automaticFunctionCallingHistory).toEqual(
|
||||||
codeAssistRes.response.automaticFunctionCallingHistory,
|
codeAssistRes.response!.automaticFunctionCallingHistory,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import type {
|
|||||||
ToolConfig,
|
ToolConfig,
|
||||||
} from '@google/genai';
|
} from '@google/genai';
|
||||||
import { GenerateContentResponse } from '@google/genai';
|
import { GenerateContentResponse } from '@google/genai';
|
||||||
|
import { debugLogger } from '../utils/debugLogger.js';
|
||||||
|
|
||||||
export interface CAGenerateContentRequest {
|
export interface CAGenerateContentRequest {
|
||||||
model: string;
|
model: string;
|
||||||
@@ -72,12 +73,12 @@ interface VertexGenerationConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface CaGenerateContentResponse {
|
export interface CaGenerateContentResponse {
|
||||||
response: VertexGenerateContentResponse;
|
response?: VertexGenerateContentResponse;
|
||||||
traceId?: string;
|
traceId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface VertexGenerateContentResponse {
|
interface VertexGenerateContentResponse {
|
||||||
candidates: Candidate[];
|
candidates?: Candidate[];
|
||||||
automaticFunctionCallingHistory?: Content[];
|
automaticFunctionCallingHistory?: Content[];
|
||||||
promptFeedback?: GenerateContentResponsePromptFeedback;
|
promptFeedback?: GenerateContentResponsePromptFeedback;
|
||||||
usageMetadata?: GenerateContentResponseUsageMetadata;
|
usageMetadata?: GenerateContentResponseUsageMetadata;
|
||||||
@@ -94,7 +95,7 @@ interface VertexCountTokenRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface CaCountTokenResponse {
|
export interface CaCountTokenResponse {
|
||||||
totalTokens: number;
|
totalTokens?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toCountTokenRequest(
|
export function toCountTokenRequest(
|
||||||
@@ -111,8 +112,13 @@ export function toCountTokenRequest(
|
|||||||
export function fromCountTokenResponse(
|
export function fromCountTokenResponse(
|
||||||
res: CaCountTokenResponse,
|
res: CaCountTokenResponse,
|
||||||
): CountTokensResponse {
|
): CountTokensResponse {
|
||||||
|
if (res.totalTokens === undefined) {
|
||||||
|
debugLogger.warn(
|
||||||
|
'Warning: Code Assist API did not return totalTokens. Defaulting to 0.',
|
||||||
|
);
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
totalTokens: res.totalTokens,
|
totalTokens: res.totalTokens ?? 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import type { AuthClient } from 'google-auth-library';
|
|||||||
import type { ValidationHandler } from '../fallback/types.js';
|
import type { ValidationHandler } from '../fallback/types.js';
|
||||||
import { ChangeAuthRequestedError } from '../utils/errors.js';
|
import { ChangeAuthRequestedError } from '../utils/errors.js';
|
||||||
import { ValidationRequiredError } from '../utils/googleQuotaErrors.js';
|
import { ValidationRequiredError } from '../utils/googleQuotaErrors.js';
|
||||||
|
import { debugLogger } from '../utils/debugLogger.js';
|
||||||
|
|
||||||
export class ProjectIdRequiredError extends Error {
|
export class ProjectIdRequiredError extends Error {
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -130,11 +131,20 @@ export async function setupUser(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (loadRes.currentTier) {
|
if (loadRes.currentTier) {
|
||||||
|
if (!loadRes.paidTier?.id && !loadRes.currentTier.id) {
|
||||||
|
debugLogger.warn(
|
||||||
|
'Warning: Code Assist API did not return a user tier ID. Defaulting to STANDARD tier.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (!loadRes.cloudaicompanionProject) {
|
if (!loadRes.cloudaicompanionProject) {
|
||||||
if (projectId) {
|
if (projectId) {
|
||||||
return {
|
return {
|
||||||
projectId,
|
projectId,
|
||||||
userTier: loadRes.paidTier?.id ?? loadRes.currentTier.id,
|
userTier:
|
||||||
|
loadRes.paidTier?.id ??
|
||||||
|
loadRes.currentTier.id ??
|
||||||
|
UserTierId.STANDARD,
|
||||||
userTierName: loadRes.paidTier?.name ?? loadRes.currentTier.name,
|
userTierName: loadRes.paidTier?.name ?? loadRes.currentTier.name,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -144,13 +154,20 @@ export async function setupUser(
|
|||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
projectId: loadRes.cloudaicompanionProject,
|
projectId: loadRes.cloudaicompanionProject,
|
||||||
userTier: loadRes.paidTier?.id ?? loadRes.currentTier.id,
|
userTier:
|
||||||
|
loadRes.paidTier?.id ?? loadRes.currentTier.id ?? UserTierId.STANDARD,
|
||||||
userTierName: loadRes.paidTier?.name ?? loadRes.currentTier.name,
|
userTierName: loadRes.paidTier?.name ?? loadRes.currentTier.name,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const tier = getOnboardTier(loadRes);
|
const tier = getOnboardTier(loadRes);
|
||||||
|
|
||||||
|
if (!tier.id) {
|
||||||
|
debugLogger.warn(
|
||||||
|
'Warning: Code Assist API did not return an onboarding tier ID. Defaulting to STANDARD tier.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let onboardReq: OnboardUserRequest;
|
let onboardReq: OnboardUserRequest;
|
||||||
if (tier.id === UserTierId.FREE) {
|
if (tier.id === UserTierId.FREE) {
|
||||||
// The free tier uses a managed google cloud project. Setting a project in the `onboardUser` request causes a `Precondition Failed` error.
|
// The free tier uses a managed google cloud project. Setting a project in the `onboardUser` request causes a `Precondition Failed` error.
|
||||||
@@ -183,7 +200,7 @@ export async function setupUser(
|
|||||||
if (projectId) {
|
if (projectId) {
|
||||||
return {
|
return {
|
||||||
projectId,
|
projectId,
|
||||||
userTier: tier.id,
|
userTier: tier.id ?? UserTierId.STANDARD,
|
||||||
userTierName: tier.name,
|
userTierName: tier.name,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -193,7 +210,7 @@ export async function setupUser(
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
projectId: lroRes.response.cloudaicompanionProject.id,
|
projectId: lroRes.response.cloudaicompanionProject.id,
|
||||||
userTier: tier.id,
|
userTier: tier.id ?? UserTierId.STANDARD,
|
||||||
userTierName: tier.name,
|
userTierName: tier.name,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ export interface LoadCodeAssistResponse {
|
|||||||
* GeminiUserTier reflects the structure received from the CodeAssist when calling LoadCodeAssist.
|
* GeminiUserTier reflects the structure received from the CodeAssist when calling LoadCodeAssist.
|
||||||
*/
|
*/
|
||||||
export interface GeminiUserTier {
|
export interface GeminiUserTier {
|
||||||
id: UserTierId;
|
id?: UserTierId;
|
||||||
name?: string;
|
name?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
// This value is used to declare whether a given tier requires the user to configure the project setting on the IDE settings or not.
|
// This value is used to declare whether a given tier requires the user to configure the project setting on the IDE settings or not.
|
||||||
@@ -79,10 +79,10 @@ export interface GeminiUserTier {
|
|||||||
* @param tierName name of the tier.
|
* @param tierName name of the tier.
|
||||||
*/
|
*/
|
||||||
export interface IneligibleTier {
|
export interface IneligibleTier {
|
||||||
reasonCode: IneligibleTierReasonCode;
|
reasonCode?: IneligibleTierReasonCode;
|
||||||
reasonMessage: string;
|
reasonMessage?: string;
|
||||||
tierId: UserTierId;
|
tierId?: UserTierId;
|
||||||
tierName: string;
|
tierName?: string;
|
||||||
validationErrorMessage?: string;
|
validationErrorMessage?: string;
|
||||||
validationUrl?: string;
|
validationUrl?: string;
|
||||||
validationUrlLinkText?: string;
|
validationUrlLinkText?: string;
|
||||||
@@ -127,7 +127,7 @@ export type UserTierId = (typeof UserTierId)[keyof typeof UserTierId] | string;
|
|||||||
* privacy notice.
|
* privacy notice.
|
||||||
*/
|
*/
|
||||||
export interface PrivacyNotice {
|
export interface PrivacyNotice {
|
||||||
showNotice: boolean;
|
showNotice?: boolean;
|
||||||
noticeText?: string;
|
noticeText?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,7 +145,7 @@ export interface OnboardUserRequest {
|
|||||||
* http://google3/google/longrunning/operations.proto;rcl=698857719;l=107
|
* http://google3/google/longrunning/operations.proto;rcl=698857719;l=107
|
||||||
*/
|
*/
|
||||||
export interface LongRunningOperationResponse {
|
export interface LongRunningOperationResponse {
|
||||||
name: string;
|
name?: string;
|
||||||
done?: boolean;
|
done?: boolean;
|
||||||
response?: OnboardUserResponse;
|
response?: OnboardUserResponse;
|
||||||
}
|
}
|
||||||
@@ -157,8 +157,8 @@ export interface LongRunningOperationResponse {
|
|||||||
export interface OnboardUserResponse {
|
export interface OnboardUserResponse {
|
||||||
// tslint:disable-next-line:enforce-name-casing This is the name of the field in the proto.
|
// tslint:disable-next-line:enforce-name-casing This is the name of the field in the proto.
|
||||||
cloudaicompanionProject?: {
|
cloudaicompanionProject?: {
|
||||||
id: string;
|
id?: string;
|
||||||
name: string;
|
name?: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,7 +195,7 @@ export interface SetCodeAssistGlobalUserSettingRequest {
|
|||||||
|
|
||||||
export interface CodeAssistGlobalUserSettingResponse {
|
export interface CodeAssistGlobalUserSettingResponse {
|
||||||
cloudaicompanionProject?: string;
|
cloudaicompanionProject?: string;
|
||||||
freeTierDataCollectionOptin: boolean;
|
freeTierDataCollectionOptin?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user