historyDir = $historyDir; // Ensure directory exists if (!is_dir($this->historyDir)) { mkdir($this->historyDir, 0777, true); } } /** * Returns the conversation context for a given user. * * @param string $userId Stable client identifier * @param bool $full Whether to load extended history */ public function buildUserContext(string $userId, bool $full = true): string { $path = $this->getHistoryPath($userId); if (!is_file($path)) { return ''; } $lines = file($path, FILE_IGNORE_NEW_LINES); if ($lines === false) { return ''; } $maxLines = $full ? $this->maxFullLines : $this->maxRegularLines; $selected = array_slice($lines, -$maxLines); return implode("\n", $selected); } /** * Appends a completed interaction to the user's history. * * Format (append-only): * Question: * */ public function appendHistory(string $userId, string $prompt, string $response): void { $path = $this->getHistoryPath($userId); $entry = "Question: {$prompt}\n{$response}\n"; file_put_contents($path, $entry, FILE_APPEND | LOCK_EX); } /** * Deletes the complete conversation history for a user. */ public function deleteHistory(string $userId): void { $path = $this->getHistoryPath($userId); if (is_file($path)) { unlink($path); } } /** * Resolves the absolute history file path for a user. */ private function getHistoryPath(string $userId): string { $safeUserId = preg_replace('/[^a-zA-Z0-9_-]/', '_', $userId); return $this->historyDir . '/' . $safeUserId . '.txt'; } }