spine-framework 0.4.0 → 0.4.1
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.
|
@@ -4256,7 +4256,23 @@ export async function runAgent(
|
|
|
4256
4256
|
const threadVisibility = thread?.visibility || 'external'
|
|
4257
4257
|
let state = getResearchState(thread)
|
|
4258
4258
|
if (userMessage?.trim()) {
|
|
4259
|
-
|
|
4259
|
+
// Idempotent insert: the caller (ticket creation, sendMessage) often
|
|
4260
|
+
// persists the inbound row itself. When the thread's latest inbound
|
|
4261
|
+
// already carries this text the row exists — skip the insert so a
|
|
4262
|
+
// re-fired kick/step can never double-post the question. New-turn
|
|
4263
|
+
// semantics below (episode reset, user_question) are unaffected.
|
|
4264
|
+
const { data: lastInboundRows } = await adminDb
|
|
4265
|
+
.from('messages')
|
|
4266
|
+
.select('content')
|
|
4267
|
+
.eq('thread_id', threadId)
|
|
4268
|
+
.eq('direction', 'inbound')
|
|
4269
|
+
.order('sequence', { ascending: false })
|
|
4270
|
+
.order('created_at', { ascending: false })
|
|
4271
|
+
.limit(1)
|
|
4272
|
+
const lastInbound = Array.isArray(lastInboundRows) ? lastInboundRows[0] : lastInboundRows
|
|
4273
|
+
if ((lastInbound?.content || '').trim() !== userMessage.trim()) {
|
|
4274
|
+
await saveMessage(threadId, userMessage.trim(), 'human', null, ctx, replyTypeSlug, threadVisibility)
|
|
4275
|
+
}
|
|
4260
4276
|
if (!state.user_question) state.user_question = userMessage.trim()
|
|
4261
4277
|
}
|
|
4262
4278
|
if (!userMessage?.trim() && !state.user_question) {
|