Skip to content

Commit 68ea334

Browse files
committed
fix: normalization sending empty content to Genie API and dark mode input styling
Send original user query to Genie API instead of normalized form (which can be empty for non-analytical questions). Normalized text is now only used for cache key generation. Also add empty-canonical fallback in the normalizer. Replace browser confirm() on gateway delete with custom Modal matching the cache-clear dialog style. Add bg-dbx-bg to all input fields missing it so they render correctly in dark mode. Co-authored-by: Isaac
1 parent 5ea18d3 commit 68ea334

File tree

6 files changed

+51
-13
lines changed

6 files changed

+51
-13
lines changed

backend/app/api/genie_clone_routes.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,17 +222,20 @@ async def _process_genie_background(
222222
if msg_id in _synthetic_messages:
223223
_synthetic_messages[msg_id].setdefault("_proxy", {})["stage"] = "processing_genie"
224224

225+
# Genie API always receives the original user question;
226+
# normalized form is only used for cache key / embedding.
227+
genie_query = original_query_text or query_text
225228
try:
226229
if conversation_id and not conversation_id.startswith(CONV_PREFIX):
227230
try:
228-
result = await genie_service.send_message(space_id, conversation_id, query_text, rs)
231+
result = await genie_service.send_message(space_id, conversation_id, genie_query, rs)
229232
except GenieConfigError:
230233
raise
231234
except Exception:
232235
logger.warning("send_message failed, falling back to start_conversation")
233-
result = await genie_service.start_conversation(space_id, query_text, rs)
236+
result = await genie_service.start_conversation(space_id, genie_query, rs)
234237
else:
235-
result = await genie_service.start_conversation(space_id, query_text, rs)
238+
result = await genie_service.start_conversation(space_id, genie_query, rs)
236239

237240

238241
if result.get("status") == "COMPLETED":

backend/app/services/question_normalizer.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ async def normalize_question(query_text: str, runtime_settings=None, space_conte
122122

123123
canonical = " | ".join(parts)
124124

125+
if not canonical:
126+
logger.warning("Question normalizer: canonical is empty — falling back to lowercased input")
127+
return string_normalized
128+
125129
logger.info(
126130
"Question normalizer: original=%r... canonical=%r...",
127131
query_text[:60],

frontend/src/components/gateways/GatewayCreateModal.jsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ export default function GatewayCreateModal({ open, onClose, onCreated }) {
199199
placeholder="Enter gateway name"
200200
value={name}
201201
onChange={(e) => setName(e.target.value)}
202-
className="w-full h-8 px-3 border border-dbx-border-input rounded text-[13px] text-dbx-text placeholder:text-dbx-text-secondary focus:outline-none focus:border-dbx-blue"
202+
className="w-full h-8 px-3 border border-dbx-border-input rounded text-[13px] text-dbx-text bg-dbx-bg placeholder:text-dbx-text-secondary focus:outline-none focus:border-dbx-blue"
203203
/>
204204
</div>
205205

@@ -216,7 +216,7 @@ export default function GatewayCreateModal({ open, onClose, onCreated }) {
216216
placeholder="Enter Genie Space ID"
217217
value={manualSpaceId}
218218
onChange={(e) => setManualSpaceId(e.target.value)}
219-
className="w-full h-8 px-3 border border-dbx-border-input rounded text-[13px] text-dbx-text placeholder:text-dbx-text-secondary focus:outline-none focus:border-dbx-blue font-mono"
219+
className="w-full h-8 px-3 border border-dbx-border-input rounded text-[13px] text-dbx-text bg-dbx-bg placeholder:text-dbx-text-secondary focus:outline-none focus:border-dbx-blue font-mono"
220220
/>
221221
<button
222222
onClick={() => { setShowManualSpace(false); setManualSpaceId('') }}
@@ -235,7 +235,7 @@ export default function GatewayCreateModal({ open, onClose, onCreated }) {
235235
placeholder="Search by name"
236236
value={spaceSearch}
237237
onChange={(e) => setSpaceSearch(e.target.value)}
238-
className="w-full h-8 pl-8 pr-3 border border-dbx-border-input rounded text-[13px] text-dbx-text placeholder:text-dbx-text-secondary focus:outline-none focus:border-dbx-blue"
238+
className="w-full h-8 pl-8 pr-3 border border-dbx-border-input rounded text-[13px] text-dbx-text bg-dbx-bg placeholder:text-dbx-text-secondary focus:outline-none focus:border-dbx-blue"
239239
/>
240240
</div>
241241
)}

frontend/src/components/gateways/GatewayDetailPage.jsx

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { useState, useEffect } from 'react'
22
import { useParams, useNavigate, Link } from 'react-router-dom'
3-
import { Trash2, Play, Copy, Loader2 } from 'lucide-react'
3+
import { Trash2, Play, Copy, Loader2, AlertTriangle } from 'lucide-react'
44
import { api } from '../../services/api'
5+
import Modal from '../shared/Modal'
56
import GatewayOverviewTab from './GatewayOverviewTab'
67
import GatewayMetricsTab from './GatewayMetricsTab'
78
import GatewayCacheTab from './GatewayCacheTab'
@@ -24,6 +25,7 @@ export default function GatewayDetailPage() {
2425
const [error, setError] = useState(null)
2526
const [activeTab, setActiveTab] = useState('overview')
2627
const [deleting, setDeleting] = useState(false)
28+
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false)
2729

2830
const fetchGateway = async () => {
2931
try {
@@ -43,10 +45,10 @@ export default function GatewayDetailPage() {
4345
}, [id])
4446

4547
const handleDelete = async () => {
46-
if (!confirm(`Delete gateway "${gateway?.name || id}"? This action cannot be undone.`)) return
4748
try {
4849
setDeleting(true)
4950
await api.deleteGateway(id)
51+
setShowDeleteConfirm(false)
5052
navigate('/')
5153
} catch (err) {
5254
alert('Failed to delete gateway: ' + (err.response?.data?.detail || err.message))
@@ -126,7 +128,7 @@ export default function GatewayDetailPage() {
126128
Test in Playground
127129
</button>
128130
<button
129-
onClick={handleDelete}
131+
onClick={() => setShowDeleteConfirm(true)}
130132
disabled={deleting}
131133
className="inline-flex items-center gap-1.5 h-8 px-3 text-[13px] font-medium text-dbx-text border border-dbx-border-input rounded hover:bg-dbx-neutral-hover transition-colors disabled:opacity-50"
132134
>
@@ -202,6 +204,35 @@ export default function GatewayDetailPage() {
202204
/>
203205
</div>
204206
</div>
207+
{/* Delete confirmation modal */}
208+
<Modal isOpen={showDeleteConfirm} onClose={() => setShowDeleteConfirm(false)} title="Delete Gateway" maxWidth="max-w-md">
209+
<div className="flex flex-col items-center text-center pt-2">
210+
<div className="w-12 h-12 rounded-full bg-dbx-status-red-bg flex items-center justify-center mb-4">
211+
<AlertTriangle size={24} className="text-dbx-text-danger" />
212+
</div>
213+
<p className="text-[14px] text-dbx-text mb-1">
214+
Are you sure you want to delete this gateway?
215+
</p>
216+
<p className="text-[13px] text-dbx-text-secondary mb-6">
217+
<span className="font-medium text-dbx-text">{gateway?.name}</span> will be permanently deleted. This action cannot be undone.
218+
</p>
219+
<div className="flex gap-3 w-full">
220+
<button
221+
onClick={() => setShowDeleteConfirm(false)}
222+
className="flex-1 h-8 text-[13px] font-medium text-dbx-text border border-dbx-border-input rounded hover:bg-dbx-neutral-hover transition-colors"
223+
>
224+
Cancel
225+
</button>
226+
<button
227+
onClick={handleDelete}
228+
disabled={deleting}
229+
className="flex-1 h-8 text-[13px] font-medium text-white bg-[#D32F2F] rounded hover:bg-[#B71C1C] transition-colors disabled:opacity-50"
230+
>
231+
{deleting ? 'Deleting...' : 'Delete'}
232+
</button>
233+
</div>
234+
</div>
235+
</Modal>
205236
</div>
206237
)
207238
}

frontend/src/components/gateways/GatewaySettingsTab.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ export default function GatewaySettingsTab({ gateway, onUpdate }) {
151151
}
152152
}
153153

154-
const inputClass = 'h-8 w-full border border-dbx-border-input rounded px-3 text-[13px] text-dbx-text outline-none focus:border-dbx-blue transition-colors'
154+
const inputClass = 'h-8 w-full border border-dbx-border-input rounded px-3 text-[13px] text-dbx-text bg-dbx-bg outline-none focus:border-dbx-blue transition-colors'
155155

156156
return (
157157
<div className="max-w-xl space-y-6">
@@ -172,7 +172,7 @@ export default function GatewaySettingsTab({ gateway, onUpdate }) {
172172
<div className="flex gap-2">
173173
<input type="number" min="0" value={form.cache_ttl_value}
174174
onChange={(e) => handleChange('cache_ttl_value', e.target.value)}
175-
className="h-8 flex-1 border border-dbx-border-input rounded px-3 text-[13px] text-dbx-text outline-none focus:border-dbx-blue transition-colors" />
175+
className="h-8 flex-1 border border-dbx-border-input rounded px-3 text-[13px] text-dbx-text bg-dbx-bg outline-none focus:border-dbx-blue transition-colors" />
176176
<select value={form.cache_ttl_unit} onChange={(e) => handleChange('cache_ttl_unit', e.target.value)}
177177
className="h-8 border border-dbx-border-input rounded px-3 text-[13px] text-dbx-text outline-none focus:border-dbx-blue transition-colors bg-dbx-bg">
178178
<option value="minutes">Minutes</option>

frontend/src/components/settings/SettingsPage.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ function EditableText({ value, onChange, placeholder, masked }) {
5656
<input ref={inputRef} type={masked ? 'password' : 'text'} value={draft}
5757
onChange={(e) => setDraft(e.target.value)} onKeyDown={handleKey}
5858
placeholder={placeholder}
59-
className="h-8 border border-dbx-blue rounded px-3 text-[13px] text-dbx-text outline-none"
59+
className="h-8 border border-dbx-blue rounded px-3 text-[13px] text-dbx-text bg-dbx-bg outline-none"
6060
style={{ width: '220px' }} />
6161
<button onClick={save}
6262
className="h-8 px-3 text-[13px] text-white bg-dbx-blue rounded hover:bg-dbx-blue-dark transition-colors">Save</button>
@@ -264,7 +264,7 @@ export default function SettingsPage() {
264264
sectionRefs.current[id]?.scrollIntoView({ behavior: 'smooth', block: 'start' })
265265
}
266266

267-
const inputClass = 'h-8 border border-dbx-border-input rounded px-3 text-[13px] text-dbx-text outline-none focus:border-dbx-blue transition-colors'
267+
const inputClass = 'h-8 border border-dbx-border-input rounded px-3 text-[13px] text-dbx-text bg-dbx-bg outline-none focus:border-dbx-blue transition-colors'
268268

269269
if (loading) {
270270
return (

0 commit comments

Comments
 (0)