@@ -173,19 +173,19 @@ export class ModelTabs {
173173 <input data-field="color" type="text" value="${ cfg . color } "/>
174174 </div>
175175 <div>
176- <label>Model ID</label>
176+ <label data-el="modelLabel" >Model ID</label>
177177 <input data-field="model" type="text" value="${ cfg . model } " placeholder="gpt-4o-mini"/>
178178 </div>
179179 <div class="full">
180180 <label>Base URL</label>
181181 <input data-field="baseURL" type="text" value="${ cfg . baseURL } " placeholder="https://api.example.com/v1"/>
182182 </div>
183183 <div>
184- <label>API Key</label>
184+ <label data-el="apiKeyLabel" >API Key</label>
185185 <input data-field="apiKey" type="password" value="${ cfg . apiKey || '' } " placeholder="sk-..."/>
186186 </div>
187187 <div>
188- <label>API Version</label>
188+ <label data-el="apiVersionLabel" >API Version</label>
189189 <input data-field="apiVersion" type="text" value="${ cfg . apiVersion || '' } " placeholder="2024-08-01-preview"/>
190190 </div>
191191 </div>
@@ -195,7 +195,7 @@ export class ModelTabs {
195195 <div class="model-section">
196196 <div class="model-grid wide">
197197 <div>
198- <label>Max tokens</label>
198+ <label data-el="maxTokensLabel" >Max tokens</label>
199199 <input data-field="maxTokens" type="number" value="${ cfg . maxTokens ?? 2048 } "/>
200200 </div>
201201 <div>
@@ -211,6 +211,7 @@ export class ModelTabs {
211211 <div class="btn-group" role="group" aria-label="Endpoint type">
212212 <button type="button" class="btn endpoint-btn ${ cfg . endpointType === 'chat' ? 'active' :'' } " data-endpoint="chat" aria-pressed="${ cfg . endpointType === 'chat' } ">Chat</button>
213213 <button type="button" class="btn endpoint-btn ${ cfg . endpointType === 'responses' ? 'active' :'' } " data-endpoint="responses" aria-pressed="${ cfg . endpointType === 'responses' } ">Responses</button>
214+ <button type="button" class="btn endpoint-btn ${ cfg . endpointType === 'groundingdino' ? 'active' :'' } " data-endpoint="groundingdino" aria-pressed="${ cfg . endpointType === 'groundingdino' } ">GroundingDINO</button>
214215 </div>
215216 <div class="inline-field endpoint-field" data-endpoint="chat" style="display:${ cfg . endpointType === 'chat' ? 'flex' :'none' } ">
216217 <label>Temperature</label>
@@ -225,6 +226,12 @@ export class ModelTabs {
225226 <option value="high" ${ cfg . reasoningEffort === 'high' ?'selected' :'' } >high</option>
226227 </select>
227228 </div>
229+ <div class="inline-field endpoint-field" data-endpoint="groundingdino" style="display:${ cfg . endpointType === 'groundingdino' ? 'flex' :'none' } ; gap:8px;">
230+ <label>Box thr</label>
231+ <input data-field="dinoBoxThreshold" type="number" step="0.01" min="0" max="1" value="${ cfg . dinoBoxThreshold ?? 0.35 } " style="width:90px"/>
232+ <label>Text thr</label>
233+ <input data-field="dinoTextThreshold" type="number" step="0.01" min="0" max="1" value="${ cfg . dinoTextThreshold ?? 0.25 } " style="width:90px"/>
234+ </div>
228235 </div>
229236 </div>
230237 </div>
@@ -246,12 +253,18 @@ export class ModelTabs {
246253 let currentEndpointType = cfg . endpointType || 'chat' ;
247254 const baseURL = card . querySelector ( 'input[data-field="baseURL"]' ) ;
248255 const model = card . querySelector ( 'input[data-field="model"]' ) ;
256+ const modelLabelEl = card . querySelector ( '[data-el="modelLabel"]' ) ;
249257 const apiVersion = card . querySelector ( 'input[data-field="apiVersion"]' ) ;
258+ const apiVersionLabelEl = card . querySelector ( '[data-el="apiVersionLabel"]' ) ;
250259 const reasoningEffort = card . querySelector ( 'select[data-field="reasoningEffort"]' ) ;
251260 const key = card . querySelector ( 'input[data-field="apiKey"]' ) ;
261+ const apiKeyLabelEl = card . querySelector ( '[data-el="apiKeyLabel"]' ) ;
252262 const temp = card . querySelector ( 'input[data-field="temperature"]' ) ;
253263 const maxTok = card . querySelector ( 'input[data-field="maxTokens"]' ) ;
264+ const maxTokensLabelEl = card . querySelector ( '[data-el="maxTokensLabel"]' ) ;
254265 const timeout = card . querySelector ( 'input[data-field="timeoutMs"]' ) ;
266+ const dinoBoxThreshold = card . querySelector ( 'input[data-field="dinoBoxThreshold"]' ) ;
267+ const dinoTextThreshold = card . querySelector ( 'input[data-field="dinoTextThreshold"]' ) ;
255268
256269 const headersTa = card . querySelector ( 'textarea[data-field="extraHeaders"]' ) ;
257270 const logEl = card . querySelector ( '[data-log]' ) ;
@@ -311,6 +324,38 @@ export class ModelTabs {
311324 color . addEventListener ( 'focus' , showColorPopover ) ;
312325 color . addEventListener ( 'blur' , ( ) => { /* keep open for interactions; closed by outside click */ } ) ;
313326
327+ const updateEndpointNonApplicableUI = ( ) => {
328+ const isDino = currentEndpointType === 'groundingdino' ;
329+ if ( model ) {
330+ model . disabled = isDino ;
331+ model . placeholder = isDino ? '(not used for DINO)' : 'gpt-4o-mini' ;
332+ if ( isDino ) {
333+ const v = String ( model . value || '' ) ;
334+ if ( ! v || / ( g p t | c l a u d e | q w e n | l l a v a | m i n i | v i s i o n ) / i. test ( v ) ) {
335+ model . value = 'GroundingDINO' ;
336+ }
337+ }
338+ }
339+ if ( modelLabelEl ) {
340+ modelLabelEl . textContent = isDino ? 'Display name (UI only)' : 'Model ID' ;
341+ }
342+ if ( apiVersion ) apiVersion . disabled = isDino ;
343+ if ( apiVersionLabelEl ) apiVersionLabelEl . textContent = isDino ? 'API Version (n/a)' : 'API Version' ;
344+ if ( maxTok ) maxTok . disabled = isDino ;
345+ if ( maxTokensLabelEl ) maxTokensLabelEl . textContent = isDino ? 'Max tokens (n/a)' : 'Max tokens' ;
346+ if ( key ) {
347+ key . disabled = isDino ;
348+ key . placeholder = isDino ? '(not used for DINO)' : 'sk-...' ;
349+ }
350+ if ( apiKeyLabelEl ) apiKeyLabelEl . textContent = isDino ? 'API Key (n/a)' : 'API Key' ;
351+ if ( headersTa ) {
352+ headersTa . disabled = isDino ;
353+ headersTa . placeholder = isDino ? '(not used for DINO)' : '{"X-Org":"..."}' ;
354+ }
355+ } ;
356+ // Initialize once
357+ updateEndpointNonApplicableUI ( ) ;
358+
314359 const persist = ( ) => {
315360 let extra = undefined ;
316361 try {
@@ -333,6 +378,8 @@ export class ModelTabs {
333378 maxTokens : Number ( maxTok . value ) ,
334379 timeoutMs : Number ( timeout . value ) ,
335380 extraHeaders : extra ,
381+ dinoBoxThreshold : dinoBoxThreshold ? Number ( dinoBoxThreshold . value ) : undefined ,
382+ dinoTextThreshold : dinoTextThreshold ? Number ( dinoTextThreshold . value ) : undefined ,
336383 } ;
337384 this . storage . updateModel ( updated ) ;
338385
@@ -406,6 +453,8 @@ export class ModelTabs {
406453 endpointPanels . forEach ( p => {
407454 p . style . display = ( p . dataset . endpoint === currentEndpointType ) ? 'flex' : 'none' ;
408455 } ) ;
456+ // Update disabled/labels for non-applicable fields
457+ updateEndpointNonApplicableUI ( ) ;
409458 persist ( ) ;
410459 } ) ;
411460 } ) ;
@@ -418,6 +467,8 @@ export class ModelTabs {
418467 timeout . addEventListener ( 'input' , persist ) ;
419468 headersTa . addEventListener ( 'input' , persist ) ;
420469 reasoningEffort . addEventListener ( 'change' , persist ) ;
470+ if ( dinoBoxThreshold ) dinoBoxThreshold . addEventListener ( 'input' , persist ) ;
471+ if ( dinoTextThreshold ) dinoTextThreshold . addEventListener ( 'input' , persist ) ;
421472
422473 return card ;
423474 }
0 commit comments