$messages) { $threads[$key] = array_values( array_filter( is_array($messages) ? $messages : [], static fn($message) => is_array($message) && is_int($message['createdAt'] ?? null) && $message['createdAt'] > $cutoff && $message['createdAt'] <= $now, ), ); if (!$threads[$key]) { unset($threads[$key]); } } return $threads; } public static function clean(array $messages, bool $timestamps = false): array { $result = []; foreach (array_slice($messages, -100) as $message) { if ( is_int($message['createdAt'] ?? null) && $message['createdAt'] <= time() - 7 * DAY_IN_SECONDS ) { continue; } if ( in_array($message['role'] ?? '', ['user', 'assistant'], true) && is_string($message['content'] ?? null) ) { $result[] = [ 'role' => $message['role'], 'content' => sanitize_textarea_field(mb_substr($message['content'], 0, 6000)), ]; if ($timestamps && is_int($message['createdAt'] ?? null) && $message['createdAt'] <= time()) { $result[array_key_last($result)]['createdAt'] = $message['createdAt']; } } } return $result; } public static function store(array &$data, string $thread, array $messages): void { $existing = []; foreach (self::prune($data['conversations'] ?? [])[$thread] ?? [] as $message) { $fingerprint = hash('sha256', $message['role'] . '|' . $message['content']); $existing[$fingerprint][] = $message['createdAt']; } $clean = self::clean($messages, true); foreach ($clean as &$message) { $fingerprint = hash('sha256', $message['role'] . '|' . $message['content']); $message['createdAt'] = !empty($existing[$fingerprint]) ? array_shift($existing[$fingerprint]) : $message['createdAt'] ?? time(); } unset($message); $data['conversations'][$thread] = $clean; $data['conversations'] = array_slice($data['conversations'], -30, null, true); } public static function remember(string $id, array $data): void { if (!empty($data['remember'])) { $threads = self::prune($data['conversations'] ?? []); if (!$threads) { self::clear(); return; } $latest = max( array_map(static fn($messages) => max(array_column($messages, 'createdAt')), $threads), ); update_user_meta( get_current_user_id(), self::key(), wp_slash([ 'sessionId' => $id, 'lastPage' => $data['lastPage'], 'conversations' => $threads, 'expires' => $latest + 7 * DAY_IN_SECONDS, ]), ); } } public static function clear(): void { delete_user_meta(get_current_user_id(), self::key()); } }