spine-framework-portal 0.2.25 → 0.2.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -79,7 +79,11 @@ async function handleNewTicket(
|
|
|
79
79
|
const agentMsg = await runAgent(threadRecord.id, message, ctx)
|
|
80
80
|
|
|
81
81
|
const confidence = agentMsg?.data?.confidence ?? 0
|
|
82
|
-
|
|
82
|
+
// Derive escalated from confidence vs threshold — don't rely solely on the
|
|
83
|
+
// message data field, which may not be set if running an older framework build.
|
|
84
|
+
const { data: pcRow } = await adminDb.from('prompt_configs').select('confidence_threshold').eq('id', promptConfigId).single()
|
|
85
|
+
const threshold = pcRow?.confidence_threshold ?? 0.75
|
|
86
|
+
const escalated = agentMsg?.data?.escalated ?? (confidence < threshold)
|
|
83
87
|
|
|
84
88
|
// 4. Backfill suggested title if agent produced one, and stamp confidence/status
|
|
85
89
|
const suggestedTitle = agentMsg?.data?.suggested_title || message.slice(0, 80)
|
|
@@ -122,7 +126,9 @@ async function handleReply(
|
|
|
122
126
|
const agentMsg = await runAgent(thread_id, message, ctx)
|
|
123
127
|
|
|
124
128
|
const confidence = agentMsg?.data?.confidence ?? 0
|
|
125
|
-
const
|
|
129
|
+
const { data: pcRow2 } = await adminDb.from('prompt_configs').select('confidence_threshold').eq('id', _ids.promptConfigId).single()
|
|
130
|
+
const threshold2 = pcRow2?.confidence_threshold ?? 0.75
|
|
131
|
+
const escalated = agentMsg?.data?.escalated ?? (confidence < threshold2)
|
|
126
132
|
|
|
127
133
|
if (escalated) {
|
|
128
134
|
const { data: currentTicket } = await adminDb
|
package/hooks/useTickets.ts
CHANGED
|
@@ -177,18 +177,8 @@ export function useSubmitFeedback() {
|
|
|
177
177
|
setLoading(true)
|
|
178
178
|
setError(null)
|
|
179
179
|
try {
|
|
180
|
-
//
|
|
181
|
-
|
|
182
|
-
method: 'PATCH',
|
|
183
|
-
body: JSON.stringify({
|
|
184
|
-
data: {
|
|
185
|
-
feedback,
|
|
186
|
-
feedback_at: new Date().toISOString()
|
|
187
|
-
}
|
|
188
|
-
}),
|
|
189
|
-
})
|
|
190
|
-
|
|
191
|
-
// Best-effort: record feedback in the core ai-interactions log
|
|
180
|
+
// Route through ai-interactions which safely merges data fields and
|
|
181
|
+
// handles not_helpful → human_assigned escalation server-side.
|
|
192
182
|
await fetchJSON('/.netlify/functions/ai-interactions', {
|
|
193
183
|
method: 'POST',
|
|
194
184
|
body: JSON.stringify({
|
|
@@ -197,21 +187,7 @@ export function useSubmitFeedback() {
|
|
|
197
187
|
ticket_id: ticketId,
|
|
198
188
|
feedback: feedback === 'up' ? 'helpful' : 'not_helpful',
|
|
199
189
|
}),
|
|
200
|
-
})
|
|
201
|
-
|
|
202
|
-
// If thumbs down, escalate to human
|
|
203
|
-
if (feedback === 'down') {
|
|
204
|
-
await fetchJSON(`/.netlify/functions/admin-data?entity=items&id=${ticketId}`, {
|
|
205
|
-
method: 'PATCH',
|
|
206
|
-
body: JSON.stringify({
|
|
207
|
-
data: {
|
|
208
|
-
status: 'human_assigned',
|
|
209
|
-
aim_escalation_reason: 'thumbs_down'
|
|
210
|
-
}
|
|
211
|
-
}),
|
|
212
|
-
})
|
|
213
|
-
}
|
|
214
|
-
|
|
190
|
+
})
|
|
215
191
|
return { success: true }
|
|
216
192
|
} catch (e: any) {
|
|
217
193
|
setError(e.message)
|
package/package.json
CHANGED
package/pages/TicketsPage.tsx
CHANGED
|
@@ -144,8 +144,8 @@ function TicketThread({ ticketId, ticketStatus, onStatusChange }: TicketThreadPr
|
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
return (
|
|
147
|
-
<div className="flex flex-col h-full">
|
|
148
|
-
<ScrollArea className="flex-1 p-4">
|
|
147
|
+
<div className="flex flex-col h-full overflow-hidden">
|
|
148
|
+
<ScrollArea className="flex-1 min-h-0 p-4">
|
|
149
149
|
<div className="space-y-3">
|
|
150
150
|
{/* AI State Indicator */}
|
|
151
151
|
{aiState === 'analyzing' && (
|
|
@@ -246,7 +246,7 @@ function DraftTicketView({ onClose, onCreated }: { onClose: () => void; onCreate
|
|
|
246
246
|
}
|
|
247
247
|
|
|
248
248
|
return (
|
|
249
|
-
<div className="flex flex-col h-full">
|
|
249
|
+
<div className="flex flex-col h-full overflow-hidden">
|
|
250
250
|
{/* Header — mirrors existing ticket header style */}
|
|
251
251
|
<div className="px-6 py-3 border-b border-border flex items-center justify-between shrink-0">
|
|
252
252
|
<div>
|
|
@@ -257,7 +257,7 @@ function DraftTicketView({ onClose, onCreated }: { onClose: () => void; onCreate
|
|
|
257
257
|
</div>
|
|
258
258
|
|
|
259
259
|
{/* Thread area */}
|
|
260
|
-
<ScrollArea className="flex-1 p-4">
|
|
260
|
+
<ScrollArea className="flex-1 min-h-0 p-4">
|
|
261
261
|
<div className="space-y-3">
|
|
262
262
|
{draftMessages.length === 0 && (
|
|
263
263
|
<p className="text-sm text-muted-foreground italic text-center py-8">Describe your issue and our AI will respond immediately.</p>
|
|
@@ -353,14 +353,9 @@ export function TicketsPage() {
|
|
|
353
353
|
|
|
354
354
|
const handleStatusChange = useCallback(async (newStatus: string) => {
|
|
355
355
|
if (!selectedId) return
|
|
356
|
-
await updateTicket(selectedId, {
|
|
357
|
-
data: {
|
|
358
|
-
status: newStatus,
|
|
359
|
-
aim_escalation_at: new Date().toISOString()
|
|
360
|
-
}
|
|
361
|
-
})
|
|
356
|
+
await updateTicket(selectedId, { status: newStatus })
|
|
362
357
|
refetch()
|
|
363
|
-
}, [selectedId,
|
|
358
|
+
}, [selectedId, updateTicket, refetch])
|
|
364
359
|
|
|
365
360
|
return (
|
|
366
361
|
<div className="flex flex-col h-full">
|