mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-24 12:04:56 -07:00
fix(core): fix quota footer for non-auto models and improve display (#25121)
This commit is contained in:
@@ -34,8 +34,8 @@ export const ALL_ITEMS = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'quota',
|
id: 'quota',
|
||||||
header: '/stats',
|
header: 'quota',
|
||||||
description: 'Remaining usage on daily limit (not shown when unavailable)',
|
description: 'Percentage of daily limit used (not shown when unavailable)',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'memory-usage',
|
id: 'memory-usage',
|
||||||
|
|||||||
@@ -281,7 +281,7 @@ describe('<Footer />', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
expect(lastFrame()).toContain('85%');
|
expect(lastFrame()).toContain('85% used');
|
||||||
expect(normalizeFrame(lastFrame())).toMatchSnapshot();
|
expect(normalizeFrame(lastFrame())).toMatchSnapshot();
|
||||||
unmount();
|
unmount();
|
||||||
});
|
});
|
||||||
@@ -306,7 +306,7 @@ describe('<Footer />', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
expect(normalizeFrame(lastFrame())).not.toContain('used');
|
expect(normalizeFrame(lastFrame())).toContain('15% used');
|
||||||
expect(normalizeFrame(lastFrame())).toMatchSnapshot();
|
expect(normalizeFrame(lastFrame())).toMatchSnapshot();
|
||||||
unmount();
|
unmount();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -351,13 +351,11 @@ export const Footer: React.FC = () => {
|
|||||||
<QuotaDisplay
|
<QuotaDisplay
|
||||||
remaining={quotaStats.remaining}
|
remaining={quotaStats.remaining}
|
||||||
limit={quotaStats.limit}
|
limit={quotaStats.limit}
|
||||||
resetTime={quotaStats.resetTime}
|
|
||||||
terse={true}
|
|
||||||
forceShow={true}
|
forceShow={true}
|
||||||
lowercase={true}
|
lowercase={true}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
10, // "daily 100%" is 10 chars, but terse is "100%" (4 chars)
|
9, // "100% used" is 9 chars
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -256,7 +256,7 @@ describe('<FooterConfigDialog />', () => {
|
|||||||
expect(nextLine).toContain('·');
|
expect(nextLine).toContain('·');
|
||||||
expect(nextLine).toContain('~/project/path');
|
expect(nextLine).toContain('~/project/path');
|
||||||
expect(nextLine).toContain('docker');
|
expect(nextLine).toContain('docker');
|
||||||
expect(nextLine).toContain('97%');
|
expect(nextLine).toContain('42% used');
|
||||||
});
|
});
|
||||||
|
|
||||||
await expect(renderResult).toMatchSvgSnapshot();
|
await expect(renderResult).toMatchSvgSnapshot();
|
||||||
|
|||||||
@@ -242,7 +242,7 @@ export const FooterConfigDialog: React.FC<FooterConfigDialogProps> = ({
|
|||||||
'context-used': (
|
'context-used': (
|
||||||
<Text color={getColor('context-used', itemColor)}>85% used</Text>
|
<Text color={getColor('context-used', itemColor)}>85% used</Text>
|
||||||
),
|
),
|
||||||
quota: <Text color={getColor('quota', itemColor)}>97%</Text>,
|
quota: <Text color={getColor('quota', itemColor)}>42% used</Text>,
|
||||||
'memory-usage': (
|
'memory-usage': (
|
||||||
<Text color={getColor('memory-usage', itemColor)}>260 MB</Text>
|
<Text color={getColor('memory-usage', itemColor)}>260 MB</Text>
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
exports[`<Footer /> > displays "Limit reached" message when remaining is 0 1`] = `
|
exports[`<Footer /> > displays "Limit reached" message when remaining is 0 1`] = `
|
||||||
" workspace (/directory) sandbox /model /stats
|
" workspace (/directory) sandbox /model quota
|
||||||
~/project/foo/bar/and/some/more/directories/to/make/it/long no sandbox gemini-pro limit reached
|
~/project/foo/bar/and/some/more/directories/to/make/it/long no sandbox gemini-pro limit reached
|
||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`<Footer /> > displays the usage indicator when usage is low 1`] = `
|
exports[`<Footer /> > displays the usage indicator when usage is low 1`] = `
|
||||||
" workspace (/directory) sandbox /model /stats
|
" workspace (/directory) sandbox /model quota
|
||||||
~/project/foo/bar/and/some/more/directories/to/make/it/long no sandbox gemini-pro 85%
|
~/project/foo/bar/and/some/more/directories/to/make/it/long no sandbox gemini-pro 85% used
|
||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ exports[`<Footer /> > footer configuration filtering (golden snapshots) > render
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`<Footer /> > hides the usage indicator when usage is not near limit 1`] = `
|
exports[`<Footer /> > hides the usage indicator when usage is not near limit 1`] = `
|
||||||
" workspace (/directory) sandbox /model /stats
|
" workspace (/directory) sandbox /model quota
|
||||||
~/project/foo/bar/and/some/more/directories/to/make/it/long no sandbox gemini-pro 15%
|
~/project/foo/bar/and/some/more/directories/to/make/it/long no sandbox gemini-pro 15% used
|
||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
|
|||||||
+9
-9
@@ -50,7 +50,7 @@
|
|||||||
<text x="72" y="240" fill="#ffffff" textLength="54" lengthAdjust="spacingAndGlyphs"> quota</text>
|
<text x="72" y="240" fill="#ffffff" textLength="54" lengthAdjust="spacingAndGlyphs"> quota</text>
|
||||||
<text x="891" y="240" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
<text x="891" y="240" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||||
<text x="0" y="257" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
<text x="0" y="257" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||||
<text x="45" y="257" fill="#afafaf" textLength="540" lengthAdjust="spacingAndGlyphs"> Remaining usage on daily limit (not shown when unavailable)</text>
|
<text x="45" y="257" fill="#afafaf" textLength="540" lengthAdjust="spacingAndGlyphs"> Percentage of daily limit used (not shown when unavailable)</text>
|
||||||
<text x="891" y="257" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
<text x="891" y="257" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||||
<text x="0" y="274" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
<text x="0" y="274" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||||
<text x="45" y="274" fill="#afafaf" textLength="27" lengthAdjust="spacingAndGlyphs">[ ]</text>
|
<text x="45" y="274" fill="#afafaf" textLength="27" lengthAdjust="spacingAndGlyphs">[ ]</text>
|
||||||
@@ -132,10 +132,10 @@
|
|||||||
<text x="0" y="631" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
<text x="0" y="631" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||||
<text x="27" y="631" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
<text x="27" y="631" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||||
<text x="45" y="631" fill="#afafaf" textLength="198" lengthAdjust="spacingAndGlyphs">workspace (/directory)</text>
|
<text x="45" y="631" fill="#afafaf" textLength="198" lengthAdjust="spacingAndGlyphs">workspace (/directory)</text>
|
||||||
<text x="297" y="631" fill="#afafaf" textLength="54" lengthAdjust="spacingAndGlyphs">branch</text>
|
<text x="288" y="631" fill="#afafaf" textLength="54" lengthAdjust="spacingAndGlyphs">branch</text>
|
||||||
<text x="405" y="631" fill="#afafaf" textLength="63" lengthAdjust="spacingAndGlyphs">sandbox</text>
|
<text x="396" y="631" fill="#afafaf" textLength="63" lengthAdjust="spacingAndGlyphs">sandbox</text>
|
||||||
<text x="513" y="631" fill="#afafaf" textLength="54" lengthAdjust="spacingAndGlyphs">/model</text>
|
<text x="504" y="631" fill="#afafaf" textLength="54" lengthAdjust="spacingAndGlyphs">/model</text>
|
||||||
<text x="693" y="631" fill="#afafaf" textLength="54" lengthAdjust="spacingAndGlyphs">/stats</text>
|
<text x="684" y="631" fill="#afafaf" textLength="45" lengthAdjust="spacingAndGlyphs">quota</text>
|
||||||
<rect x="801" y="629" width="36" height="17" fill="#001a00" />
|
<rect x="801" y="629" width="36" height="17" fill="#001a00" />
|
||||||
<text x="801" y="631" fill="#ffffff" textLength="36" lengthAdjust="spacingAndGlyphs">diff</text>
|
<text x="801" y="631" fill="#ffffff" textLength="36" lengthAdjust="spacingAndGlyphs">diff</text>
|
||||||
<rect x="837" y="629" width="18" height="17" fill="#001a00" />
|
<rect x="837" y="629" width="18" height="17" fill="#001a00" />
|
||||||
@@ -144,10 +144,10 @@
|
|||||||
<text x="0" y="648" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
<text x="0" y="648" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||||
<text x="27" y="648" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
<text x="27" y="648" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||||
<text x="45" y="648" fill="#ffffff" textLength="126" lengthAdjust="spacingAndGlyphs">~/project/path</text>
|
<text x="45" y="648" fill="#ffffff" textLength="126" lengthAdjust="spacingAndGlyphs">~/project/path</text>
|
||||||
<text x="297" y="648" fill="#ffffff" textLength="36" lengthAdjust="spacingAndGlyphs">main</text>
|
<text x="288" y="648" fill="#ffffff" textLength="36" lengthAdjust="spacingAndGlyphs">main</text>
|
||||||
<text x="405" y="648" fill="#00cd00" textLength="54" lengthAdjust="spacingAndGlyphs">docker</text>
|
<text x="396" y="648" fill="#00cd00" textLength="54" lengthAdjust="spacingAndGlyphs">docker</text>
|
||||||
<text x="513" y="648" fill="#ffffff" textLength="126" lengthAdjust="spacingAndGlyphs">gemini-2.5-pro</text>
|
<text x="504" y="648" fill="#ffffff" textLength="126" lengthAdjust="spacingAndGlyphs">gemini-2.5-pro</text>
|
||||||
<text x="693" y="648" fill="#ffffff" textLength="27" lengthAdjust="spacingAndGlyphs">97%</text>
|
<text x="684" y="648" fill="#ffffff" textLength="72" lengthAdjust="spacingAndGlyphs">42% used</text>
|
||||||
<rect x="801" y="646" width="27" height="17" fill="#001a00" />
|
<rect x="801" y="646" width="27" height="17" fill="#001a00" />
|
||||||
<text x="801" y="648" fill="#d7ffd7" textLength="27" lengthAdjust="spacingAndGlyphs">+12</text>
|
<text x="801" y="648" fill="#d7ffd7" textLength="27" lengthAdjust="spacingAndGlyphs">+12</text>
|
||||||
<rect x="828" y="646" width="9" height="17" fill="#001a00" />
|
<rect x="828" y="646" width="9" height="17" fill="#001a00" />
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
+9
-9
@@ -59,7 +59,7 @@
|
|||||||
<text x="72" y="240" fill="#ffffff" textLength="54" lengthAdjust="spacingAndGlyphs"> quota</text>
|
<text x="72" y="240" fill="#ffffff" textLength="54" lengthAdjust="spacingAndGlyphs"> quota</text>
|
||||||
<text x="891" y="240" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
<text x="891" y="240" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||||
<text x="0" y="257" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
<text x="0" y="257" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||||
<text x="45" y="257" fill="#afafaf" textLength="540" lengthAdjust="spacingAndGlyphs"> Remaining usage on daily limit (not shown when unavailable)</text>
|
<text x="45" y="257" fill="#afafaf" textLength="540" lengthAdjust="spacingAndGlyphs"> Percentage of daily limit used (not shown when unavailable)</text>
|
||||||
<text x="891" y="257" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
<text x="891" y="257" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||||
<text x="0" y="274" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
<text x="0" y="274" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||||
<text x="45" y="274" fill="#afafaf" textLength="27" lengthAdjust="spacingAndGlyphs">[ ]</text>
|
<text x="45" y="274" fill="#afafaf" textLength="27" lengthAdjust="spacingAndGlyphs">[ ]</text>
|
||||||
@@ -133,10 +133,10 @@
|
|||||||
<text x="27" y="631" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
<text x="27" y="631" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||||
<rect x="45" y="629" width="198" height="17" fill="#001a00" />
|
<rect x="45" y="629" width="198" height="17" fill="#001a00" />
|
||||||
<text x="45" y="631" fill="#ffffff" textLength="198" lengthAdjust="spacingAndGlyphs">workspace (/directory)</text>
|
<text x="45" y="631" fill="#ffffff" textLength="198" lengthAdjust="spacingAndGlyphs">workspace (/directory)</text>
|
||||||
<text x="324" y="631" fill="#afafaf" textLength="54" lengthAdjust="spacingAndGlyphs">branch</text>
|
<text x="315" y="631" fill="#afafaf" textLength="54" lengthAdjust="spacingAndGlyphs">branch</text>
|
||||||
<text x="459" y="631" fill="#afafaf" textLength="63" lengthAdjust="spacingAndGlyphs">sandbox</text>
|
<text x="450" y="631" fill="#afafaf" textLength="63" lengthAdjust="spacingAndGlyphs">sandbox</text>
|
||||||
<text x="594" y="631" fill="#afafaf" textLength="54" lengthAdjust="spacingAndGlyphs">/model</text>
|
<text x="585" y="631" fill="#afafaf" textLength="54" lengthAdjust="spacingAndGlyphs">/model</text>
|
||||||
<text x="801" y="631" fill="#afafaf" textLength="54" lengthAdjust="spacingAndGlyphs">/stats</text>
|
<text x="783" y="631" fill="#afafaf" textLength="45" lengthAdjust="spacingAndGlyphs">quota</text>
|
||||||
<text x="864" y="631" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
<text x="864" y="631" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||||
<text x="891" y="631" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
<text x="891" y="631" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||||
<text x="0" y="648" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
<text x="0" y="648" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||||
@@ -144,10 +144,10 @@
|
|||||||
<rect x="45" y="646" width="126" height="17" fill="#001a00" />
|
<rect x="45" y="646" width="126" height="17" fill="#001a00" />
|
||||||
<text x="45" y="648" fill="#ffffff" textLength="126" lengthAdjust="spacingAndGlyphs">~/project/path</text>
|
<text x="45" y="648" fill="#ffffff" textLength="126" lengthAdjust="spacingAndGlyphs">~/project/path</text>
|
||||||
<rect x="171" y="646" width="72" height="17" fill="#001a00" />
|
<rect x="171" y="646" width="72" height="17" fill="#001a00" />
|
||||||
<text x="324" y="648" fill="#ffffff" textLength="36" lengthAdjust="spacingAndGlyphs">main</text>
|
<text x="315" y="648" fill="#ffffff" textLength="36" lengthAdjust="spacingAndGlyphs">main</text>
|
||||||
<text x="459" y="648" fill="#00cd00" textLength="54" lengthAdjust="spacingAndGlyphs">docker</text>
|
<text x="450" y="648" fill="#00cd00" textLength="54" lengthAdjust="spacingAndGlyphs">docker</text>
|
||||||
<text x="594" y="648" fill="#ffffff" textLength="126" lengthAdjust="spacingAndGlyphs">gemini-2.5-pro</text>
|
<text x="585" y="648" fill="#ffffff" textLength="126" lengthAdjust="spacingAndGlyphs">gemini-2.5-pro</text>
|
||||||
<text x="801" y="648" fill="#ffffff" textLength="27" lengthAdjust="spacingAndGlyphs">97%</text>
|
<text x="783" y="648" fill="#ffffff" textLength="72" lengthAdjust="spacingAndGlyphs">42% used</text>
|
||||||
<text x="864" y="648" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
<text x="864" y="648" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||||
<text x="891" y="648" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
<text x="891" y="648" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||||
<text x="0" y="665" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
<text x="0" y="665" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
+8
-8
@@ -50,7 +50,7 @@
|
|||||||
<text x="72" y="240" fill="#ffffff" textLength="54" lengthAdjust="spacingAndGlyphs"> quota</text>
|
<text x="72" y="240" fill="#ffffff" textLength="54" lengthAdjust="spacingAndGlyphs"> quota</text>
|
||||||
<text x="891" y="240" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
<text x="891" y="240" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||||
<text x="0" y="257" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
<text x="0" y="257" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||||
<text x="45" y="257" fill="#afafaf" textLength="540" lengthAdjust="spacingAndGlyphs"> Remaining usage on daily limit (not shown when unavailable)</text>
|
<text x="45" y="257" fill="#afafaf" textLength="540" lengthAdjust="spacingAndGlyphs"> Percentage of daily limit used (not shown when unavailable)</text>
|
||||||
<text x="891" y="257" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
<text x="891" y="257" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||||
<text x="0" y="274" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
<text x="0" y="274" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||||
<text x="45" y="274" fill="#afafaf" textLength="27" lengthAdjust="spacingAndGlyphs">[ ]</text>
|
<text x="45" y="274" fill="#afafaf" textLength="27" lengthAdjust="spacingAndGlyphs">[ ]</text>
|
||||||
@@ -131,13 +131,13 @@
|
|||||||
<text x="27" y="631" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
<text x="27" y="631" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||||
<text x="45" y="631" fill="#afafaf" textLength="126" lengthAdjust="spacingAndGlyphs">~/project/path</text>
|
<text x="45" y="631" fill="#afafaf" textLength="126" lengthAdjust="spacingAndGlyphs">~/project/path</text>
|
||||||
<text x="207" y="631" fill="#afafaf" textLength="27" lengthAdjust="spacingAndGlyphs"> · </text>
|
<text x="207" y="631" fill="#afafaf" textLength="27" lengthAdjust="spacingAndGlyphs"> · </text>
|
||||||
<text x="279" y="631" fill="#afafaf" textLength="36" lengthAdjust="spacingAndGlyphs">main</text>
|
<text x="270" y="631" fill="#afafaf" textLength="36" lengthAdjust="spacingAndGlyphs">main</text>
|
||||||
<text x="351" y="631" fill="#afafaf" textLength="27" lengthAdjust="spacingAndGlyphs"> · </text>
|
<text x="342" y="631" fill="#afafaf" textLength="27" lengthAdjust="spacingAndGlyphs"> · </text>
|
||||||
<text x="432" y="631" fill="#00cd00" textLength="54" lengthAdjust="spacingAndGlyphs">docker</text>
|
<text x="405" y="631" fill="#00cd00" textLength="54" lengthAdjust="spacingAndGlyphs">docker</text>
|
||||||
<text x="522" y="631" fill="#afafaf" textLength="27" lengthAdjust="spacingAndGlyphs"> · </text>
|
<text x="495" y="631" fill="#afafaf" textLength="27" lengthAdjust="spacingAndGlyphs"> · </text>
|
||||||
<text x="594" y="631" fill="#afafaf" textLength="126" lengthAdjust="spacingAndGlyphs">gemini-2.5-pro</text>
|
<text x="558" y="631" fill="#afafaf" textLength="126" lengthAdjust="spacingAndGlyphs">gemini-2.5-pro</text>
|
||||||
<text x="756" y="631" fill="#afafaf" textLength="27" lengthAdjust="spacingAndGlyphs"> · </text>
|
<text x="720" y="631" fill="#afafaf" textLength="27" lengthAdjust="spacingAndGlyphs"> · </text>
|
||||||
<text x="828" y="631" fill="#afafaf" textLength="27" lengthAdjust="spacingAndGlyphs">97%</text>
|
<text x="783" y="631" fill="#afafaf" textLength="72" lengthAdjust="spacingAndGlyphs">42% used</text>
|
||||||
<text x="864" y="631" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
<text x="864" y="631" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||||
<text x="891" y="631" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
<text x="891" y="631" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||||
<text x="0" y="648" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
<text x="0" y="648" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
@@ -16,7 +16,7 @@ exports[`<FooterConfigDialog /> > highlights the active item in the preview 1`]
|
|||||||
│ [✓] model-name │
|
│ [✓] model-name │
|
||||||
│ Current model identifier │
|
│ Current model identifier │
|
||||||
│ [✓] quota │
|
│ [✓] quota │
|
||||||
│ Remaining usage on daily limit (not shown when unavailable) │
|
│ Percentage of daily limit used (not shown when unavailable) │
|
||||||
│ [ ] context-used │
|
│ [ ] context-used │
|
||||||
│ Percentage of context window used │
|
│ Percentage of context window used │
|
||||||
│ [ ] memory-usage │
|
│ [ ] memory-usage │
|
||||||
@@ -38,8 +38,8 @@ exports[`<FooterConfigDialog /> > highlights the active item in the preview 1`]
|
|||||||
│ │
|
│ │
|
||||||
│ ┌────────────────────────────────────────────────────────────────────────────────────────────┐ │
|
│ ┌────────────────────────────────────────────────────────────────────────────────────────────┐ │
|
||||||
│ │ Preview: │ │
|
│ │ Preview: │ │
|
||||||
│ │ workspace (/directory) branch sandbox /model /stats diff │ │
|
│ │ workspace (/directory) branch sandbox /model quota diff │ │
|
||||||
│ │ ~/project/path main docker gemini-2.5-pro 97% +12 -4 │ │
|
│ │ ~/project/path main docker gemini-2.5-pro 42% used +12 -4 │ │
|
||||||
│ └────────────────────────────────────────────────────────────────────────────────────────────┘ │
|
│ └────────────────────────────────────────────────────────────────────────────────────────────┘ │
|
||||||
│ │
|
│ │
|
||||||
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯"
|
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯"
|
||||||
@@ -61,7 +61,7 @@ exports[`<FooterConfigDialog /> > renders correctly with default settings 1`] =
|
|||||||
│ [✓] model-name │
|
│ [✓] model-name │
|
||||||
│ Current model identifier │
|
│ Current model identifier │
|
||||||
│ [✓] quota │
|
│ [✓] quota │
|
||||||
│ Remaining usage on daily limit (not shown when unavailable) │
|
│ Percentage of daily limit used (not shown when unavailable) │
|
||||||
│ [ ] context-used │
|
│ [ ] context-used │
|
||||||
│ Percentage of context window used │
|
│ Percentage of context window used │
|
||||||
│ [ ] memory-usage │
|
│ [ ] memory-usage │
|
||||||
@@ -83,8 +83,8 @@ exports[`<FooterConfigDialog /> > renders correctly with default settings 1`] =
|
|||||||
│ │
|
│ │
|
||||||
│ ┌────────────────────────────────────────────────────────────────────────────────────────────┐ │
|
│ ┌────────────────────────────────────────────────────────────────────────────────────────────┐ │
|
||||||
│ │ Preview: │ │
|
│ │ Preview: │ │
|
||||||
│ │ workspace (/directory) branch sandbox /model /stats │ │
|
│ │ workspace (/directory) branch sandbox /model quota │ │
|
||||||
│ │ ~/project/path main docker gemini-2.5-pro 97% │ │
|
│ │ ~/project/path main docker gemini-2.5-pro 42% used │ │
|
||||||
│ └────────────────────────────────────────────────────────────────────────────────────────────┘ │
|
│ └────────────────────────────────────────────────────────────────────────────────────────────┘ │
|
||||||
│ │
|
│ │
|
||||||
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
|
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||||
@@ -107,7 +107,7 @@ exports[`<FooterConfigDialog /> > renders correctly with default settings 2`] =
|
|||||||
│ [✓] model-name │
|
│ [✓] model-name │
|
||||||
│ Current model identifier │
|
│ Current model identifier │
|
||||||
│ [✓] quota │
|
│ [✓] quota │
|
||||||
│ Remaining usage on daily limit (not shown when unavailable) │
|
│ Percentage of daily limit used (not shown when unavailable) │
|
||||||
│ [ ] context-used │
|
│ [ ] context-used │
|
||||||
│ Percentage of context window used │
|
│ Percentage of context window used │
|
||||||
│ [ ] memory-usage │
|
│ [ ] memory-usage │
|
||||||
@@ -129,8 +129,8 @@ exports[`<FooterConfigDialog /> > renders correctly with default settings 2`] =
|
|||||||
│ │
|
│ │
|
||||||
│ ┌────────────────────────────────────────────────────────────────────────────────────────────┐ │
|
│ ┌────────────────────────────────────────────────────────────────────────────────────────────┐ │
|
||||||
│ │ Preview: │ │
|
│ │ Preview: │ │
|
||||||
│ │ workspace (/directory) branch sandbox /model /stats │ │
|
│ │ workspace (/directory) branch sandbox /model quota │ │
|
||||||
│ │ ~/project/path main docker gemini-2.5-pro 97% │ │
|
│ │ ~/project/path main docker gemini-2.5-pro 42% used │ │
|
||||||
│ └────────────────────────────────────────────────────────────────────────────────────────────┘ │
|
│ └────────────────────────────────────────────────────────────────────────────────────────────┘ │
|
||||||
│ │
|
│ │
|
||||||
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯"
|
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯"
|
||||||
@@ -152,7 +152,7 @@ exports[`<FooterConfigDialog /> > updates the preview when Show footer labels is
|
|||||||
│ [✓] model-name │
|
│ [✓] model-name │
|
||||||
│ Current model identifier │
|
│ Current model identifier │
|
||||||
│ [✓] quota │
|
│ [✓] quota │
|
||||||
│ Remaining usage on daily limit (not shown when unavailable) │
|
│ Percentage of daily limit used (not shown when unavailable) │
|
||||||
│ [ ] context-used │
|
│ [ ] context-used │
|
||||||
│ Percentage of context window used │
|
│ Percentage of context window used │
|
||||||
│ [ ] memory-usage │
|
│ [ ] memory-usage │
|
||||||
@@ -174,7 +174,7 @@ exports[`<FooterConfigDialog /> > updates the preview when Show footer labels is
|
|||||||
│ │
|
│ │
|
||||||
│ ┌────────────────────────────────────────────────────────────────────────────────────────────┐ │
|
│ ┌────────────────────────────────────────────────────────────────────────────────────────────┐ │
|
||||||
│ │ Preview: │ │
|
│ │ Preview: │ │
|
||||||
│ │ ~/project/path · main · docker · gemini-2.5-pro · 97% │ │
|
│ │ ~/project/path · main · docker · gemini-2.5-pro · 42% used │ │
|
||||||
│ └────────────────────────────────────────────────────────────────────────────────────────────┘ │
|
│ └────────────────────────────────────────────────────────────────────────────────────────────┘ │
|
||||||
│ │
|
│ │
|
||||||
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯"
|
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯"
|
||||||
|
|||||||
@@ -3006,6 +3006,78 @@ describe('Config Quota & Preview Model Access', () => {
|
|||||||
// Never set => stays null (unknown); getter returns true so UI shows preview
|
// Never set => stays null (unknown); getter returns true so UI shows preview
|
||||||
expect(config.getHasAccessToPreviewModel()).toBe(true);
|
expect(config.getHasAccessToPreviewModel()).toBe(true);
|
||||||
});
|
});
|
||||||
|
it('should derive quota from remainingFraction when remainingAmount is missing', async () => {
|
||||||
|
mockCodeAssistServer.retrieveUserQuota.mockResolvedValue({
|
||||||
|
buckets: [
|
||||||
|
{
|
||||||
|
modelId: 'gemini-3-flash-preview',
|
||||||
|
remainingFraction: 0.96,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
config.setModel('gemini-3-flash-preview');
|
||||||
|
mockCoreEvents.emitQuotaChanged.mockClear();
|
||||||
|
await config.refreshUserQuota();
|
||||||
|
|
||||||
|
// Normalized: limit=100, remaining=96
|
||||||
|
expect(mockCoreEvents.emitQuotaChanged).toHaveBeenCalledWith(
|
||||||
|
96,
|
||||||
|
100,
|
||||||
|
undefined,
|
||||||
|
);
|
||||||
|
expect(config.getQuotaRemaining()).toBe(96);
|
||||||
|
expect(config.getQuotaLimit()).toBe(100);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should store quota from remainingFraction when remainingFraction is 0', async () => {
|
||||||
|
mockCodeAssistServer.retrieveUserQuota.mockResolvedValue({
|
||||||
|
buckets: [
|
||||||
|
{
|
||||||
|
modelId: 'gemini-3-pro-preview',
|
||||||
|
remainingFraction: 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
config.setModel('gemini-3-pro-preview');
|
||||||
|
mockCoreEvents.emitQuotaChanged.mockClear();
|
||||||
|
await config.refreshUserQuota();
|
||||||
|
|
||||||
|
// remaining=0, limit=100 but limit>0 check still passes
|
||||||
|
// however remaining=0 means 0% remaining = 100% used
|
||||||
|
expect(config.getQuotaRemaining()).toBe(0);
|
||||||
|
expect(config.getQuotaLimit()).toBe(100);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit QuotaChanged when model is switched via setModel', async () => {
|
||||||
|
mockCodeAssistServer.retrieveUserQuota.mockResolvedValue({
|
||||||
|
buckets: [
|
||||||
|
{
|
||||||
|
modelId: 'gemini-2.5-pro',
|
||||||
|
remainingAmount: '10',
|
||||||
|
remainingFraction: 0.2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
modelId: 'gemini-2.5-flash',
|
||||||
|
remainingAmount: '80',
|
||||||
|
remainingFraction: 0.8,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
config.setModel('auto-gemini-2.5');
|
||||||
|
await config.refreshUserQuota();
|
||||||
|
mockCoreEvents.emitQuotaChanged.mockClear();
|
||||||
|
|
||||||
|
// Switch to a specific model — should re-emit quota for that model
|
||||||
|
config.setModel('gemini-2.5-pro');
|
||||||
|
expect(mockCoreEvents.emitQuotaChanged).toHaveBeenCalledWith(
|
||||||
|
10,
|
||||||
|
50,
|
||||||
|
undefined,
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('refreshUserQuotaIfStale', () => {
|
describe('refreshUserQuotaIfStale', () => {
|
||||||
|
|||||||
@@ -832,18 +832,16 @@ export class Config implements McpContext, AgentLoopContext {
|
|||||||
private lastEmittedQuotaLimit: number | undefined;
|
private lastEmittedQuotaLimit: number | undefined;
|
||||||
|
|
||||||
private emitQuotaChangedEvent(): void {
|
private emitQuotaChangedEvent(): void {
|
||||||
const pooled = this.getPooledQuota();
|
const remaining = this.getQuotaRemaining();
|
||||||
|
const limit = this.getQuotaLimit();
|
||||||
|
const resetTime = this.getQuotaResetTime();
|
||||||
if (
|
if (
|
||||||
this.lastEmittedQuotaRemaining !== pooled.remaining ||
|
this.lastEmittedQuotaRemaining !== remaining ||
|
||||||
this.lastEmittedQuotaLimit !== pooled.limit
|
this.lastEmittedQuotaLimit !== limit
|
||||||
) {
|
) {
|
||||||
this.lastEmittedQuotaRemaining = pooled.remaining;
|
this.lastEmittedQuotaRemaining = remaining;
|
||||||
this.lastEmittedQuotaLimit = pooled.limit;
|
this.lastEmittedQuotaLimit = limit;
|
||||||
coreEvents.emitQuotaChanged(
|
coreEvents.emitQuotaChanged(remaining, limit, resetTime);
|
||||||
pooled.remaining,
|
|
||||||
pooled.limit,
|
|
||||||
pooled.resetTime,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1819,6 +1817,9 @@ export class Config implements McpContext, AgentLoopContext {
|
|||||||
// When the user explicitly sets a model, that becomes the active model.
|
// When the user explicitly sets a model, that becomes the active model.
|
||||||
this._activeModel = newModel;
|
this._activeModel = newModel;
|
||||||
coreEvents.emitModelChanged(newModel);
|
coreEvents.emitModelChanged(newModel);
|
||||||
|
this.lastEmittedQuotaRemaining = undefined;
|
||||||
|
this.lastEmittedQuotaLimit = undefined;
|
||||||
|
this.emitQuotaChangedEvent();
|
||||||
}
|
}
|
||||||
if (this.onModelChange && !isTemporary) {
|
if (this.onModelChange && !isTemporary) {
|
||||||
this.onModelChange(newModel);
|
this.onModelChange(newModel);
|
||||||
@@ -2112,24 +2113,31 @@ export class Config implements McpContext, AgentLoopContext {
|
|||||||
this.lastQuotaFetchTime = Date.now();
|
this.lastQuotaFetchTime = Date.now();
|
||||||
|
|
||||||
for (const bucket of quota.buckets) {
|
for (const bucket of quota.buckets) {
|
||||||
if (
|
if (!bucket.modelId || bucket.remainingFraction == null) {
|
||||||
bucket.modelId &&
|
continue;
|
||||||
bucket.remainingAmount &&
|
}
|
||||||
bucket.remainingFraction != null
|
|
||||||
) {
|
let remaining: number;
|
||||||
const remaining = parseInt(bucket.remainingAmount, 10);
|
let limit: number;
|
||||||
const limit =
|
|
||||||
|
if (bucket.remainingAmount) {
|
||||||
|
remaining = parseInt(bucket.remainingAmount, 10);
|
||||||
|
limit =
|
||||||
bucket.remainingFraction > 0
|
bucket.remainingFraction > 0
|
||||||
? Math.round(remaining / bucket.remainingFraction)
|
? Math.round(remaining / bucket.remainingFraction)
|
||||||
: (this.modelQuotas.get(bucket.modelId)?.limit ?? 0);
|
: (this.modelQuotas.get(bucket.modelId)?.limit ?? 0);
|
||||||
|
} else {
|
||||||
|
// Server only sent remainingFraction — use a normalized scale.
|
||||||
|
limit = 100;
|
||||||
|
remaining = Math.round(bucket.remainingFraction * limit);
|
||||||
|
}
|
||||||
|
|
||||||
if (!isNaN(remaining) && Number.isFinite(limit) && limit > 0) {
|
if (!isNaN(remaining) && Number.isFinite(limit) && limit > 0) {
|
||||||
this.modelQuotas.set(bucket.modelId, {
|
this.modelQuotas.set(bucket.modelId, {
|
||||||
remaining,
|
remaining,
|
||||||
limit,
|
limit,
|
||||||
resetTime: bucket.resetTime,
|
resetTime: bucket.resetTime,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.emitQuotaChangedEvent();
|
this.emitQuotaChangedEvent();
|
||||||
|
|||||||
Reference in New Issue
Block a user