11import React , { useEffect , useState } from "react" ;
22import System from "@/models/system" ;
3- import PreLoader from "@/components/Preloader" ;
43import { LMSTUDIO_COMMON_URLS } from "@/utils/constants" ;
5- import { CaretDown , CaretUp , Info } from "@phosphor-icons/react" ;
4+ import { CaretDown , CaretUp , Info , CircleNotch } from "@phosphor-icons/react" ;
65import { Tooltip } from "react-tooltip" ;
76import useProviderEndpointAutoDiscovery from "@/hooks/useProviderEndpointAutoDiscovery" ;
87
@@ -11,6 +10,8 @@ export default function LMStudioEmbeddingOptions({ settings }) {
1110 autoDetecting : loading ,
1211 basePath,
1312 basePathValue,
13+ authToken,
14+ authTokenValue,
1415 showAdvancedControls,
1516 setShowAdvancedControls,
1617 handleAutoDetectClick,
@@ -31,20 +32,24 @@ export default function LMStudioEmbeddingOptions({ settings }) {
3132 return (
3233 < div className = "w-full flex flex-col gap-y-7" >
3334 < div className = "w-full flex items-start gap-[36px] mt-1.5" >
34- < LMStudioModelSelection settings = { settings } basePath = { basePath . value } />
35+ < LMStudioModelSelection
36+ settings = { settings }
37+ basePath = { basePath . value }
38+ apiKey = { authTokenValue . value }
39+ />
3540 < div className = "flex flex-col w-60" >
3641 < div
3742 data-tooltip-place = "top"
3843 data-tooltip-id = "max-embedding-chunk-length-tooltip"
3944 className = "flex gap-x-1 items-center mb-3"
4045 >
46+ < label className = "text-white text-sm font-semibold block" >
47+ Max embedding chunk length
48+ </ label >
4149 < Info
4250 size = { 16 }
4351 className = "text-theme-text-secondary cursor-pointer"
4452 />
45- < label className = "text-white text-sm font-semibold block" >
46- Max embedding chunk length
47- </ label >
4853 < Tooltip id = "max-embedding-chunk-length-tooltip" >
4954 Maximum length of text chunks, in characters, for embedding.
5055 </ Tooltip >
@@ -61,9 +66,6 @@ export default function LMStudioEmbeddingOptions({ settings }) {
6166 required = { true }
6267 autoComplete = "off"
6368 />
64- < p className = "text-xs leading-[18px] font-base text-white text-opacity-60 mt-2" >
65- Maximum length of text chunks, in characters, for embedding.
66- </ p >
6769 </ div >
6870 </ div >
6971 < div className = "flex justify-start mt-4" >
@@ -85,19 +87,41 @@ export default function LMStudioEmbeddingOptions({ settings }) {
8587
8688 < div hidden = { ! showAdvancedControls } >
8789 < div className = "w-full flex items-start gap-4" >
88- < div className = "flex flex-col w-60 " >
90+ < div className = "flex flex-col w-[300px] " >
8991 < div className = "flex justify-between items-center mb-2" >
90- < label className = "text-white text-sm font-semibold" >
91- LM Studio Base URL
92- </ label >
92+ < div className = "flex items-center gap-1" >
93+ < label className = "text-white text-sm font-semibold" >
94+ LM Studio Base URL
95+ </ label >
96+ < Info
97+ size = { 18 }
98+ className = "text-theme-text-secondary cursor-pointer"
99+ data-tooltip-id = "lmstudio-base-url"
100+ data-tooltip-content = "Enter the URL where LM Studio is running."
101+ />
102+ < Tooltip
103+ id = "lmstudio-base-url"
104+ place = "top"
105+ delayShow = { 300 }
106+ className = "tooltip !text-xs !opacity-100"
107+ style = { {
108+ maxWidth : "250px" ,
109+ whiteSpace : "normal" ,
110+ wordWrap : "break-word" ,
111+ } }
112+ />
113+ </ div >
93114 { loading ? (
94- < PreLoader size = "6" />
115+ < CircleNotch
116+ size = { 16 }
117+ className = "text-theme-text-secondary animate-spin"
118+ />
95119 ) : (
96120 < >
97121 { ! basePathValue . value && (
98122 < button
99123 onClick = { handleAutoDetectClick }
100- className = "bg-primary-button text-xs font-medium px-2 py-1 rounded-lg hover:bg-secondary hover:text-white shadow-[0_4px_14px_rgba(0,0,0,0.25)]"
124+ className = "border-none bg-primary-button text-xs font-medium px-2 py-1 rounded-lg hover:bg-secondary hover:text-white shadow-[0_4px_14px_rgba(0,0,0,0.25)]"
101125 >
102126 Auto-Detect
103127 </ button >
@@ -117,17 +141,59 @@ export default function LMStudioEmbeddingOptions({ settings }) {
117141 onChange = { basePath . onChange }
118142 onBlur = { basePath . onBlur }
119143 />
120- < p className = "text-xs leading-[18px] font-base text-white text-opacity-60 mt-2" >
121- Enter the URL where LM Studio is running.
122- </ p >
144+ </ div >
145+ < div className = "flex flex-col w-60" >
146+ < div className = "flex items-center mb-2 gap-x-1" >
147+ < label className = "text-white text-sm font-semibold" >
148+ Authentication Token
149+ </ label >
150+ < Info
151+ size = { 18 }
152+ className = "text-theme-text-secondary cursor-pointer"
153+ data-tooltip-id = "lmstudio-authentication-token"
154+ />
155+ < Tooltip
156+ id = "lmstudio-authentication-token"
157+ place = "top"
158+ delayShow = { 300 }
159+ delayHide = { 400 }
160+ clickable = { true }
161+ className = "tooltip !text-xs !opacity-100"
162+ style = { {
163+ maxWidth : "250px" ,
164+ whiteSpace : "normal" ,
165+ wordWrap : "break-word" ,
166+ } }
167+ >
168+ < p className = "text-xs leading-[18px] font-base" >
169+ Enter a < code > Bearer</ code > Auth Token for interacting with
170+ your LM Studio server.
171+ < br /> < br />
172+ Useful if running LM Studio behind an authentication or proxy.
173+ </ p >
174+ </ Tooltip >
175+ </ div >
176+ < input
177+ type = "password"
178+ name = "LMStudioAuthToken"
179+ className = "border-none bg-theme-settings-input-bg text-white placeholder:text-theme-settings-input-placeholder text-sm rounded-lg outline-none block w-full p-2.5 focus:outline-primary-button active:outline-primary-button"
180+ placeholder = "LM Studio Auth Token"
181+ defaultValue = { settings ?. LMStudioAuthToken ? "*" . repeat ( 20 ) : "" }
182+ value = { authTokenValue . value }
183+ onChange = { authToken . onChange }
184+ onBlur = { authToken . onBlur }
185+ required = { false }
186+ autoComplete = "off"
187+ spellCheck = { false }
188+ />
123189 </ div >
124190 </ div >
125191 </ div >
126192 </ div >
127193 ) ;
128194}
129195
130- function LMStudioModelSelection ( { settings, basePath = null } ) {
196+ function LMStudioModelSelection ( { settings, basePath = null , apiKey = null } ) {
131197 const [ customModels , setCustomModels ] = useState ( [ ] ) ;
132198 const [ loading , setLoading ] = useState ( true ) ;
133199
@@ -142,7 +208,7 @@ function LMStudioModelSelection({ settings, basePath = null }) {
142208 try {
143209 const { models } = await System . customModels (
144210 "lmstudio" ,
145- null ,
211+ apiKey ,
146212 basePath
147213 ) ;
148214 setCustomModels ( models || [ ] ) ;
@@ -153,7 +219,7 @@ function LMStudioModelSelection({ settings, basePath = null }) {
153219 setLoading ( false ) ;
154220 }
155221 findCustomModels ( ) ;
156- } , [ basePath ] ) ;
222+ } , [ basePath , apiKey ] ) ;
157223
158224 if ( loading || customModels . length == 0 ) {
159225 return (
0 commit comments