Skip to content

Commit 8df4210

Browse files
fix(patch): cherry-pick 9a74271 to release/v0.33.0-preview.5-pr-21236 [CONFLICTS] (#21714)
Co-authored-by: Gaurav <39389231+gsquared94@users.noreply.github.com>
1 parent 508aaed commit 8df4210

10 files changed

Lines changed: 92 additions & 23 deletions

File tree

packages/cli/src/config/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,7 @@ export async function loadCliConfig(
875875
fakeResponses: argv.fakeResponses,
876876
recordResponses: argv.recordResponses,
877877
retryFetchErrors: settings.general?.retryFetchErrors,
878+
billing: settings.billing,
878879
maxAttempts: settings.general?.maxAttempts,
879880
ptyInfo: ptyInfo?.name,
880881
disableLLMCorrection: settings.tools?.disableLLMCorrection,

packages/cli/src/ui/hooks/creditsFlowHandler.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@ async function handleOverageMenu(
110110
isDialogPending,
111111
setOverageMenuRequest,
112112
setModelSwitchedFromQuotaError,
113-
historyManager,
114113
} = args;
115114

116115
logBillingEvent(
@@ -155,13 +154,6 @@ async function handleOverageMenu(
155154
setModelSwitchedFromQuotaError(false);
156155
config.setQuotaErrorOccurred(false);
157156
config.setOverageStrategy('always');
158-
historyManager.addItem(
159-
{
160-
type: MessageType.INFO,
161-
text: `Using AI Credits for this request.`,
162-
},
163-
Date.now(),
164-
);
165157
return 'retry_with_credits';
166158

167159
case 'use_fallback':

packages/cli/src/ui/hooks/useGeminiStream.test.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ describe('useGeminiStream', () => {
271271
addHistory: vi.fn(),
272272
getSessionId: vi.fn(() => 'test-session-id'),
273273
setQuotaErrorOccurred: vi.fn(),
274+
resetBillingTurnState: vi.fn(),
274275
getQuotaErrorOccurred: vi.fn(() => false),
275276
getModel: vi.fn(() => 'gemini-2.5-pro'),
276277
getContentGeneratorConfig: vi.fn(() => ({

packages/cli/src/ui/hooks/useGeminiStream.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1374,6 +1374,9 @@ export const useGeminiStream = (
13741374
if (!options?.isContinuation) {
13751375
setModelSwitchedFromQuotaError(false);
13761376
config.setQuotaErrorOccurred(false);
1377+
config.resetBillingTurnState(
1378+
settings.merged.billing?.overageStrategy,
1379+
);
13771380
suppressedToolErrorCountRef.current = 0;
13781381
suppressedToolErrorNoteShownRef.current = false;
13791382
lowVerbosityFailureNoteShownRef.current = false;
@@ -1534,6 +1537,7 @@ export const useGeminiStream = (
15341537
setThought,
15351538
maybeAddSuppressedToolErrorNote,
15361539
maybeAddLowVerbosityFailureNote,
1540+
settings.merged.billing?.overageStrategy,
15371541
],
15381542
);
15391543

packages/cli/src/ui/hooks/useQuotaAndFallback.ts

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,6 @@ export function useQuotaAndFallback({
6767
const isDialogPending = useRef(false);
6868
const isValidationPending = useRef(false);
6969

70-
// Initial overage strategy from settings; runtime value read from config at call time.
71-
const initialOverageStrategy =
72-
(settings.merged.billing?.overageStrategy as
73-
| 'ask'
74-
| 'always'
75-
| 'never'
76-
| undefined) ?? 'ask';
77-
7870
// Set up Flash fallback handler
7971
useEffect(() => {
8072
const fallbackHandler: FallbackModelHandler = async (
@@ -109,9 +101,7 @@ export function useQuotaAndFallback({
109101
? getResetTimeMessage(error.retryDelayMs)
110102
: undefined;
111103

112-
const overageStrategy =
113-
config.getBillingSettings().overageStrategy ??
114-
initialOverageStrategy;
104+
const overageStrategy = config.getBillingSettings().overageStrategy;
115105

116106
const creditsResult = await handleCreditsFlow({
117107
config,
@@ -209,7 +199,6 @@ export function useQuotaAndFallback({
209199
userTier,
210200
paidTier,
211201
settings,
212-
initialOverageStrategy,
213202
setModelSwitchedFromQuotaError,
214203
onShowAuthSelection,
215204
errorVerbosity,

packages/core/src/billing/billing.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,14 +229,14 @@ describe('billing', () => {
229229
expect(isOverageEligibleModel('gemini-3.1-pro-preview')).toBe(true);
230230
});
231231

232-
it('should return true for gemini-3.1-pro-preview-customtools', () => {
232+
it('should return false for gemini-3.1-pro-preview-customtools', () => {
233233
expect(isOverageEligibleModel('gemini-3.1-pro-preview-customtools')).toBe(
234234
false,
235235
);
236236
});
237237

238-
it('should return false for gemini-3-flash-preview', () => {
239-
expect(isOverageEligibleModel('gemini-3-flash-preview')).toBe(false);
238+
it('should return true for gemini-3-flash-preview', () => {
239+
expect(isOverageEligibleModel('gemini-3-flash-preview')).toBe(true);
240240
});
241241

242242
it('should return false for gemini-2.5-pro', () => {

packages/core/src/billing/billing.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type {
1212
import {
1313
PREVIEW_GEMINI_MODEL,
1414
PREVIEW_GEMINI_3_1_MODEL,
15+
PREVIEW_GEMINI_FLASH_MODEL,
1516
} from '../config/models.js';
1617

1718
/**
@@ -32,6 +33,7 @@ export const G1_CREDIT_TYPE: CreditType = 'GOOGLE_ONE_AI';
3233
export const OVERAGE_ELIGIBLE_MODELS = new Set([
3334
PREVIEW_GEMINI_MODEL,
3435
PREVIEW_GEMINI_3_1_MODEL,
36+
PREVIEW_GEMINI_FLASH_MODEL,
3537
]);
3638

3739
/**

packages/core/src/code_assist/server.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import {
4848
shouldAutoUseCredits,
4949
} from '../billing/billing.js';
5050
import { logBillingEvent } from '../telemetry/loggers.js';
51+
import { coreEvents } from '../utils/events.js';
5152
import { CreditsUsedEvent } from '../telemetry/billingEvents.js';
5253
import type {
5354
CaCountTokenResponse,
@@ -102,6 +103,11 @@ export class CodeAssistServer implements ContentGenerator {
102103
const modelIsEligible = isOverageEligibleModel(req.model);
103104
const shouldEnableCredits = modelIsEligible && autoUse;
104105

106+
if (shouldEnableCredits && !this.config?.getCreditsNotificationShown()) {
107+
this.config?.setCreditsNotificationShown(true);
108+
coreEvents.emitFeedback('info', 'Using AI Credits for this request.');
109+
}
110+
105111
const enabledCreditTypes = shouldEnableCredits
106112
? ([G1_CREDIT_TYPE] as string[])
107113
: undefined;

packages/core/src/config/config.test.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2397,6 +2397,65 @@ describe('Availability Service Integration', () => {
23972397
config.resetTurn();
23982398
expect(spy).toHaveBeenCalled();
23992399
});
2400+
2401+
it('resetTurn does NOT reset billing state', () => {
2402+
const config = new Config({
2403+
...baseParams,
2404+
billing: { overageStrategy: 'ask' },
2405+
});
2406+
2407+
// Simulate accepting credits mid-turn
2408+
config.setOverageStrategy('always');
2409+
config.setCreditsNotificationShown(true);
2410+
2411+
// resetTurn should leave billing state intact
2412+
config.resetTurn();
2413+
expect(config.getBillingSettings().overageStrategy).toBe('always');
2414+
expect(config.getCreditsNotificationShown()).toBe(true);
2415+
});
2416+
2417+
it('resetBillingTurnState resets overageStrategy to configured value', () => {
2418+
const config = new Config({
2419+
...baseParams,
2420+
billing: { overageStrategy: 'ask' },
2421+
});
2422+
2423+
config.setOverageStrategy('always');
2424+
expect(config.getBillingSettings().overageStrategy).toBe('always');
2425+
2426+
config.resetBillingTurnState('ask');
2427+
expect(config.getBillingSettings().overageStrategy).toBe('ask');
2428+
});
2429+
2430+
it('resetBillingTurnState preserves overageStrategy when configured as always', () => {
2431+
const config = new Config({
2432+
...baseParams,
2433+
billing: { overageStrategy: 'always' },
2434+
});
2435+
2436+
config.resetBillingTurnState('always');
2437+
expect(config.getBillingSettings().overageStrategy).toBe('always');
2438+
});
2439+
2440+
it('resetBillingTurnState defaults to ask when no strategy provided', () => {
2441+
const config = new Config({
2442+
...baseParams,
2443+
billing: { overageStrategy: 'always' },
2444+
});
2445+
2446+
config.resetBillingTurnState();
2447+
expect(config.getBillingSettings().overageStrategy).toBe('ask');
2448+
});
2449+
2450+
it('resetBillingTurnState resets creditsNotificationShown', () => {
2451+
const config = new Config(baseParams);
2452+
2453+
config.setCreditsNotificationShown(true);
2454+
expect(config.getCreditsNotificationShown()).toBe(true);
2455+
2456+
config.resetBillingTurnState();
2457+
expect(config.getCreditsNotificationShown()).toBe(false);
2458+
});
24002459
});
24012460

24022461
describe('Hooks configuration', () => {

packages/core/src/config/config.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,7 @@ export class Config implements McpContext {
671671
fallbackModelHandler?: FallbackModelHandler;
672672
validationHandler?: ValidationHandler;
673673
private quotaErrorOccurred: boolean = false;
674+
private creditsNotificationShown: boolean = false;
674675
private modelQuotas: Map<
675676
string,
676677
{ remaining: number; limit: number; resetTime?: string }
@@ -1438,6 +1439,12 @@ export class Config implements McpContext {
14381439
this.modelAvailabilityService.resetTurn();
14391440
}
14401441

1442+
/** Resets billing state (overageStrategy, creditsNotificationShown) once per user prompt. */
1443+
resetBillingTurnState(overageStrategy?: OverageStrategy): void {
1444+
this.creditsNotificationShown = false;
1445+
this.billing.overageStrategy = overageStrategy ?? 'ask';
1446+
}
1447+
14411448
getMaxSessionTurns(): number {
14421449
return this.maxSessionTurns;
14431450
}
@@ -1450,6 +1457,14 @@ export class Config implements McpContext {
14501457
return this.quotaErrorOccurred;
14511458
}
14521459

1460+
setCreditsNotificationShown(value: boolean): void {
1461+
this.creditsNotificationShown = value;
1462+
}
1463+
1464+
getCreditsNotificationShown(): boolean {
1465+
return this.creditsNotificationShown;
1466+
}
1467+
14531468
setQuota(
14541469
remaining: number | undefined,
14551470
limit: number | undefined,

0 commit comments

Comments
 (0)