$role, "content" => (string)$content, "ts" => time(), "iso" => date("c"), "metadata" => $metadata, ]; return @file_put_contents( self::path($chat_id), json_encode($entry, JSON_UNESCAPED_UNICODE) . "\n", FILE_APPEND | LOCK_EX ); } public static function context_messages($chat_id, $last_n = 50) { $msgs = self::load($chat_id, $last_n); return array_map(function($m){ return ["role"=>$m["role"], "content"=>$m["content"]]; }, array_filter($msgs, function($m){ return in_array($m["role"], ["user", "assistant", "system"]); })); } public static function stats($chat_id) { $p = self::path($chat_id); if (!file_exists($p)) return ["exists"=>false, "turns"=>0, "size"=>0]; $lines = @file($p, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); return [ "exists" => true, "turns" => count($lines ?: []), "size_bytes" => filesize($p), "path" => $p, "first" => ($lines && $lines[0]) ? @json_decode($lines[0], true)["iso"] ?? "?" : "?", "last" => ($lines && end($lines)) ? @json_decode(end($lines), true)["iso"] ?? "?" : "?", ]; } public static function list_chats() { self::init(); $out = []; foreach (glob(self::DIR . "/*.jsonl") as $f) { $bn = basename($f, ".jsonl"); $lines = @file($f, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); $out[] = [ "chat_id" => $bn, "turns" => count($lines ?: []), "size_kb" => round(filesize($f)/1024, 1), "mtime" => date("c", filemtime($f)), ]; } return $out; } } // If called directly via HTTP, act as API if (php_sapi_name() !== "cli" && basename($_SERVER["SCRIPT_FILENAME"] ?? "") === "ambre-internal-memory.php") { header("Content-Type: application/json; charset=utf-8"); $raw = file_get_contents("php://input"); $in = json_decode($raw, true) ?: $_GET; $action = $in["action"] ?? "stats"; $chat_id = $in["chat_id"] ?? ""; switch ($action) { case "append": $result = AmbreInternalMemory::append($chat_id, $in["role"] ?? "user", $in["content"] ?? "", $in["metadata"] ?? []); echo json_encode(["ok"=>(bool)$result, "written"=>$result]); break; case "load": echo json_encode(["ok"=>true, "messages"=>AmbreInternalMemory::load($chat_id, intval($in["n"] ?? 100))]); break; case "context": echo json_encode(["ok"=>true, "messages"=>AmbreInternalMemory::context_messages($chat_id, intval($in["n"] ?? 50))]); break; case "stats": echo json_encode(["ok"=>true, "stats"=>AmbreInternalMemory::stats($chat_id)]); break; case "list": echo json_encode(["ok"=>true, "chats"=>AmbreInternalMemory::list_chats()]); break; default: echo json_encode(["error"=>"unknown action. Use: append|load|context|stats|list"]); } }