@@ -6,10 +6,11 @@ import { useApp } from '../context/AppContext';
66import { getApiKey , saveApiKey } from '../utils' ;
77import { MODELS_API_URL } from '../utils/constants' ;
88import { getProviderIds , getProviderDisplayName } from '../utils/providerUtils' ;
9- import { FaTimes , FaServer , FaKey , FaSlidersH , FaCode , FaFileAlt , FaShieldAlt , FaTint } from 'react-icons/fa' ;
9+ import { FaTimes , FaServer , FaKey , FaSlidersH , FaCode , FaFileAlt , FaShieldAlt , FaTint , FaInfoCircle , FaArrowLeft } from 'react-icons/fa' ;
10+ import { TokenBucketDemo } from './TokenBucketDemo' ;
1011
1112// Helper function to render resilience settings section
12- function ResilienceSettingsSection ( { config, updateConfig, sectionRef } ) {
13+ function ResilienceSettingsSection ( { config, updateConfig, sectionRef, onShowTokenBucket } ) {
1314 return (
1415 < section ref = { sectionRef } className = "config-section" >
1516 < div className = "config-section-header" >
@@ -72,6 +73,37 @@ function ResilienceSettingsSection({ config, updateConfig, sectionRef }) {
7273 < span > Rate limiting</ span >
7374 </ div >
7475 < small className = "resilience-hint resilience-hint-note" > Token bucket algorithm controls request and token consumption. When empty, requests wait for tokens to replenish. Applied per LLM provider.</ small >
76+ < button
77+ onClick = { onShowTokenBucket }
78+ style = { {
79+ display : 'inline-flex' ,
80+ alignItems : 'center' ,
81+ gap : '6px' ,
82+ padding : '8px 12px' ,
83+ marginTop : '8px' ,
84+ marginBottom : '12px' ,
85+ background : '#f4f4f5' ,
86+ border : '1px solid #e4e4e7' ,
87+ borderRadius : '6px' ,
88+ fontSize : '12px' ,
89+ color : '#09090b' ,
90+ cursor : 'pointer' ,
91+ transition : 'all 0.2s' ,
92+ fontWeight : 500 ,
93+ } }
94+ onMouseEnter = { ( e ) => {
95+ e . currentTarget . style . background = '#e4e4e7' ;
96+ e . currentTarget . style . borderColor = '#d4d4d8' ;
97+ } }
98+ onMouseLeave = { ( e ) => {
99+ e . currentTarget . style . background = '#f4f4f5' ;
100+ e . currentTarget . style . borderColor = '#e4e4e7' ;
101+ } }
102+ title = "Learn about Token Bucket Rate Algorithm"
103+ >
104+ < FaInfoCircle />
105+ Visualize Token Bucket Algorithm
106+ </ button >
75107 < div className = "resilience-grid" >
76108 < div className = "resilience-field" >
77109 < label > Requests/min</ label >
@@ -145,7 +177,7 @@ function ResilienceSettingsSection({ config, updateConfig, sectionRef }) {
145177}
146178
147179export function SettingsDrawer ( ) {
148- const { settingsOpen, setSettingsOpen, config, setConfig, saveConversation, settingsDefaultSection } = useApp ( ) ;
180+ const { settingsOpen, setSettingsOpen, config, setConfig, saveConversation, settingsDefaultSection, currentRoute , setCurrentRoute } = useApp ( ) ;
149181 const [ apiKey , setApiKeyState ] = useState ( '' ) ;
150182 const [ models , setModels ] = useState ( [ ] ) ;
151183 const [ filteredModels , setFilteredModels ] = useState ( [ ] ) ;
@@ -504,13 +536,48 @@ export function SettingsDrawer() {
504536 </ button >
505537 </ div >
506538 < div className = "settings-drawer-body" >
507- < div className = "config-panel" >
508- { settingsDefaultSection === 'resilience' ? (
539+ { currentRoute === 'token-bucket' ? (
540+ < div style = { { padding : '20px' , height : '100%' , overflowY : 'auto' } } >
541+ < button
542+ onClick = { ( ) => setCurrentRoute ( 'playground' ) }
543+ style = { {
544+ display : 'inline-flex' ,
545+ alignItems : 'center' ,
546+ gap : '8px' ,
547+ marginBottom : '20px' ,
548+ padding : '8px 12px' ,
549+ background : '#f4f4f5' ,
550+ border : '1px solid #e4e4e7' ,
551+ borderRadius : '6px' ,
552+ fontSize : '13px' ,
553+ color : '#09090b' ,
554+ cursor : 'pointer' ,
555+ transition : 'all 0.2s' ,
556+ fontWeight : 500 ,
557+ } }
558+ onMouseEnter = { ( e ) => {
559+ e . currentTarget . style . background = '#e4e4e7' ;
560+ e . currentTarget . style . borderColor = '#d4d4d8' ;
561+ } }
562+ onMouseLeave = { ( e ) => {
563+ e . currentTarget . style . background = '#f4f4f5' ;
564+ e . currentTarget . style . borderColor = '#e4e4e7' ;
565+ } }
566+ >
567+ < FaArrowLeft />
568+ Back to Settings
569+ </ button >
570+ < TokenBucketDemo onBack = { ( ) => setCurrentRoute ( 'playground' ) } />
571+ </ div >
572+ ) : (
573+ < div className = "config-panel" >
574+ { settingsDefaultSection === 'resilience' ? (
509575 < >
510576 < ResilienceSettingsSection
511577 config = { config }
512578 updateConfig = { updateConfig }
513579 sectionRef = { resilienceSectionRef }
580+ onShowTokenBucket = { ( ) => setCurrentRoute ( 'token-bucket' ) }
514581 />
515582 < section ref = { modelsSectionRef } className = "config-section" >
516583 < div className = "config-section-header" >
@@ -840,10 +907,12 @@ export function SettingsDrawer() {
840907 config = { config }
841908 updateConfig = { updateConfig }
842909 sectionRef = { resilienceSectionRef }
910+ onShowTokenBucket = { ( ) => setCurrentRoute ( 'token-bucket' ) }
843911 />
844912 </ >
845913 ) }
846- </ div >
914+ </ div >
915+ ) }
847916 </ div >
848917 </ aside >
849918 </ >
0 commit comments