1- import { memo , useCallback , useEffect , useMemo , useRef , useState } from "react"
2- import { useEvent } from "react-use"
1+ import { memo , useCallback , useMemo , useState } from "react"
2+ import { useDebounce , useEvent } from "react-use"
33import { Checkbox , Dropdown , Pane , type DropdownOption } from "vscrui"
44import { VSCodeLink , VSCodeRadio , VSCodeRadioGroup , VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
55import { TemperatureControl } from "./TemperatureControl"
@@ -88,29 +88,21 @@ const ApiOptions = ({
8888 return normalizeApiConfiguration ( apiConfiguration )
8989 } , [ apiConfiguration ] )
9090
91- const requestLocalModelsTimeoutRef = useRef < NodeJS . Timeout | null > ( null )
9291 // Pull ollama/lmstudio models
93- const requestLocalModels = useCallback ( ( ) => {
94- if ( selectedProvider === "ollama" ) {
95- vscode . postMessage ( { type : "requestOllamaModels" , text : apiConfiguration ?. ollamaBaseUrl } )
96- } else if ( selectedProvider === "lmstudio" ) {
97- vscode . postMessage ( { type : "requestLmStudioModels" , text : apiConfiguration ?. lmStudioBaseUrl } )
98- } else if ( selectedProvider === "vscode-lm" ) {
99- vscode . postMessage ( { type : "requestVsCodeLmModels" } )
100- }
101- } , [ selectedProvider , apiConfiguration ?. ollamaBaseUrl , apiConfiguration ?. lmStudioBaseUrl ] )
10292 // Debounced model updates, only executed 250ms after the user stops typing
103- useEffect ( ( ) => {
104- if ( requestLocalModelsTimeoutRef . current ) {
105- clearTimeout ( requestLocalModelsTimeoutRef . current )
106- }
107- requestLocalModelsTimeoutRef . current = setTimeout ( requestLocalModels , 250 )
108- return ( ) => {
109- if ( requestLocalModelsTimeoutRef . current ) {
110- clearTimeout ( requestLocalModelsTimeoutRef . current )
93+ useDebounce (
94+ ( ) => {
95+ if ( selectedProvider === "ollama" ) {
96+ vscode . postMessage ( { type : "requestOllamaModels" , text : apiConfiguration ?. ollamaBaseUrl } )
97+ } else if ( selectedProvider === "lmstudio" ) {
98+ vscode . postMessage ( { type : "requestLmStudioModels" , text : apiConfiguration ?. lmStudioBaseUrl } )
99+ } else if ( selectedProvider === "vscode-lm" ) {
100+ vscode . postMessage ( { type : "requestVsCodeLmModels" } )
111101 }
112- }
113- } , [ requestLocalModels ] )
102+ } ,
103+ 250 ,
104+ [ selectedProvider , apiConfiguration ?. ollamaBaseUrl , apiConfiguration ?. lmStudioBaseUrl ] ,
105+ )
114106 const handleMessage = useCallback ( ( event : MessageEvent ) => {
115107 const message : ExtensionMessage = event . data
116108 if ( message . type === "ollamaModels" && Array . isArray ( message . ollamaModels ) ) {
@@ -663,8 +655,7 @@ const ApiOptions = ({
663655 ] } >
664656 < div
665657 style = { {
666- padding : 15 ,
667- backgroundColor : "var(--vscode-editor-background)" ,
658+ padding : 12 ,
668659 } } >
669660 < p
670661 style = { {
@@ -678,24 +669,11 @@ const ApiOptions = ({
678669 </ p >
679670
680671 { /* Capabilities Section */ }
681- < div
682- style = { {
683- marginBottom : 20 ,
684- padding : 12 ,
685- backgroundColor : "var(--vscode-editor-inactiveSelectionBackground)" ,
686- borderRadius : 4 ,
687- } } >
688- < span
689- style = { {
690- fontWeight : 500 ,
691- fontSize : "12px" ,
692- display : "block" ,
693- marginBottom : 12 ,
694- color : "var(--vscode-editor-foreground)" ,
695- } } >
672+ < div >
673+ < h3 className = "font-medium text-sm text-vscode-editor-foreground" >
696674 Model Capabilities
697- </ span >
698- < div style = { { display : "flex" , flexDirection : "column" , gap : 12 } } >
675+ </ h3 >
676+ < div className = "flex flex-col gap-2" >
699677 < div className = "token-config-field" >
700678 < VSCodeTextField
701679 value = {
@@ -792,158 +770,104 @@ const ApiOptions = ({
792770 </ span >
793771 </ div >
794772 </ div >
773+ </ div >
774+ </ div >
795775
796- < div
797- style = { {
798- backgroundColor : "var(--vscode-editor-background)" ,
799- padding : "12px" ,
800- borderRadius : "4px" ,
801- marginTop : "8px" ,
802- border : "1px solid var(--vscode-input-border)" ,
803- transition : "background-color 0.2s ease" ,
804- } } >
805- < span
776+ < div >
777+ < h3 className = "font-medium text-sm text-vscode-editor-foreground" > Model Features</ h3 >
778+ < div className = "flex flex-col gap-2" >
779+ < div className = "feature-toggle" >
780+ < div style = { { display : "flex" , alignItems : "center" , gap : "8px" } } >
781+ < Checkbox
782+ checked = {
783+ apiConfiguration ?. openAiCustomModelInfo ?. supportsImages ??
784+ openAiModelInfoSaneDefaults . supportsImages
785+ }
786+ onChange = { handleInputChange ( "openAiCustomModelInfo" , ( checked ) => {
787+ return {
788+ ...( apiConfiguration ?. openAiCustomModelInfo ||
789+ openAiModelInfoSaneDefaults ) ,
790+ supportsImages : checked ,
791+ }
792+ } ) } >
793+ < span style = { { fontWeight : 500 } } > Image Support</ span >
794+ </ Checkbox >
795+ < i
796+ className = "codicon codicon-info"
797+ title = "Enable if the model can process and understand images in the input. Required for image-based assistance and visual code understanding."
798+ style = { {
799+ fontSize : "12px" ,
800+ color : "var(--vscode-descriptionForeground)" ,
801+ cursor : "help" ,
802+ } }
803+ />
804+ </ div >
805+ < p
806806 style = { {
807807 fontSize : "11px" ,
808- fontWeight : 500 ,
809- color : "var(--vscode-editor-foreground)" ,
810- display : "block" ,
811- marginBottom : "10px" ,
808+ color : "var(--vscode-descriptionForeground)" ,
809+ marginLeft : "24px" ,
810+ marginTop : "4px" ,
811+ lineHeight : "1.4" ,
812+ marginBottom : 0 ,
812813 } } >
813- Model Features
814- </ span >
815-
816- < div style = { { display : "flex" , flexDirection : "column" , gap : "12px" } } >
817- < div className = "feature-toggle" >
818- < div style = { { display : "flex" , alignItems : "center" , gap : "8px" } } >
819- < Checkbox
820- checked = {
821- apiConfiguration ?. openAiCustomModelInfo ?. supportsImages ??
822- openAiModelInfoSaneDefaults . supportsImages
823- }
824- onChange = { handleInputChange (
825- "openAiCustomModelInfo" ,
826- ( checked ) => {
827- return {
828- ...( apiConfiguration ?. openAiCustomModelInfo ||
829- openAiModelInfoSaneDefaults ) ,
830- supportsImages : checked ,
831- }
832- } ,
833- ) } >
834- < span style = { { fontWeight : 500 } } > Image Support</ span >
835- </ Checkbox >
836- < i
837- className = "codicon codicon-info"
838- title = "Enable if the model can process and understand images in the input. Required for image-based assistance and visual code understanding."
839- style = { {
840- fontSize : "12px" ,
841- color : "var(--vscode-descriptionForeground)" ,
842- cursor : "help" ,
843- } }
844- />
845- </ div >
846- < p
847- style = { {
848- fontSize : "11px" ,
849- color : "var(--vscode-descriptionForeground)" ,
850- marginLeft : "24px" ,
851- marginTop : "4px" ,
852- lineHeight : "1.4" ,
853- } } >
854- Allows the model to analyze and understand images, essential for
855- visual code assistance
856- </ p >
857- </ div >
814+ Allows the model to analyze and understand images, essential for visual code
815+ assistance
816+ </ p >
817+ </ div >
858818
859- < div
860- className = "feature-toggle"
819+ < div
820+ className = "feature-toggle"
821+ style = { {
822+ borderTop : "1px solid var(--vscode-input-border)" ,
823+ } } >
824+ < div style = { { display : "flex" , alignItems : "center" , gap : "8px" } } >
825+ < Checkbox
826+ checked = {
827+ apiConfiguration ?. openAiCustomModelInfo ?. supportsComputerUse ??
828+ false
829+ }
830+ onChange = { handleInputChange ( "openAiCustomModelInfo" , ( checked ) => {
831+ return {
832+ ...( apiConfiguration ?. openAiCustomModelInfo ||
833+ openAiModelInfoSaneDefaults ) ,
834+ supportsComputerUse : checked ,
835+ }
836+ } ) } >
837+ < span style = { { fontWeight : 500 } } > Computer Use</ span >
838+ </ Checkbox >
839+ < i
840+ className = "codicon codicon-info"
841+ title = "Enable if the model can interact with your computer through commands and file operations. Required for automated tasks and file modifications."
861842 style = { {
862- borderTop : "1px solid var(--vscode-input-border)" ,
863- paddingTop : "12px" ,
864- } } >
865- < div style = { { display : "flex" , alignItems : "center" , gap : "8px" } } >
866- < Checkbox
867- checked = {
868- apiConfiguration ?. openAiCustomModelInfo
869- ?. supportsComputerUse ?? false
870- }
871- onChange = { handleInputChange (
872- "openAiCustomModelInfo" ,
873- ( checked ) => {
874- return {
875- ...( apiConfiguration ?. openAiCustomModelInfo ||
876- openAiModelInfoSaneDefaults ) ,
877- supportsComputerUse : checked ,
878- }
879- } ,
880- ) } >
881- < span style = { { fontWeight : 500 } } > Computer Use</ span >
882- </ Checkbox >
883- < i
884- className = "codicon codicon-info"
885- title = "Enable if the model can interact with your computer through commands and file operations. Required for automated tasks and file modifications."
886- style = { {
887- fontSize : "12px" ,
888- color : "var(--vscode-descriptionForeground)" ,
889- cursor : "help" ,
890- } }
891- />
892- </ div >
893- < p
894- style = { {
895- fontSize : "11px" ,
896- color : "var(--vscode-descriptionForeground)" ,
897- marginLeft : "24px" ,
898- marginTop : "4px" ,
899- lineHeight : "1.4" ,
900- } } >
901- This model feature is for computer use like sonnet 3.5 support
902- </ p >
903- </ div >
843+ fontSize : "12px" ,
844+ color : "var(--vscode-descriptionForeground)" ,
845+ cursor : "help" ,
846+ } }
847+ />
904848 </ div >
849+ < p
850+ style = { {
851+ fontSize : "11px" ,
852+ color : "var(--vscode-descriptionForeground)" ,
853+ marginLeft : "24px" ,
854+ marginTop : "4px" ,
855+ lineHeight : "1.4" ,
856+ marginBottom : 0 ,
857+ } } >
858+ This model feature is for computer use like sonnet 3.5 support
859+ </ p >
905860 </ div >
906861 </ div >
907862 </ div >
908863
909864 { /* Pricing Section */ }
910- < div
911- style = { {
912- backgroundColor : "var(--vscode-editor-inactiveSelectionBackground)" ,
913- padding : "12px" ,
914- borderRadius : "4px" ,
915- marginTop : "15px" ,
916- } } >
917- < div style = { { marginBottom : "12px" } } >
918- < span
919- style = { {
920- fontWeight : 500 ,
921- fontSize : "12px" ,
922- color : "var(--vscode-editor-foreground)" ,
923- display : "block" ,
924- marginBottom : "4px" ,
925- } } >
926- Model Pricing
927- </ span >
928- < span
929- style = { {
930- fontSize : "11px" ,
931- color : "var(--vscode-descriptionForeground)" ,
932- display : "block" ,
933- } } >
934- Configure token-based pricing in USD per million tokens
935- </ span >
936- </ div >
937-
938- < div
939- style = { {
940- display : "grid" ,
941- gridTemplateColumns : "1fr 1fr" ,
942- gap : "12px" ,
943- backgroundColor : "var(--vscode-editor-background)" ,
944- padding : "12px" ,
945- borderRadius : "4px" ,
946- } } >
865+ < div >
866+ < h3 className = "font-medium text-sm text-vscode-editor-foreground mb-0" >
867+ Model Pricing
868+ </ h3 >
869+ < div className = "text-xs" > Configure token-based pricing in USD per million tokens</ div >
870+ < div className = "flex flex-row gap-2 mt-1.5" >
947871 < div className = "price-input" >
948872 < VSCodeTextField
949873 value = {
0 commit comments