|
|
const crypto = require('crypto') |
|
|
const logger = require('./logger') |
|
|
|
|
|
class SessionHelper { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
generateSessionHash(requestBody) { |
|
|
if (!requestBody || typeof requestBody !== 'object') { |
|
|
return null |
|
|
} |
|
|
|
|
|
|
|
|
if (requestBody.metadata && requestBody.metadata.user_id) { |
|
|
|
|
|
const userIdString = requestBody.metadata.user_id |
|
|
const sessionMatch = userIdString.match(/session_([a-f0-9-]{36})/) |
|
|
if (sessionMatch && sessionMatch[1]) { |
|
|
const sessionId = sessionMatch[1] |
|
|
|
|
|
logger.debug(`📋 Session ID extracted from metadata.user_id: ${sessionId}`) |
|
|
return sessionId |
|
|
} |
|
|
} |
|
|
|
|
|
let cacheableContent = '' |
|
|
const system = requestBody.system || '' |
|
|
const messages = requestBody.messages || [] |
|
|
|
|
|
|
|
|
|
|
|
if (Array.isArray(system)) { |
|
|
for (const part of system) { |
|
|
if (part && part.cache_control && part.cache_control.type === 'ephemeral') { |
|
|
cacheableContent += part.text || '' |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
for (const msg of messages) { |
|
|
const content = msg.content || '' |
|
|
let hasCacheControl = false |
|
|
|
|
|
if (Array.isArray(content)) { |
|
|
for (const part of content) { |
|
|
if (part && part.cache_control && part.cache_control.type === 'ephemeral') { |
|
|
hasCacheControl = true |
|
|
break |
|
|
} |
|
|
} |
|
|
} else if ( |
|
|
typeof content === 'string' && |
|
|
msg.cache_control && |
|
|
msg.cache_control.type === 'ephemeral' |
|
|
) { |
|
|
hasCacheControl = true |
|
|
} |
|
|
|
|
|
if (hasCacheControl) { |
|
|
for (const message of messages) { |
|
|
let messageText = '' |
|
|
if (typeof message.content === 'string') { |
|
|
messageText = message.content |
|
|
} else if (Array.isArray(message.content)) { |
|
|
messageText = message.content |
|
|
.filter((part) => part.type === 'text') |
|
|
.map((part) => part.text || '') |
|
|
.join('') |
|
|
} |
|
|
|
|
|
if (messageText) { |
|
|
cacheableContent += messageText |
|
|
break |
|
|
} |
|
|
} |
|
|
break |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (cacheableContent) { |
|
|
const hash = crypto |
|
|
.createHash('sha256') |
|
|
.update(cacheableContent) |
|
|
.digest('hex') |
|
|
.substring(0, 32) |
|
|
logger.debug(`📋 Session hash generated from cacheable content: ${hash}`) |
|
|
return hash |
|
|
} |
|
|
|
|
|
|
|
|
if (system) { |
|
|
let systemText = '' |
|
|
if (typeof system === 'string') { |
|
|
systemText = system |
|
|
} else if (Array.isArray(system)) { |
|
|
systemText = system.map((part) => part.text || '').join('') |
|
|
} |
|
|
|
|
|
if (systemText) { |
|
|
const hash = crypto.createHash('sha256').update(systemText).digest('hex').substring(0, 32) |
|
|
logger.debug(`📋 Session hash generated from system content: ${hash}`) |
|
|
return hash |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (messages.length > 0) { |
|
|
const firstMessage = messages[0] |
|
|
let firstMessageText = '' |
|
|
|
|
|
if (typeof firstMessage.content === 'string') { |
|
|
firstMessageText = firstMessage.content |
|
|
} else if (Array.isArray(firstMessage.content)) { |
|
|
if (!firstMessage.content) { |
|
|
logger.error('📋 Session hash generated from first message failed: ', firstMessage) |
|
|
} |
|
|
|
|
|
firstMessageText = firstMessage.content |
|
|
.filter((part) => part.type === 'text') |
|
|
.map((part) => part.text || '') |
|
|
.join('') |
|
|
} |
|
|
|
|
|
if (firstMessageText) { |
|
|
const hash = crypto |
|
|
.createHash('sha256') |
|
|
.update(firstMessageText) |
|
|
.digest('hex') |
|
|
.substring(0, 32) |
|
|
logger.debug(`📋 Session hash generated from first message: ${hash}`) |
|
|
return hash |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
logger.debug('📋 Unable to generate session hash - no suitable content found') |
|
|
return null |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getSessionRedisKey(sessionHash) { |
|
|
return `sticky_session:${sessionHash}` |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
isValidSessionHash(sessionHash) { |
|
|
return ( |
|
|
typeof sessionHash === 'string' && |
|
|
sessionHash.length === 32 && |
|
|
/^[a-f0-9]{32}$/.test(sessionHash) |
|
|
) |
|
|
} |
|
|
} |
|
|
|
|
|
module.exports = new SessionHelper() |
|
|
|