{"id":108851,"date":"2025-05-13T20:37:30","date_gmt":"2025-05-13T17:07:30","guid":{"rendered":"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/"},"modified":"2025-05-13T20:37:30","modified_gmt":"2025-05-13T17:07:30","slug":"%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7","status":"publish","type":"post","link":"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/","title":{"rendered":"\u0646\u062d\u0648\u0647 \u0633\u0627\u062e\u062a \u0628\u0631\u0646\u0627\u0645\u0647 \u0639\u0627\u0645\u0644 \u0635\u0648\u062a\u06cc AI \u0628\u0647 \u067e\u0627\u06cc\u0627\u0646 \u0628\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 AI\/ML API \u0648 OpenAi Realtime API"},"content":{"rendered":"<div data-article-id=\"2484982\" id=\"article-body\">\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_85 counter-hierarchy ez-toc-counter-rtl ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">\u0641\u0647\u0631\u0633\u062a \u0645\u0637\u0627\u0644\u0628<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"\u062a\u063a\u06cc\u06cc\u0631 \u0648\u0636\u0639\u06cc\u062a \u0641\u0647\u0631\u0633\u062a \u0645\u0637\u0627\u0644\u0628\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%F0%9F%8C%B1_%D9%88%DB%8C_%D8%B9%D9%88%D8%A7%D9%85%D9%84_%D9%87%D9%88%D8%B4_%D9%85%D8%B5%D9%86%D9%88%D8%B9%DB%8C_%D8%A8%D8%B1%D8%A7%DB%8C_%D8%B1%D8%B4%D8%AF_%D8%B4%D8%AE%D8%B5%DB%8C\" >\ud83c\udf31 \u0648\u06cc: \u0639\u0648\u0627\u0645\u0644 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u0628\u0631\u0627\u06cc \u0631\u0634\u062f \u0634\u062e\u0635\u06cc<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D9%85%D8%B9%D9%85%D8%A7%D8%B1%DB%8C\" >\u0645\u0639\u0645\u0627\u0631\u06cc<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D9%85%D9%82%D8%AF%D9%85%D9%87\" >\u0645\u0642\u062f\u0645\u0647<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%AA%D9%86%D8%B8%DB%8C%D9%85_%D9%BE%D8%B1%D9%88%DA%98%D9%87_%D8%A7%D9%88%D9%84%DB%8C%D9%87\" >\u062a\u0646\u0638\u06cc\u0645 \u067e\u0631\u0648\u0698\u0647 \u0627\u0648\u0644\u06cc\u0647<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%B3%D8%A7%D8%AE%D8%AA_%D9%86%D9%85%D8%A7%DB%8C%D9%86%D8%AF%DA%AF%D8%A7%D9%86_AI_%D8%B3%D9%81%D8%A7%D8%B1%D8%B4%DB%8C_SDK\" >\u0633\u0627\u062e\u062a \u0646\u0645\u0627\u06cc\u0646\u062f\u06af\u0627\u0646 AI \u0633\u0641\u0627\u0631\u0634\u06cc SDK<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#Made_Made_AI_Agents_SDK_%D8%A7%D8%B2_%D8%A7%D8%A8%D8%AA%D8%AF%D8%A7\" >Made Made AI Agents SDK (\u0627\u0632 \u0627\u0628\u062a\u062f\u0627)<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D9%86%D9%85%D8%A7%DB%8C%D9%86%D8%AF%DA%AF%D8%A7%D9%86_%D9%87%D9%88%D8%B4_%D9%85%D8%B5%D9%86%D9%88%D8%B9%DB%8C_%D9%88%DB%8C\" >\u0646\u0645\u0627\u06cc\u0646\u062f\u06af\u0627\u0646 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u0648\u06cc<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%DA%AF%D9%88%D8%B1\" >\u06af\u0648\u0631<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D9%86%D9%85%D8%A7%DB%8C%D9%86%D8%AF%D9%87_%D8%B9%D9%85%D9%88%D9%85%DB%8C\" >\u0646\u0645\u0627\u06cc\u0646\u062f\u0647 \u0639\u0645\u0648\u0645\u06cc<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D9%86%D9%85%D8%A7%DB%8C%D9%86%D8%AF%D9%87_%D9%85%D8%AF%DB%8C%D8%B1_%D9%BE%D8%A7%D8%AF%D8%A7%D8%B4\" >\u0646\u0645\u0627\u06cc\u0646\u062f\u0647 \u0645\u062f\u06cc\u0631 \u067e\u0627\u062f\u0627\u0634<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%B9%D8%A7%D9%85%D9%84_%D9%85%D8%A7%D8%B4%DB%8C%D9%86_%D8%AD%D8%B3%D8%A7%D8%A8\" >\u0639\u0627\u0645\u0644 \u0645\u0627\u0634\u06cc\u0646 \u062d\u0633\u0627\u0628<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%B9%D8%A7%D9%85%D9%84_%D9%85%D8%AF%DB%8C%D8%B1_%D8%B9%D8%A7%D8%AF%D8%AA\" >\u0639\u0627\u0645\u0644 \u0645\u062f\u06cc\u0631 \u0639\u0627\u062f\u062a<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%B9%D8%A7%D9%85%D9%84_%DA%A9%D8%A7%D8%B1%D8%A8%D8%B1_%D8%B3%D8%A7%D8%AF%D9%87\" >\u0639\u0627\u0645\u0644 \u06a9\u0627\u0631\u0628\u0631 \u0633\u0627\u062f\u0647<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D9%82%D9%88%D8%A7%D9%86%DB%8C%D9%86_%D8%A7%D9%86%D8%AA%D9%82%D8%A7%D9%84\" >\u0642\u0648\u0627\u0646\u06cc\u0646 \u0627\u0646\u062a\u0642\u0627\u0644<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D9%87%D9%85%D9%87_%D8%B9%D9%88%D8%A7%D9%85%D9%84\" >\u0647\u0645\u0647 \u0639\u0648\u0627\u0645\u0644<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-16\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D9%85%D9%86%D8%B7%D9%82_%D8%B9%D9%88%D8%A7%D9%85%D9%84_%D8%AC%D8%A7%D9%85%D8%B9\" >\u0645\u0646\u0637\u0642 \u0639\u0648\u0627\u0645\u0644 \u062c\u0627\u0645\u0639<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-17\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%B2%D9%85%DB%8C%D9%86%D9%87_%DA%A9%D8%A7%D8%B1%D8%A8%D8%B1_%D8%B1%D8%A7_%D8%AA%D8%B2%D8%B1%DB%8C%D9%82_%DA%A9%D9%86%DB%8C%D8%AF\" >\u0632\u0645\u06cc\u0646\u0647 \u06a9\u0627\u0631\u0628\u0631 \u0631\u0627 \u062a\u0632\u0631\u06cc\u0642 \u06a9\u0646\u06cc\u062f<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-18\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%A8%D9%84%D9%88%DA%A9_%D8%B2%D9%85%DB%8C%D9%86%D9%87_%DA%A9%D8%A7%D8%B1%D8%A8%D8%B1_%D8%B1%D8%A7_%D8%A7%DB%8C%D8%AC%D8%A7%D8%AF_%DA%A9%D9%86%DB%8C%D8%AF\" >\u0628\u0644\u0648\u06a9 \u0632\u0645\u06cc\u0646\u0647 \u06a9\u0627\u0631\u0628\u0631 \u0631\u0627 \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-19\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%A7%D8%A8%D8%B2%D8%A7%D8%B1%D9%87%D8%A7%DB%8C_%D8%AF%D8%A7%D8%AF%D9%87_%DA%A9%D8%A7%D8%B1%D8%A8%D8%B1_%D8%B1%D8%A7_%D8%A7%DB%8C%D8%AC%D8%A7%D8%AF_%DA%A9%D9%86%DB%8C%D8%AF\" >\u0627\u0628\u0632\u0627\u0631\u0647\u0627\u06cc \u062f\u0627\u062f\u0647 \u06a9\u0627\u0631\u0628\u0631 \u0631\u0627 \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f<\/a><\/li><\/ul><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-20\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#API\" >API<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-21\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%AA%D9%88%D8%A7%D8%A8%D8%B9_%D9%BE%DB%8C%D8%B4_%D9%81%D8%B1%D8%B6\" >\u062a\u0648\u0627\u0628\u0639 \u067e\u06cc\u0634 \u0641\u0631\u0636<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-22\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%DA%A9%D9%86%D8%AA%D8%B1%D9%84_%DA%A9%D9%86%D9%86%D8%AF%D9%87_%D9%85%D8%B3%DB%8C%D8%B1_API\" >\u06a9\u0646\u062a\u0631\u0644 \u06a9\u0646\u0646\u062f\u0647 \u0645\u0633\u06cc\u0631 API<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-23\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%AA%D9%85%D8%A7%D8%B3_%D8%A8%D8%A7_%D8%B9%D9%85%D9%84%DA%A9%D8%B1%D8%AF_%D8%B9%D9%85%D9%84%DA%A9%D8%B1%D8%AF\" >\u062a\u0645\u0627\u0633 \u0628\u0627 \u0639\u0645\u0644\u06a9\u0631\u062f \u0639\u0645\u0644\u06a9\u0631\u062f<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-24\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%B9%D9%85%D9%84%DA%A9%D8%B1%D8%AF%D9%87%D8%A7%DB%8C_%D9%BE%D8%A7%DB%8C%DA%AF%D8%A7%D9%87_%D8%AF%D8%A7%D8%AF%D9%87_%D8%B1%D8%A7_%DA%A9%D9%86%D8%AA%D8%B1%D9%84_%DA%A9%D9%86%DB%8C%D8%AF\" >\u0639\u0645\u0644\u06a9\u0631\u062f\u0647\u0627\u06cc \u067e\u0627\u06cc\u06af\u0627\u0647 \u062f\u0627\u062f\u0647 \u0631\u0627 \u06a9\u0646\u062a\u0631\u0644 \u06a9\u0646\u06cc\u062f<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-25\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%B3%D8%A7%D8%AE%D8%AA%D9%86_%D8%B9%D8%A7%D9%85%D9%84_WEI_AI\" >\u0633\u0627\u062e\u062a\u0646 \u0639\u0627\u0645\u0644 WEI AI<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-26\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%B1%D8%A7%D8%A8%D8%B7_%DA%AF%D9%BE\" >\u0631\u0627\u0628\u0637 \u06af\u067e<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-27\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D9%88%D8%B1%D9%88%D8%AF%DB%8C_%DA%AF%D9%BE\" >\u0648\u0631\u0648\u062f\u06cc \u06af\u067e<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-28\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D9%BE%DB%8C%D8%B4%D8%B1%D9%81%D8%AA_%D9%87%D8%A7%DB%8C_%D8%A8%DB%8C%D8%B4%D8%AA%D8%B1_%D9%88%D8%B1%D9%88%D8%AF%DB%8C_%DA%86%D8%AA\" >\u067e\u06cc\u0634\u0631\u0641\u062a \u0647\u0627\u06cc \u0628\u06cc\u0634\u062a\u0631 (\u0648\u0631\u0648\u062f\u06cc \u0686\u062a)<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-29\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%A7%D8%B1%D8%A7%D8%A6%D9%87_%D8%AF%D9%87%D9%86%D8%AF%D9%87_%DA%AF%D9%BE\" >\u0627\u0631\u0627\u0626\u0647 \u062f\u0647\u0646\u062f\u0647 \u06af\u067e<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-30\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%A7%D8%B1%D8%A7%D8%A6%D9%87_%D8%AF%D9%87%D9%86%D8%AF%DA%AF%D8%A7%D9%86_%D8%A7%D8%B1%D8%A7%D8%A6%D9%87_%D8%AF%D9%87%D9%86%D8%AF%D9%87_%DA%AF%D9%BE\" >\u0627\u0631\u0627\u0626\u0647 \u062f\u0647\u0646\u062f\u06af\u0627\u0646 (\u0627\u0631\u0627\u0626\u0647 \u062f\u0647\u0646\u062f\u0647 \u06af\u067e)<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-31\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%B7%D8%B1%D8%AD_%D9%BE%D8%A7%DB%8C%DA%AF%D8%A7%D9%87_%D8%AF%D8%A7%D8%AF%D9%87_%D8%B1%D8%A7_%D8%AA%D8%B9%D8%B1%DB%8C%D9%81_%DA%A9%D9%86%DB%8C%D8%AF\" >\u0637\u0631\u062d \u067e\u0627\u06cc\u06af\u0627\u0647 \u062f\u0627\u062f\u0647 \u0631\u0627 \u062a\u0639\u0631\u06cc\u0641 \u06a9\u0646\u06cc\u062f<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-32\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%B2%D9%85%DB%8C%D9%86%D9%87_%D9%BE%D8%A7%DB%8C%DA%AF%D8%A7%D9%87_%D8%AF%D8%A7%D8%AF%D9%87\" >\u0632\u0645\u06cc\u0646\u0647 \u067e\u0627\u06cc\u06af\u0627\u0647 \u062f\u0627\u062f\u0647<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-33\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%A7%D8%B1%D8%A7%D8%A6%D9%87_%D8%AF%D9%87%D9%86%D8%AF%DA%AF%D8%A7%D9%86_%D8%B2%D9%85%DB%8C%D9%86%D9%87_%D8%A8%D8%A7%D9%86%DA%A9_%D8%A7%D8%B7%D9%84%D8%A7%D8%B9%D8%A7%D8%AA%DB%8C\" >\u0627\u0631\u0627\u0626\u0647 \u062f\u0647\u0646\u062f\u06af\u0627\u0646 (\u0632\u0645\u06cc\u0646\u0647 \u0628\u0627\u0646\u06a9 \u0627\u0637\u0644\u0627\u0639\u0627\u062a\u06cc)<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-34\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%B2%D9%85%DB%8C%D9%86%D9%87_%D8%AD%D8%A7%D9%81%D8%B8%D9%87_%D9%BE%D9%86%D9%87%D8%A7%D9%86_%DA%A9%D8%A7%D8%B1%D8%A8%D8%B1\" >\u0632\u0645\u06cc\u0646\u0647 \u062d\u0627\u0641\u0638\u0647 \u067e\u0646\u0647\u0627\u0646 \u06a9\u0627\u0631\u0628\u0631<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-35\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%A7%D8%B1%D8%A7%D8%A6%D9%87_%D8%AF%D9%87%D9%86%D8%AF%DA%AF%D8%A7%D9%86_%D8%B2%D9%85%DB%8C%D9%86%D9%87_%D8%AD%D8%A7%D9%81%D8%B8%D9%87_%D9%BE%D9%86%D9%87%D8%A7%D9%86_%DA%A9%D8%A7%D8%B1%D8%A8%D8%B1\" >\u0627\u0631\u0627\u0626\u0647 \u062f\u0647\u0646\u062f\u06af\u0627\u0646 (\u0632\u0645\u06cc\u0646\u0647 \u062d\u0627\u0641\u0638\u0647 \u067e\u0646\u0647\u0627\u0646 \u06a9\u0627\u0631\u0628\u0631)<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-36\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%DA%AF%D9%BE_%D8%B5%D9%88%D8%AA%DB%8C\" >\u06af\u067e \u0635\u0648\u062a\u06cc<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-37\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%B1%D8%B3%DB%8C%D8%AF%DA%AF%DB%8C_%D8%A8%D9%87_%D8%B1%D9%88%DB%8C%D8%AF%D8%A7%D8%AF_%D8%B3%D8%B1%D9%88%D8%B1_%D9%87%D9%88%DA%A9\" >\u0631\u0633\u06cc\u062f\u06af\u06cc \u0628\u0647 \u0631\u0648\u06cc\u062f\u0627\u062f \u0633\u0631\u0648\u0631 (\u0647\u0648\u06a9)<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-38\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%AD%D8%A7%D9%84%D8%AA_%D8%AC%D8%B1%DB%8C%D8%A7%D9%86_%D9%88%D8%A7%D9%82%D8%B9%DB%8C\" >\u062d\u0627\u0644\u062a \u062c\u0631\u06cc\u0627\u0646 \u0648\u0627\u0642\u0639\u06cc<\/a><\/li><\/ul><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-39\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%A7%D8%AF%D8%BA%D8%A7%D9%85_%D8%A8%D8%A7_AIML_API_%D9%88_Openai_Realtime_API\" >\u0627\u062f\u063a\u0627\u0645 \u0628\u0627 AI\/ML API \u0648 Openai Realtime API<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-40\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D9%BE%DB%8C%DA%A9%D8%B1%D8%A8%D9%86%D8%AF%DB%8C_%D8%B9%D9%88%D8%A7%D9%85%D9%84_%D9%87%D9%88%D8%B4_%D9%85%D8%B5%D9%86%D9%88%D8%B9%DB%8C\" >\u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc \u0639\u0648\u0627\u0645\u0644 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-41\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%A7%D8%A8%D8%B2%D8%A7%D8%B1%D9%87%D8%A7%DB%8C_%D9%BE%D8%A7%DB%8C%DA%AF%D8%A7%D9%87_%D8%AF%D8%A7%D8%AF%D9%87_%D8%B9%D8%A7%D9%85%D9%84\" >\u0627\u0628\u0632\u0627\u0631\u0647\u0627\u06cc \u067e\u0627\u06cc\u06af\u0627\u0647 \u062f\u0627\u062f\u0647 \u0639\u0627\u0645\u0644<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-42\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%A2%D8%AA%D8%B4_%D8%B3%D9%88%D8%B2%DB%8C_OpenTime_%D8%A8%D8%A7%D8%B2_%D8%A7%D8%B3%D8%AA\" >\u0622\u062a\u0634 \u0633\u0648\u0632\u06cc OpenTime \u0628\u0627\u0632 \u0627\u0633\u062a<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-43\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%AA%D9%86%D8%B8%DB%8C%D9%85_env\" >\u062a\u0646\u0638\u06cc\u0645 .env<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-44\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%A8%D8%A7%D8%B2%DA%AF%D8%B4%D8%AA_%D8%A8%D9%87_UI\" >\u0628\u0627\u0632\u06af\u0634\u062a \u0628\u0647 UI<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-45\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87_%D8%B1%D8%A7_%D8%A7%D8%AC%D8%B1%D8%A7_%DA%A9%D9%86%DB%8C%D8%AF\" >\u0628\u0631\u0646\u0627\u0645\u0647 \u0631\u0627 \u0627\u062c\u0631\u0627 \u06a9\u0646\u06cc\u062f<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-46\" href=\"https:\/\/nabfollower.com\/blog\/%d9%86%d8%ad%d9%88%d9%87-%d8%b3%d8%a7%d8%ae%d8%aa-%d8%a8%d8%b1%d9%86%d8%a7%d9%85%d9%87-%d8%b9%d8%a7%d9%85%d9%84-%d8%b5%d9%88%d8%aa%db%8c-ai-%d8%a8%d9%87-%d9%be%d8%a7%db%8c%d8%a7%d9%86-%d8%a8%d8%a7\/#%D9%85%D8%B1%D8%A7%D8%AD%D9%84_%D8%A8%D8%B9%D8%AF%DB%8C\" >\u0645\u0631\u0627\u062d\u0644 \u0628\u0639\u062f\u06cc<\/a><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"%F0%9F%8C%B1_%D9%88%DB%8C_%D8%B9%D9%88%D8%A7%D9%85%D9%84_%D9%87%D9%88%D8%B4_%D9%85%D8%B5%D9%86%D9%88%D8%B9%DB%8C_%D8%A8%D8%B1%D8%A7%DB%8C_%D8%B1%D8%B4%D8%AF_%D8%B4%D8%AE%D8%B5%DB%8C\"><\/span>\n<p>  \ud83c\udf31 \u0648\u06cc: \u0639\u0648\u0627\u0645\u0644 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u0628\u0631\u0627\u06cc \u0631\u0634\u062f \u0634\u062e\u0635\u06cc<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><img decoding=\"async\" src=\"https:\/\/media2.dev.to\/dynamic\/image\/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto\/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4tb6kr52ys10smsrw4ce.png\" alt=\"\u0648\u06cc: \u0639\u0648\u0627\u0645\u0644 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u0628\u0631\u0627\u06cc \u0631\u0634\u062f \u0634\u062e\u0635\u06cc\" loading=\"lazy\" width=\"800\" height=\"450\" title=\"\"><\/p>\n<p>\u0627\u062e\u06cc\u0631\u0627\u064b \u062f\u0631 \u06cc\u06a9 Hackathon Localdown \u0634\u0631\u06a9\u062a \u06a9\u0631\u062f\u0645. <br \/>\u0645\u0646 \u0648\u06cc \u0631\u0627 \u0633\u0627\u062e\u062a\u0645 \u060c \u06cc\u06a9 \u0639\u0627\u0645\u0644 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u06a9\u0647 \u0628\u0647 \u0634\u0645\u0627 \u062f\u0631 \u0627\u06cc\u062c\u0627\u062f \u0639\u0627\u062f\u062a \u0647\u0627\u06cc \u062e\u0648\u0628 \u06a9\u0645\u06a9 \u0645\u06cc \u06a9\u0646\u062f. <\/p>\n<p>TLDR: \ud83c\udf31 WEI \u0639\u0627\u0645\u0644 AI \u0645\u06a9\u0627\u0644\u0645\u0647 \u0634\u0645\u0627 \u0627\u0633\u062a \u06a9\u0647 \u0627\u0632 \u0637\u0631\u06cc\u0642 \u06af\u0641\u062a\u06af\u0648\u06cc \u0637\u0628\u06cc\u0639\u06cc \u060c \u0639\u0627\u062f\u062a \u0631\u0627 \u0628\u06cc \u062f\u0631\u062f\u0633\u0631 \u0645\u06cc \u06a9\u0646\u062f. \u0628\u0627 WEI \u0635\u062d\u0628\u062a \u06a9\u0646\u06cc\u062f \u060c \u0628\u0631\u0627\u06cc \u062b\u0628\u0627\u062a \u0627\u0645\u062a\u06cc\u0627\u0632 \u06a9\u0633\u0628 \u06a9\u0646\u06cc\u062f \u0648 \u06a9\u0627\u0631\u0647\u0627\u06cc \u0631\u0648\u0632\u0645\u0631\u0647 \u0631\u0627 \u0628\u0647 \u062a\u062c\u0631\u0628\u06cc\u0627\u062a \u067e\u0627\u062f\u0627\u0634 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0646\u06cc\u062f &#8211; \u0647\u0645\u0647 \u0628\u0627 \u0634\u062e\u0635\u06cc\u062a\u06cc \u0628\u0627\u0632\u06cc\u06af\u0648\u0634 \u06a9\u0647 \u0634\u0645\u0627 \u0631\u0627 \u062f\u0631 \u0633\u0641\u0631 \u0633\u0644\u0627\u0645\u062a\u06cc \u062e\u0648\u062f \u0627\u0646\u06af\u06cc\u0632\u0647 \u0645\u06cc \u062f\u0647\u062f. <\/p>\n<p>\u0645\u0646 \u062f\u0631 \u0647\u06a9\u0627\u062a\u0648\u0646 \u0645\u0642\u0627\u0645 \u0633\u0648\u0645 \u0631\u0627 \u06a9\u0633\u0628 \u06a9\u0631\u062f\u0645. <br \/>\u062f\u0631 \u0627\u06cc\u0646\u062c\u0627 \u06cc\u06a9 \u0622\u0645\u0648\u0632\u0634 \u062c\u0627\u0645\u0639 \u062f\u0631 \u0645\u0648\u0631\u062f \u0686\u06af\u0648\u0646\u06af\u06cc \u0633\u0627\u062e\u062a \u062e\u0648\u062f \u0627\u0632 \u062e\u06cc\u0644\u06cc \u062e\u0631\u0627\u0634 \u0622\u0648\u0631\u062f\u0647 \u0634\u062f\u0647 \u0627\u0633\u062a.<\/p>\n<p>\u0628\u06cc\u0627\u06cc\u06cc\u062f \u0634\u0631\u0648\u0639 \u06a9\u0646\u06cc\u0645<\/p>\n<h2><span class=\"ez-toc-section\" id=\"%D9%85%D8%B9%D9%85%D8%A7%D8%B1%DB%8C\"><\/span>\n<p>  \u0645\u0639\u0645\u0627\u0631\u06cc<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><img decoding=\"async\" src=\"https:\/\/media2.dev.to\/dynamic\/image\/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto\/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6a5eh0ozk6atq7wosmho.png\" alt=\"\u0645\u0639\u0645\u0627\u0631\u06cc\" loading=\"lazy\" width=\"800\" height=\"450\" title=\"\"><\/p>\n<h2><span class=\"ez-toc-section\" id=\"%D9%85%D9%82%D8%AF%D9%85%D9%87\"><\/span>\n<p>  \u0645\u0642\u062f\u0645\u0647<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u062f\u0631 \u0627\u06cc\u0646 \u0622\u0645\u0648\u0632\u0634 \u060c \u0645\u0646 \u0634\u0645\u0627 \u0631\u0627 \u062f\u0631 \u06a9\u0644 \u0645\u0631\u0627\u062d\u0644 \u0633\u0627\u062e\u062a WEI \u0631\u0627\u0647\u0646\u0645\u0627\u06cc\u06cc \u0645\u06cc \u06a9\u0646\u0645. \u0627\u06cc\u0646 \u06cc\u06a9 \u0622\u0645\u0648\u0632\u0634 \u0628\u0633\u06cc\u0627\u0631 \u062c\u0627\u0645\u0639 \u0627\u0633\u062a \u060c \u0628\u0646\u0627\u0628\u0631\u0627\u06cc\u0646 \u0645\u0646 \u0632\u0645\u06cc\u0646 \u0632\u06cc\u0627\u062f\u06cc \u0631\u0627 \u067e\u0648\u0634\u0634 \u062e\u0648\u0627\u0647\u0645 \u062f\u0627\u062f. \u0642\u0633\u0645\u062a \u062c\u0627\u0644\u0628 \u0645\u0627 AI \u0639\u0648\u0627\u0645\u0644 SDK \u0631\u0627 \u0627\u0632 \u0627\u0628\u062a\u062f\u0627 \u0645\u06cc \u0633\u0627\u0632\u06cc\u0645 (\u0628\u0627 \u0645\u0631\u0627\u062c\u0639\u0647 \u0628\u0647 \u0645\u0623\u0645\u0648\u0631\u06cc\u0646 \u0631\u0633\u0645\u06cc OpenAi Python SDK).<\/p>\n<p>\u0627\u0632 \u062c\u0645\u0644\u0647 \u0627\u0645\u0627 \u0645\u062d\u062f\u0648\u062f \u0628\u0647: <\/p>\n<ul>\n<li>\u062a\u0646\u0638\u06cc\u0645 \u067e\u0631\u0648\u0698\u0647 \u0627\u0648\u0644\u06cc\u0647<\/li>\n<li>\u0633\u0627\u062e\u062a SDK AIE AIA \u0633\u0641\u0627\u0631\u0634\u06cc \u0628\u0627 \u062f\u0633\u062a\u0648\u0631\u0627\u0644\u0639\u0645\u0644 \u0647\u0627\u06cc \u067e\u06cc\u0686\u06cc\u062f\u0647 \u0633\u06cc\u0633\u062a\u0645<\/li>\n<li>\u0633\u0627\u062e\u062a\u0645\u0627\u0646 <em>\u0632\u06cc\u0628\u0627<\/em> \u0648\u062a <em>\u062e\u0646\u06a9 \u06a9\u0631\u062f\u0646<\/em> UI\/UX \u0628\u0627 UI Shadcn \u060c \u0628\u062f\u0648\u06cc \u062d\u0631\u06a9\u062a\u06cc \u060c \u06a9\u06cc\u062a \u0633\u0631\u06cc\u0639 \u0648 tailwindcs \u0628\u0627 \u0646\u0645\u0627\u062f\u0647\u0627\u06cc \u0645\u06cc\u0646\u06cc\u0645\u0627\u0644\u06cc\u0633\u062a\u06cc \u0627\u0632 \u0646\u0645\u0627\u062f\u0647\u0627\u06cc \u0641\u0633\u0641\u0631<\/li>\n<li>\u0627\u062f\u063a\u0627\u0645 \u0628\u0627 AI\/ML API \u0648 Openai Realtime API<\/li>\n<li>\u0630\u062e\u06cc\u0631\u0647 \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u0645\u062d\u0644\u06cc \u0628\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 IndexedDB<\/li>\n<li>\u0627\u0633\u062a\u0642\u0631\u0627\u0631 \u0628\u0631\u0646\u0627\u0645\u0647 \u0628\u0647 Vercel<\/li>\n<li>\u0648 \u0628\u0633\u06cc\u0627\u0631\u06cc \u062f\u06cc\u06af\u0631 &#8230;&#8230;..<\/li>\n<\/ul>\n<p>\u0628\u0646\u0627\u0628\u0631\u0627\u06cc\u0646 &#8230; \u062d\u062a\u0645\u0627\u064b \u0628\u0627 \u0645\u0646 \u0642\u0641\u0644 \u0648 \u0628\u0633\u0627\u0632\u06cc\u062f.<\/p>\n<p>\u0648\u06cc \u0627\u0632 \u062c\u062f\u06cc\u062f\u062a\u0631\u06cc\u0646 \u0648 \u0628\u0632\u0631\u06af\u062a\u0631\u06cc\u0646 \u0627\u0628\u0632\u0627\u0631\u0647\u0627 \u0628\u0647\u0631\u0647 \u0645\u06cc \u0628\u0631\u062f:<\/p>\n<blockquote>\n<p>\u0637\u0631\u0627\u062d Rua\u061f Anora &#8211; \u0628\u0648\u0645 Inteligent \u0631\u0627 \u0628\u0631\u0627\u06cc \u062e\u0644\u0627\u0642\u06cc\u062a \u0628\u06cc \u0646\u0647\u0627\u06cc\u062a \u0627\u0645\u062a\u062d\u0627\u0646 \u06a9\u0646\u06cc\u062f<\/p>\n<\/blockquote>\n<h2><span class=\"ez-toc-section\" id=\"%D8%AA%D9%86%D8%B8%DB%8C%D9%85_%D9%BE%D8%B1%D9%88%DA%98%D9%87_%D8%A7%D9%88%D9%84%DB%8C%D9%87\"><\/span>\n<p>  \u062a\u0646\u0638\u06cc\u0645 \u067e\u0631\u0648\u0698\u0647 \u0627\u0648\u0644\u06cc\u0647<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>shadcn\/ui \u0631\u0627 \u0628\u0631\u0627\u06cc next.js. \u0646\u0635\u0628 \u0648 \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc \u06a9\u0646\u06cc\u062f.<\/p>\n<p>\u062f\u0633\u062a\u0648\u0631 init \u0631\u0627 \u0628\u0631\u0627\u06cc \u0627\u06cc\u062c\u0627\u062f \u06cc\u06a9 \u067e\u0631\u0648\u0698\u0647 \u062c\u062f\u06cc\u062f \u0628\u0639\u062f\u06cc. js \u06cc\u0627 \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u06cc\u06a9 \u0645\u0648\u0631\u062f \u0645\u0648\u062c\u0648\u062f \u0627\u062c\u0631\u0627 \u06a9\u0646\u06cc\u062f:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code>npx shadcn@latest init\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0627\u06a9\u0646\u0648\u0646 \u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u0645 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0631\u062f\u0646 \u0642\u0637\u0639\u0627\u062a \u0631\u0627 \u0634\u0631\u0648\u0639 \u06a9\u0646\u06cc\u0645 &#8230;<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code>npx shadcn@latest add button\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u062f\u0633\u062a\u0648\u0631 \u0628\u0627\u0644\u0627 \u0627\u0636\u0627\u0641\u0647 \u0645\u06cc \u06a9\u0646\u062f <em>\u062f\u06a9\u0645\u0647<\/em> \u0645\u0624\u0644\u0641\u0647 \u067e\u0631\u0648\u0698\u0647 \u0634\u0645\u0627. \u0633\u067e\u0633 \u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u0622\u0646 \u0631\u0627 \u0645\u0627\u0646\u0646\u062f \u0627\u06cc\u0646 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">Button<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/components\/ui\/button<\/span><span class=\"dl\">\"<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">Home<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">return <\/span><span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nc\">Button<\/span><span class=\"p\">&gt;<\/span>WEI<span class=\"p\"\/><span class=\"nc\">Button<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\"\/><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n  <span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h2><span class=\"ez-toc-section\" id=\"%D8%B3%D8%A7%D8%AE%D8%AA_%D9%86%D9%85%D8%A7%DB%8C%D9%86%D8%AF%DA%AF%D8%A7%D9%86_AI_%D8%B3%D9%81%D8%A7%D8%B1%D8%B4%DB%8C_SDK\"><\/span>\n<p>  \u0633\u0627\u062e\u062a \u0646\u0645\u0627\u06cc\u0646\u062f\u06af\u0627\u0646 AI \u0633\u0641\u0627\u0631\u0634\u06cc SDK<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0645\u0627 \u0628\u0647 \u062a\u0642\u0631\u06cc\u0628\u0627\u064b \u0646\u06cc\u0627\u0632 \u062f\u0627\u0631\u06cc\u0645. 6 \u062a\u0627 7 \u0639\u0627\u0645\u0644 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u0628\u0631\u0627\u06cc \u0633\u0627\u062e\u062a \u0648\u06cc. <br \/>\u0622\u0646\u0647\u0627 \u0645\u0633\u0626\u0648\u0644 \u062c\u0646\u0628\u0647 \u0647\u0627\u06cc \u0645\u062e\u062a\u0644\u0641 \u0628\u0631\u0646\u0627\u0645\u0647 \u0647\u0633\u062a\u0646\u062f.<\/p>\n<blockquote>\n<p>\u0646\u0645\u0627\u06cc\u0646\u062f\u06af\u0627\u0646 \u0628\u06cc\u0634\u062a\u0631 \u062d\u062a\u06cc \u0633\u0631\u06af\u0631\u0645 \u06a9\u0646\u0646\u062f\u0647 \u062a\u0631 \u0647\u0633\u062a\u0646\u062f.<\/p>\n<\/blockquote>\n<p>\u0648\u06cc \u0645\u06cc \u062a\u0648\u0627\u0646\u062f \u0686\u0646\u062f\u06cc\u0646 \u0639\u0627\u0645\u0644 \u0631\u0627 \u0628\u0647 \u0637\u0648\u0631 \u0647\u0645\u0632\u0645\u0627\u0646 \u0627\u062f\u0627\u0631\u0647 \u06a9\u0646\u062f. <\/p>\n<ul>\n<li>\n<strong>\u06af\u0648\u0631<\/strong>: \u0627\u06cc\u0646 \u0646\u0645\u0627\u06cc\u0646\u062f\u0647 \u0645\u0633\u0626\u0648\u0644 \u062a\u0628\u0631\u06cc\u06a9 \u0628\u0647 \u06a9\u0627\u0631\u0628\u0631 \u0648 \u0627\u0631\u0627\u0626\u0647 \u06cc\u06a9 \u062a\u062c\u0631\u0628\u0647 \u0627\u0633\u062a\u0642\u0628\u0627\u0644 \u0634\u062e\u0635\u06cc \u0627\u0633\u062a.<\/li>\n<li>\n<strong>\u0646\u0645\u0627\u06cc\u0646\u062f\u0647 \u0639\u0645\u0648\u0645\u06cc<\/strong>: \u0627\u06cc\u0646 \u0646\u0645\u0627\u06cc\u0646\u062f\u0647 \u0645\u0633\u0626\u0648\u0644 \u06a9\u0627\u0631\u0647\u0627\u06cc \u0647\u062f\u0641 \u06a9\u0644\u06cc \u0645\u0627\u0646\u0646\u062f \u067e\u0627\u0633\u062e \u062f\u0627\u062f\u0646 \u0628\u0647 \u0633\u0624\u0627\u0644\u0627\u062a \u060c \u0627\u0631\u0627\u0626\u0647 \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u0648 \u063a\u06cc\u0631\u0647 \u0627\u0633\u062a.<\/li>\n<li>\n<strong>\u0639\u0627\u0645\u0644 \u0639\u0627\u062f\u062a<\/strong>: \u0627\u06cc\u0646 \u0639\u0627\u0645\u0644 \u0645\u0633\u0626\u0648\u0644 \u06a9\u0627\u0631\u0647\u0627\u06cc \u0645\u0631\u062a\u0628\u0637 \u0628\u0627 \u0639\u0627\u062f\u062a \u0645\u0627\u0646\u0646\u062f \u0627\u0636\u0627\u0641\u0647 \u06a9\u0631\u062f\u0646 \u0639\u0627\u062f\u0627\u062a \u060c \u0631\u062f\u06cc\u0627\u0628\u06cc \u067e\u06cc\u0634\u0631\u0641\u062a \u0648 \u063a\u06cc\u0631\u0647 \u0627\u0633\u062a.<\/li>\n<li>\n<strong>\u0646\u0645\u0627\u06cc\u0646\u062f\u0647 \u067e\u0627\u062f\u0627\u0634<\/strong>: \u0627\u06cc\u0646 \u0646\u0645\u0627\u06cc\u0646\u062f\u0647 \u0645\u0633\u0626\u0648\u0644 \u06a9\u0627\u0631\u0647\u0627\u06cc \u0645\u0631\u062a\u0628\u0637 \u0628\u0627 \u067e\u0627\u062f\u0627\u0634 \u0645\u0627\u0646\u0646\u062f \u0627\u0636\u0627\u0641\u0647 \u06a9\u0631\u062f\u0646 \u067e\u0627\u062f\u0627\u0634 \u060c \u067e\u06cc\u0634\u0631\u0641\u062a \u067e\u06cc\u06af\u06cc\u0631\u06cc \u0648 \u063a\u06cc\u0631\u0647 \u0627\u0633\u062a.<\/li>\n<li>\n<strong>\u0639\u0627\u0645\u0644<\/strong>: \u0627\u06cc\u0646 \u0646\u0645\u0627\u06cc\u0646\u062f\u0647 \u0645\u0633\u0626\u0648\u0644 \u06a9\u0627\u0631\u0647\u0627\u06cc \u0645\u0631\u062a\u0628\u0637 \u0628\u0627 \u062e\u0637 \u0645\u0627\u0646\u0646\u062f \u0627\u0636\u0627\u0641\u0647 \u06a9\u0631\u062f\u0646 \u0631\u06af\u0647 \u0647\u0627 \u060c \u067e\u06cc\u0634\u0631\u0641\u062a \u0631\u062f\u06cc\u0627\u0628\u06cc \u0648 \u063a\u06cc\u0631\u0647 \u0627\u0633\u062a.<\/li>\n<li>\n<strong>\u0627\u0645\u062a\u06cc\u0627\u0632<\/strong>: \u0627\u06cc\u0646 \u0646\u0645\u0627\u06cc\u0646\u062f\u0647 \u0645\u0633\u0626\u0648\u0644 \u0648\u0638\u0627\u06cc\u0641 \u0645\u0631\u0628\u0648\u0637 \u0628\u0647 \u0646\u0642\u0627\u0637 \u0645\u0627\u0646\u0646\u062f \u0627\u0636\u0627\u0641\u0647 \u06a9\u0631\u062f\u0646 \u0627\u0645\u062a\u06cc\u0627\u0632 \u060c \u067e\u06cc\u0634\u0631\u0641\u062a \u0631\u062f\u06cc\u0627\u0628\u06cc \u0648 \u063a\u06cc\u0631\u0647 \u0627\u0633\u062a.<\/li>\n<li>\n<strong>\u0639\u0627\u0645\u0644 \u0627\u062a\u0645\u0627\u0645<\/strong>: \u0627\u06cc\u0646 \u0646\u0645\u0627\u06cc\u0646\u062f\u0647 \u0645\u0633\u0626\u0648\u0644 \u0627\u0646\u062c\u0627\u0645 \u06a9\u0627\u0631\u0647\u0627\u06cc \u0645\u0631\u062a\u0628\u0637 \u0628\u0627 \u062a\u06a9\u0645\u06cc\u0644 \u0645\u0627\u0646\u0646\u062f \u0627\u0636\u0627\u0641\u0647 \u06a9\u0631\u062f\u0646 \u062a\u06a9\u0645\u06cc\u0644 \u060c \u067e\u06cc\u0634\u0631\u0641\u062a \u067e\u06cc\u06af\u06cc\u0631\u06cc \u0648 \u063a\u06cc\u0631\u0647 \u0627\u0633\u062a.<\/li>\n<\/ul>\n<p>\u0647\u0645\u0647 \u0639\u0648\u0627\u0645\u0644 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u0642\u0627\u062f\u0631 \u0628\u0647 \u0627\u0646\u062a\u0642\u0627\u0644 \u06a9\u0646\u062a\u0631\u0644 \u0628\u0647 \u06cc\u06a9\u062f\u06cc\u06af\u0631 \u0647\u0633\u062a\u0646\u062f. <br \/>\u0628\u0627 \u0627\u0628\u0632\u0627\u0631\u0647\u0627\u06cc \u0645\u0646\u0627\u0633\u0628 \u062a\u0645\u0627\u0633 \u0628\u06af\u06cc\u0631\u06cc\u062f \u0648 \u0622\u0646\u0647\u0627 \u0631\u0627 \u0627\u062c\u0631\u0627 \u06a9\u0646\u06cc\u062f.<\/p>\n<blockquote>\n<p>\u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u0648\u06cc\u062f\u06cc\u0648\u06cc \u0646\u0633\u062e\u0647 \u06cc \u0646\u0645\u0627\u06cc\u0634\u06cc \u0631\u0627 \u062f\u0631 \u0632\u06cc\u0631 \u0645\u0634\u0627\u0647\u062f\u0647 \u06a9\u0646\u06cc\u062f.<\/p>\n<\/blockquote>\n<p><a href=\"https:\/\/www.youtube.com\/watch\u061fv=logbsew_ivy\" rel=\"nofollow noopener\" target=\"_blank\">https:\/\/www.youtube.com\/watch\u061fv=logbsew_ivy<\/a><br \/>\n<\/iframe>\n<\/p>\n<p>\u06cc\u0627 \u0628\u0647 \u0627\u0633\u0644\u0627\u06cc\u062f\u0647\u0627\u06cc \u0627\u0631\u0627\u0626\u0647 \u062f\u0631 \u0632\u06cc\u0631 \u0646\u06af\u0627\u0647 \u06a9\u0646\u06cc\u062f.<\/p>\n<p>\u0645\u0639\u0631\u0641\u06cc WEI: AI Agents \u0628\u0631\u0627\u06cc \u0631\u0634\u062f \u0634\u062e\u0635\u06cc: https:\/\/www.canva.com\/design\/daglvqfujti\/pm8qn0ydccxy35frxl049g\/edit<\/p>\n<p><em>\u062d\u0645\u0644 \u0648 \u0646\u0642\u0644 \u0631\u0627 \u0627\u062f\u0627\u0645\u0647 \u062f\u0647\u06cc\u062f &#8230;<\/em><\/p>\n<h3><span class=\"ez-toc-section\" id=\"Made_Made_AI_Agents_SDK_%D8%A7%D8%B2_%D8%A7%D8%A8%D8%AA%D8%AF%D8%A7\"><\/span>\n<p>  Made Made AI Agents SDK (\u0627\u0632 \u0627\u0628\u062a\u062f\u0627)<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0645\u0627 \u0628\u0647 \u0646\u0645\u0627\u06cc\u0646\u062f\u06af\u0627\u0646 \u0631\u0633\u0645\u06cc OpenAi Python SDK \u0645\u0631\u0627\u062c\u0639\u0647 \u0645\u06cc \u06a9\u0646\u06cc\u0645 \u062a\u0627 \u0628\u062a\u0648\u0627\u0646\u06cc\u0645 AI Agents SDK \u0631\u0627 \u062f\u0631 TypeCript \u0628\u0633\u0627\u0632\u06cc\u0645.<\/p>\n<p>\u06cc\u06a9 \u0641\u0627\u06cc\u0644 \u062c\u062f\u06cc\u062f \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f <code>types.ts<\/code> \u062f\u0631 \u062f\u0627\u062e\u0644 <code>app<\/code> \u067e\u0648\u0634\u0647 <br \/>\u0648 \u06a9\u062f \u0632\u06cc\u0631 \u0631\u0627 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"k\">export<\/span> <span class=\"kd\">type<\/span> <span class=\"nx\">SessionStatus<\/span> <span class=\"o\">=<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">DISCONNECTED<\/span><span class=\"dl\">\"<\/span> <span class=\"o\">|<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">CONNECTING<\/span><span class=\"dl\">\"<\/span> <span class=\"o\">|<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">CONNECTED<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kr\">interface<\/span> <span class=\"nx\">ToolParameterProperty<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">type<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">description<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">enum<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">[];<\/span>\n  <span class=\"nl\">pattern<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">properties<\/span><span class=\"p\">?:<\/span> <span class=\"nb\">Record<\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">string<\/span><span class=\"p\">,<\/span> <span class=\"nx\">ToolParameterProperty<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">required<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">[];<\/span>\n  <span class=\"nl\">additionalProperties<\/span><span class=\"p\">?:<\/span> <span class=\"nx\">boolean<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">items<\/span><span class=\"p\">?:<\/span> <span class=\"nx\">ToolParameterProperty<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kr\">interface<\/span> <span class=\"nx\">ToolParameters<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">type<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">properties<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Record<\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">string<\/span><span class=\"p\">,<\/span> <span class=\"nx\">ToolParameterProperty<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">required<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">[];<\/span>\n  <span class=\"nl\">additionalProperties<\/span><span class=\"p\">?:<\/span> <span class=\"nx\">boolean<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kr\">interface<\/span> <span class=\"nx\">Tool<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">function<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">name<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">description<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"nx\">ToolParameters<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kr\">interface<\/span> <span class=\"nx\">AgentConfig<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">name<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">publicDescription<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span> <span class=\"c1\">\/\/ gives context to agent transfer tool<\/span>\n  <span class=\"nl\">instructions<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">tools<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Tool<\/span><span class=\"p\">[];<\/span>\n  <span class=\"nl\">toolLogic<\/span><span class=\"p\">?:<\/span> <span class=\"nb\">Record<\/span><span class=\"o\">&lt;<\/span>\n    <span class=\"kr\">string<\/span><span class=\"p\">,<\/span>\n    <span class=\"p\">(<\/span><span class=\"nx\">args<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">,<\/span> <span class=\"nx\">transcriptLogsFiltered<\/span><span class=\"p\">:<\/span> <span class=\"nx\">TranscriptItem<\/span><span class=\"p\">[])<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nb\">Promise<\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">any<\/span><span class=\"o\">&gt;<\/span> <span class=\"o\">|<\/span> <span class=\"kr\">any<\/span>\n  <span class=\"o\">&gt;<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">downstreamAgents<\/span><span class=\"p\">?:<\/span> <span class=\"nx\">AgentConfig<\/span><span class=\"p\">[]<\/span> <span class=\"o\">|<\/span> <span class=\"p\">{<\/span> <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span> <span class=\"nl\">publicDescription<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span> <span class=\"p\">}[];<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kd\">type<\/span> <span class=\"nx\">AllAgentConfigsType<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">Record<\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">string<\/span><span class=\"p\">,<\/span> <span class=\"nx\">AgentConfig<\/span><span class=\"p\">[]<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kr\">interface<\/span> <span class=\"nx\">TranscriptItem<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">itemId<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">MESSAGE<\/span><span class=\"dl\">\"<\/span> <span class=\"o\">|<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">BREADCRUMB<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">role<\/span><span class=\"p\">?:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">user<\/span><span class=\"dl\">\"<\/span> <span class=\"o\">|<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">assistant<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">title<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">data<\/span><span class=\"p\">?:<\/span> <span class=\"nb\">Record<\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">string<\/span><span class=\"p\">,<\/span> <span class=\"kr\">any<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">expanded<\/span><span class=\"p\">:<\/span> <span class=\"nx\">boolean<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">timestamp<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">createdAtMs<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">status<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">IN_PROGRESS<\/span><span class=\"dl\">\"<\/span> <span class=\"o\">|<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">DONE<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">isHidden<\/span><span class=\"p\">:<\/span> <span class=\"nx\">boolean<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kr\">interface<\/span> <span class=\"nx\">Log<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">id<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">timestamp<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">direction<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">eventName<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">data<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">expanded<\/span><span class=\"p\">:<\/span> <span class=\"nx\">boolean<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">type<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kr\">interface<\/span> <span class=\"nx\">ServerEvent<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">type<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">event_id<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">item_id<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">transcript<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">delta<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">session<\/span><span class=\"p\">?:<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">id<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">};<\/span>\n  <span class=\"nl\">item<\/span><span class=\"p\">?:<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">id<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">object<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">type<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">status<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">name<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">arguments<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">role<\/span><span class=\"p\">?:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">user<\/span><span class=\"dl\">\"<\/span> <span class=\"o\">|<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">assistant<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">content<\/span><span class=\"p\">?:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"kd\">type<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">transcript<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">text<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}[];<\/span>\n  <span class=\"p\">};<\/span>\n  <span class=\"nl\">response<\/span><span class=\"p\">?:<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">output<\/span><span class=\"p\">?:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"kd\">type<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">name<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">arguments<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">call_id<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}[];<\/span>\n    <span class=\"nl\">status_details<\/span><span class=\"p\">?:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">error<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">};<\/span>\n  <span class=\"p\">};<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kr\">interface<\/span> <span class=\"nx\">LoggedEvent<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">id<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">direction<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">client<\/span><span class=\"dl\">\"<\/span> <span class=\"o\">|<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">server<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">expanded<\/span><span class=\"p\">:<\/span> <span class=\"nx\">boolean<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">timestamp<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">eventName<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">eventData<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Record<\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">string<\/span><span class=\"p\">,<\/span> <span class=\"kr\">any<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">;<\/span> <span class=\"c1\">\/\/ can have arbitrary objects logged<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kr\">interface<\/span> <span class=\"nx\">Activity<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">points<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">description<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kr\">interface<\/span> <span class=\"nx\">Routine<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">name<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">activities<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Activity<\/span><span class=\"p\">[];<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<blockquote>\n<p>\u0645\u06a9\u0627\u0646 \u0641\u0627\u06cc\u0644: <code>app\/types.ts<\/code><\/p>\n<\/blockquote>\n<h2><span class=\"ez-toc-section\" id=\"%D9%86%D9%85%D8%A7%DB%8C%D9%86%D8%AF%DA%AF%D8%A7%D9%86_%D9%87%D9%88%D8%B4_%D9%85%D8%B5%D9%86%D9%88%D8%B9%DB%8C_%D9%88%DB%8C\"><\/span>\n<p>  \u0646\u0645\u0627\u06cc\u0646\u062f\u06af\u0627\u0646 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u0648\u06cc<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0628\u06cc\u0627\u06cc\u06cc\u062f \u0628\u0627 \u0686\u06cc\u0632\u06cc \u0633\u0627\u062f\u0647 \u0634\u0631\u0648\u0639 \u06a9\u0646\u06cc\u0645: <code>Greeter Agent<\/code>\u0628\u0634\u0631<\/p>\n<h3><span class=\"ez-toc-section\" id=\"%DA%AF%D9%88%D8%B1\"><\/span>\n<p>  \u06af\u0648\u0631<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0627\u06cc\u0646 \u0646\u0645\u0627\u06cc\u0646\u062f\u0647 \u0645\u0633\u0626\u0648\u0644 \u062a\u0628\u0631\u06cc\u06a9 \u0628\u0647 \u06a9\u0627\u0631\u0628\u0631 \u0648 \u0627\u0631\u0627\u0626\u0647 \u06cc\u06a9 \u062a\u062c\u0631\u0628\u0647 \u062e\u0648\u0634 \u0622\u0645\u062f\u06cc\u062f \u0634\u062e\u0635\u06cc \u0627\u0633\u062a.<br \/>\u0627\u06cc\u0646 \u062f\u0633\u062a\u0631\u0633\u06cc \u0628\u0647 \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u067e\u0631\u0648\u0641\u0627\u06cc\u0644 \u06a9\u0627\u0631\u0628\u0631 \u060c \u0639\u0627\u062f\u0627\u062a \u060c \u062a\u06a9\u0645\u06cc\u0644 \u060c \u0627\u0645\u062a\u06cc\u0627\u0632 \u060c \u062e\u0637 \u0648 \u0641\u0639\u0627\u0644\u06cc\u062a \u0647\u0627\u06cc \u0627\u062e\u06cc\u0631 \u062f\u0633\u062a\u0631\u0633\u06cc \u062f\u0627\u0631\u062f.<br \/>\u067e\u0633 \u0627\u0632 \u0627\u062a\u0645\u0627\u0645 \u060c \u06a9\u0646\u062a\u0631\u0644 \u0628\u0647 <code>General Agent<\/code>\u0628\u0634\u0631<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight typescript\"><code><span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">AgentConfig<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/app\/types<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">getUserDataForAgent<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/app\/utils\/agentDatabaseTools<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">injectTransferTools<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/utils<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">general<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/general<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"kd\">const<\/span> <span class=\"nx\">greeter<\/span><span class=\"p\">:<\/span> <span class=\"nx\">AgentConfig<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n  <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">greeter<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n  <span class=\"na\">publicDescription<\/span><span class=\"p\">:<\/span>\n    <span class=\"dl\">\"<\/span><span class=\"s2\">A friendly welcome agent that greets users and provides a personalized welcome experience.<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n  <span class=\"na\">instructions<\/span><span class=\"p\">:<\/span> <span class=\"s2\">`\n# Personality\nYou are Wei, a warm and friendly wellness buddy. Your role is to greet users with personalized welcome messages that acknowledge their progress, habits, and achievements. Your tone is encouraging, positive, and conversational. \n... omitted for brevity. \n`<\/span><span class=\"p\">,<\/span>\n  <span class=\"na\">tools<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span>\n    <span class=\"p\">{<\/span>\n      <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">function<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getUserData<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">description<\/span><span class=\"p\">:<\/span>\n        <span class=\"dl\">\"<\/span><span class=\"s2\">Get the user's profile information, habits, completions, rewards, points, streak, and recent activity.<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{},<\/span>\n        <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[],<\/span>\n      <span class=\"p\">},<\/span>\n    <span class=\"p\">},<\/span>\n  <span class=\"p\">],<\/span>\n  <span class=\"na\">toolLogic<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">getUserData<\/span><span class=\"p\">:<\/span> <span class=\"k\">async <\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">userData<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">getUserDataForAgent<\/span><span class=\"p\">();<\/span>\n        <span class=\"k\">return<\/span> <span class=\"nx\">userData<\/span><span class=\"p\">;<\/span>\n      <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Error getting user data for greeter agent:<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n        <span class=\"k\">return<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">error<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Failed to retrieve user data. Please try again later.<\/span><span class=\"dl\">\"<\/span>\n        <span class=\"p\">};<\/span>\n      <span class=\"p\">}<\/span>\n    <span class=\"p\">},<\/span>\n  <span class=\"p\">},<\/span>\n  <span class=\"na\">downstreamAgents<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span><span class=\"nx\">general<\/span><span class=\"p\">],<\/span>\n<span class=\"p\">};<\/span>\n\n<span class=\"kd\">const<\/span> <span class=\"nx\">agents<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">injectTransferTools<\/span><span class=\"p\">([<\/span><span class=\"nx\">greeter<\/span><span class=\"p\">,<\/span> <span class=\"nx\">general<\/span><span class=\"p\">]);<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"nx\">agents<\/span><span class=\"p\">;<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<blockquote>\n<p>\u0645\u06a9\u0627\u0646 \u0641\u0627\u06cc\u0644: <code>app\/agentConfigs\/greeter.ts<\/code><\/p>\n<\/blockquote>\n<h3><span class=\"ez-toc-section\" id=\"%D9%86%D9%85%D8%A7%DB%8C%D9%86%D8%AF%D9%87_%D8%B9%D9%85%D9%88%D9%85%DB%8C\"><\/span>\n<p>  \u0646\u0645\u0627\u06cc\u0646\u062f\u0647 \u0639\u0645\u0648\u0645\u06cc<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0627\u06cc\u0646 \u0646\u0645\u0627\u06cc\u0646\u062f\u0647 \u0645\u0633\u0626\u0648\u0644 \u0648\u0638\u0627\u06cc\u0641 \u0639\u0645\u0648\u0645\u06cc \u0645\u0627\u0646\u0646\u062f \u067e\u0627\u0633\u062e \u062f\u0627\u062f\u0646 \u0628\u0647 \u0633\u0624\u0627\u0644\u0627\u062a \u060c \u0627\u0631\u0627\u0626\u0647 \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u060c \u0639\u0644\u0627\u0645\u062a \u06af\u0630\u0627\u0631\u06cc \u0639\u0627\u062f\u0627\u062a \u0628\u0647 \u0635\u0648\u0631\u062a \u06a9\u0627\u0645\u0644 \u0648 \u063a\u06cc\u0631\u0647 \u0627\u0633\u062a.<br \/>\u0627\u06cc\u0646 \u062f\u0633\u062a\u0631\u0633\u06cc \u0628\u0647 \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u067e\u0631\u0648\u0641\u0627\u06cc\u0644 \u06a9\u0627\u0631\u0628\u0631 \u060c \u0639\u0627\u062f\u0627\u062a \u060c \u062a\u06a9\u0645\u06cc\u0644 \u060c \u0627\u0645\u062a\u06cc\u0627\u0632 \u060c \u062e\u0637 \u0648 \u0641\u0639\u0627\u0644\u06cc\u062a \u0647\u0627\u06cc \u0627\u062e\u06cc\u0631 \u062f\u0633\u062a\u0631\u0633\u06cc \u062f\u0627\u0631\u062f.<br \/>\u0645\u06cc \u062a\u0648\u0627\u0646\u062f \u062a\u0645\u0627\u0633 \u0628\u06af\u06cc\u0631\u062f: <code>getUserData<\/code>\u0628\u0627 <code>completeHabit<\/code>\u0628\u0634\u0631<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight typescript\"><code><span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">AgentConfig<\/span><span class=\"p\">,<\/span> <span class=\"nx\">TranscriptItem<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/app\/types<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">getUserDataForAgent<\/span><span class=\"p\">,<\/span> <span class=\"nx\">completeHabit<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/app\/utils\/agentDatabaseTools<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kd\">const<\/span> <span class=\"nx\">general<\/span><span class=\"p\">:<\/span> <span class=\"nx\">AgentConfig<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">general<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">publicDescription<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Your general wellbeing assistant. I can help you track habits, manage rewards, and provide encouragement.<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">instructions<\/span><span class=\"p\">:<\/span> <span class=\"s2\">`\n# Personality and Tone\nYou're Wei, a friendly, motivating, and supportive wellbeing assistant who helps users track their habits, earn points, and redeem rewards. Your personality is warm and encouraging, but also straightforward and helpful. You should be conversational but concise.\n... omitted for brevity.\n`<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">tools<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span>\n        <span class=\"p\">{<\/span>\n            <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">function<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n            <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getUserData<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n            <span class=\"na\">description<\/span><span class=\"p\">:<\/span>\n                <span class=\"dl\">\"<\/span><span class=\"s2\">Get the user's profile information, habits, completions, rewards, points, streak, and recent activity.<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n            <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n                <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n                <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{},<\/span>\n                <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[],<\/span>\n            <span class=\"p\">},<\/span>\n        <span class=\"p\">},<\/span>\n        <span class=\"p\">{<\/span>\n            <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">function<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n            <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">completeHabit<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n            <span class=\"na\">description<\/span><span class=\"p\">:<\/span>\n                <span class=\"dl\">\"<\/span><span class=\"s2\">Mark a habit as complete, award points to the user, and return the updated points balance.<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n            <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n                <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n                <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n                    <span class=\"na\">habitId<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n                        <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">string<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n                        <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">The ID of the habit to complete<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n                    <span class=\"p\">},<\/span>\n                <span class=\"p\">},<\/span>\n                <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">habitId<\/span><span class=\"dl\">\"<\/span><span class=\"p\">],<\/span>\n            <span class=\"p\">},<\/span>\n        <span class=\"p\">},<\/span>\n    <span class=\"p\">],<\/span>\n    <span class=\"na\">toolLogic<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">getUserData<\/span><span class=\"p\">:<\/span> <span class=\"k\">async <\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n            <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n                <span class=\"kd\">const<\/span> <span class=\"nx\">userData<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">getUserDataForAgent<\/span><span class=\"p\">();<\/span>\n                <span class=\"k\">return<\/span> <span class=\"nx\">userData<\/span><span class=\"p\">;<\/span>\n            <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n                <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Error getting user data for agent:<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n                <span class=\"k\">return<\/span> <span class=\"p\">{<\/span>\n                    <span class=\"na\">error<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Failed to retrieve user data. Please try again later.<\/span><span class=\"dl\">\"<\/span>\n                <span class=\"p\">};<\/span>\n            <span class=\"p\">}<\/span>\n        <span class=\"p\">},<\/span>\n        <span class=\"na\">completeHabit<\/span><span class=\"p\">:<\/span> <span class=\"k\">async <\/span><span class=\"p\">({<\/span> <span class=\"nx\">habitId<\/span> <span class=\"p\">})<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n            <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n                <span class=\"kd\">const<\/span> <span class=\"nx\">result<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">completeHabit<\/span><span class=\"p\">(<\/span><span class=\"nx\">habitId<\/span><span class=\"p\">);<\/span>\n                <span class=\"k\">return<\/span> <span class=\"nx\">result<\/span><span class=\"p\">;<\/span>\n            <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n                <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Error completing habit:<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n                <span class=\"k\">return<\/span> <span class=\"p\">{<\/span>\n                    <span class=\"na\">success<\/span><span class=\"p\">:<\/span> <span class=\"kc\">false<\/span><span class=\"p\">,<\/span>\n                    <span class=\"na\">message<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Failed to complete habit. Please try again later.<\/span><span class=\"dl\">\"<\/span>\n                <span class=\"p\">};<\/span>\n            <span class=\"p\">}<\/span>\n        <span class=\"p\">}<\/span>\n    <span class=\"p\">},<\/span>\n<span class=\"p\">};<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"nx\">general<\/span><span class=\"p\">;<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"%D9%86%D9%85%D8%A7%DB%8C%D9%86%D8%AF%D9%87_%D9%85%D8%AF%DB%8C%D8%B1_%D9%BE%D8%A7%D8%AF%D8%A7%D8%B4\"><\/span>\n<p>  \u0646\u0645\u0627\u06cc\u0646\u062f\u0647 \u0645\u062f\u06cc\u0631 \u067e\u0627\u062f\u0627\u0634<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0627\u06cc\u0646 \u0646\u0645\u0627\u06cc\u0646\u062f\u0647 \u0645\u0633\u0626\u0648\u0644 \u0645\u062f\u06cc\u0631\u06cc\u062a \u062c\u0648\u0627\u06cc\u0632 \u0627\u0633\u062a.<br \/>\u0627\u06cc\u0646 \u062f\u0633\u062a\u0631\u0633\u06cc \u0628\u0647 \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u067e\u0631\u0648\u0641\u0627\u06cc\u0644 \u06a9\u0627\u0631\u0628\u0631 \u060c \u0639\u0627\u062f\u0627\u062a \u060c \u062a\u06a9\u0645\u06cc\u0644 \u060c \u0627\u0645\u062a\u06cc\u0627\u0632 \u060c \u062e\u0637 \u0648 \u0641\u0639\u0627\u0644\u06cc\u062a \u0647\u0627\u06cc \u0627\u062e\u06cc\u0631 \u062f\u0633\u062a\u0631\u0633\u06cc \u062f\u0627\u0631\u062f.<br \/>\u0645\u06cc \u062a\u0648\u0627\u0646\u062f \u062a\u0645\u0627\u0633 \u0628\u06af\u06cc\u0631\u062f: <code>getUserStats<\/code>\u0628\u0627 <code>getUserRewards<\/code>\u0628\u0627 <code>getRewardRedemptions<\/code>\u0628\u0627 <code>redeemReward<\/code>\u0628\u0634\u0631<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight typescript\"><code><span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">AgentConfig<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/app\/types<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">getUserStats<\/span><span class=\"p\">,<\/span> <span class=\"nx\">getUserRewards<\/span><span class=\"p\">,<\/span> <span class=\"nx\">getRewardRedemptions<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/app\/utils\/agentDatabaseTools<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">DATABASE_NAME<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/lib\/config<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">DATABASE_VERSION<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/lib\/config<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">openDB<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">idb<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"kd\">const<\/span> <span class=\"nx\">rewardsManager<\/span><span class=\"p\">:<\/span> <span class=\"nx\">AgentConfig<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n  <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">rewardsManager<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n  <span class=\"na\">publicDescription<\/span><span class=\"p\">:<\/span>\n    <span class=\"dl\">\"<\/span><span class=\"s2\">Displays available rewards and processes point redemptions.<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n  <span class=\"na\">instructions<\/span><span class=\"p\">:<\/span> <span class=\"s2\">`\n# Personality and Tone\n## Identity\nYou\\'re Wei\\'s cheerful curator\u2014fun-loving, a bit mischievous, who makes rewards feel special.\n... omitted for brevity.\n`<\/span><span class=\"p\">,<\/span>\n  <span class=\"na\">tools<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span>\n    <span class=\"p\">{<\/span>\n      <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">function<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getUserStats<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Get the user's current points balance and streak information<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{},<\/span>\n        <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[],<\/span>\n      <span class=\"p\">},<\/span>\n    <span class=\"p\">},<\/span>\n    <span class=\"p\">{<\/span>\n      <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">function<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getUserRewards<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Get the list of rewards available to the user<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{},<\/span>\n        <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[],<\/span>\n      <span class=\"p\">},<\/span>\n    <span class=\"p\">},<\/span>\n    <span class=\"p\">{<\/span>\n      <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">function<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getRewardRedemptions<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Get the user's past reward redemptions<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">daysAgo<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n            <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">number<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n            <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Get redemptions from this many days ago (default 30)<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"p\">},<\/span>\n        <span class=\"p\">},<\/span>\n        <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[],<\/span>\n      <span class=\"p\">},<\/span>\n    <span class=\"p\">},<\/span>\n    <span class=\"p\">{<\/span>\n      <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">function<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">redeemReward<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Redeem a reward for the user, deducting points from their balance<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">rewardId<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n            <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">string<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n            <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">The ID of the reward to redeem<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"p\">},<\/span>\n        <span class=\"p\">},<\/span>\n        <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">rewardId<\/span><span class=\"dl\">\"<\/span><span class=\"p\">],<\/span>\n      <span class=\"p\">},<\/span>\n    <span class=\"p\">},<\/span>\n  <span class=\"p\">],<\/span>\n  <span class=\"na\">toolLogic<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">getUserStats<\/span><span class=\"p\">:<\/span> <span class=\"k\">async <\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">stats<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">getUserStats<\/span><span class=\"p\">();<\/span>\n        <span class=\"k\">return<\/span> <span class=\"nx\">stats<\/span><span class=\"p\">;<\/span>\n      <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Error getting user stats:<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n        <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> <span class=\"na\">error<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Failed to retrieve user stats<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">};<\/span>\n      <span class=\"p\">}<\/span>\n    <span class=\"p\">},<\/span>\n    <span class=\"na\">getUserRewards<\/span><span class=\"p\">:<\/span> <span class=\"k\">async <\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">rewards<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">getUserRewards<\/span><span class=\"p\">();<\/span>\n        <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">rewards<\/span> <span class=\"p\">};<\/span>\n      <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Error getting user rewards:<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n        <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> <span class=\"na\">error<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Failed to retrieve rewards<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">};<\/span>\n      <span class=\"p\">}<\/span>\n    <span class=\"p\">},<\/span>\n    <span class=\"na\">getRewardRedemptions<\/span><span class=\"p\">:<\/span> <span class=\"k\">async <\/span><span class=\"p\">({<\/span> <span class=\"nx\">daysAgo<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">30<\/span> <span class=\"p\">})<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">redemptions<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">getRewardRedemptions<\/span><span class=\"p\">(<\/span><span class=\"nx\">daysAgo<\/span><span class=\"p\">);<\/span>\n        <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">redemptions<\/span> <span class=\"p\">};<\/span>\n      <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Error getting reward redemptions:<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n        <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> <span class=\"na\">error<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Failed to retrieve reward redemptions<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">};<\/span>\n      <span class=\"p\">}<\/span>\n    <span class=\"p\">},<\/span>\n    <span class=\"na\">redeemReward<\/span><span class=\"p\">:<\/span> <span class=\"k\">async <\/span><span class=\"p\">({<\/span> <span class=\"nx\">rewardId<\/span> <span class=\"p\">})<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n        <span class=\"c1\">\/\/ We need to use the database context directly since redeemReward isn't exported<\/span>\n        <span class=\"c1\">\/\/ First get the database from the context<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">db<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">openDB<\/span><span class=\"p\">(<\/span><span class=\"nx\">DATABASE_NAME<\/span><span class=\"p\">,<\/span> <span class=\"nx\">DATABASE_VERSION<\/span><span class=\"p\">);<\/span>\n\n        <span class=\"c1\">\/\/ Get the reward details<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">reward<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">get<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">rewards<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">rewardId<\/span><span class=\"p\">);<\/span>\n        <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">reward<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n          <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">close<\/span><span class=\"p\">();<\/span>\n          <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> \n            <span class=\"na\">success<\/span><span class=\"p\">:<\/span> <span class=\"kc\">false<\/span><span class=\"p\">,<\/span> \n            <span class=\"na\">message<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Reward not found<\/span><span class=\"dl\">\"<\/span> \n          <span class=\"p\">};<\/span>\n        <span class=\"p\">}<\/span>\n\n        <span class=\"c1\">\/\/ Get the user's current points<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">userData<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">get<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">user<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">default<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n        <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">userData<\/span> <span class=\"o\">||<\/span> <span class=\"nx\">userData<\/span><span class=\"p\">.<\/span><span class=\"nx\">points<\/span> <span class=\"o\">&lt;<\/span> <span class=\"nx\">reward<\/span><span class=\"p\">.<\/span><span class=\"nx\">cost<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n          <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">close<\/span><span class=\"p\">();<\/span>\n          <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> \n            <span class=\"na\">success<\/span><span class=\"p\">:<\/span> <span class=\"kc\">false<\/span><span class=\"p\">,<\/span> \n            <span class=\"na\">message<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Not enough points to redeem this reward<\/span><span class=\"dl\">\"<\/span> \n          <span class=\"p\">};<\/span>\n        <span class=\"p\">}<\/span>\n\n        <span class=\"c1\">\/\/ Create redemption record<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">redemptionId<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">`redemption_<\/span><span class=\"p\">${<\/span><span class=\"nb\">Date<\/span><span class=\"p\">.<\/span><span class=\"nf\">now<\/span><span class=\"p\">()}<\/span><span class=\"s2\">_<\/span><span class=\"p\">${<\/span><span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">random<\/span><span class=\"p\">().<\/span><span class=\"nf\">toString<\/span><span class=\"p\">(<\/span><span class=\"mi\">36<\/span><span class=\"p\">).<\/span><span class=\"nf\">substr<\/span><span class=\"p\">(<\/span><span class=\"mi\">2<\/span><span class=\"p\">,<\/span> <span class=\"mi\">9<\/span><span class=\"p\">)}<\/span><span class=\"s2\">`<\/span><span class=\"p\">;<\/span>\n        <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">add<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">rewardRedemptions<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">id<\/span><span class=\"p\">:<\/span> <span class=\"nx\">redemptionId<\/span><span class=\"p\">,<\/span>\n          <span class=\"nx\">rewardId<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">redeemedAt<\/span><span class=\"p\">:<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(),<\/span>\n          <span class=\"na\">cost<\/span><span class=\"p\">:<\/span> <span class=\"nx\">reward<\/span><span class=\"p\">.<\/span><span class=\"nx\">cost<\/span>\n        <span class=\"p\">});<\/span>\n\n        <span class=\"c1\">\/\/ Update user points<\/span>\n        <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">put<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">user<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span>\n          <span class=\"p\">...<\/span><span class=\"nx\">userData<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">points<\/span><span class=\"p\">:<\/span> <span class=\"nx\">userData<\/span><span class=\"p\">.<\/span><span class=\"nx\">points<\/span> <span class=\"o\">-<\/span> <span class=\"nx\">reward<\/span><span class=\"p\">.<\/span><span class=\"nx\">cost<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">lastActive<\/span><span class=\"p\">:<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">()<\/span>\n        <span class=\"p\">});<\/span>\n\n        <span class=\"c1\">\/\/ Get updated user stats<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">updatedUserData<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">get<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">user<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">default<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n        <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">close<\/span><span class=\"p\">();<\/span>\n\n        <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> \n          <span class=\"na\">success<\/span><span class=\"p\">:<\/span> <span class=\"kc\">true<\/span><span class=\"p\">,<\/span> \n          <span class=\"na\">message<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Reward redeemed successfully<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> \n          <span class=\"na\">newPoints<\/span><span class=\"p\">:<\/span> <span class=\"nx\">updatedUserData<\/span><span class=\"p\">?.<\/span><span class=\"nx\">points<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">0<\/span>\n        <span class=\"p\">};<\/span>\n      <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Error redeeming reward:<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n        <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> <span class=\"na\">success<\/span><span class=\"p\">:<\/span> <span class=\"kc\">false<\/span><span class=\"p\">,<\/span> <span class=\"na\">message<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Failed to redeem reward<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">};<\/span>\n      <span class=\"p\">}<\/span>\n    <span class=\"p\">},<\/span>\n  <span class=\"p\">},<\/span>\n<span class=\"p\">};<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"nx\">rewardsManager<\/span><span class=\"p\">;<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<blockquote>\n<p>\u0645\u06a9\u0627\u0646 \u0641\u0627\u06cc\u0644: <code>app\/agentConfigs\/wellbeing\/rewards-manager.ts<\/code><\/p>\n<\/blockquote>\n<h3><span class=\"ez-toc-section\" id=\"%D8%B9%D8%A7%D9%85%D9%84_%D9%85%D8%A7%D8%B4%DB%8C%D9%86_%D8%AD%D8%B3%D8%A7%D8%A8\"><\/span>\n<p>  \u0639\u0627\u0645\u0644 \u0645\u0627\u0634\u06cc\u0646 \u062d\u0633\u0627\u0628<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0627\u06cc\u0646 \u0646\u0645\u0627\u06cc\u0646\u062f\u0647 \u0645\u0633\u0626\u0648\u0644 \u0645\u062d\u0627\u0633\u0628\u0647 \u0627\u0645\u062a\u06cc\u0627\u0632 \u0627\u0633\u062a.<br \/>\u0627\u06cc\u0646 \u062f\u0633\u062a\u0631\u0633\u06cc \u0628\u0647 \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u067e\u0631\u0648\u0641\u0627\u06cc\u0644 \u06a9\u0627\u0631\u0628\u0631 \u060c \u0639\u0627\u062f\u0627\u062a \u060c \u062a\u06a9\u0645\u06cc\u0644 \u060c \u0627\u0645\u062a\u06cc\u0627\u0632 \u060c \u062e\u0637 \u0648 \u0641\u0639\u0627\u0644\u06cc\u062a \u0647\u0627\u06cc \u0627\u062e\u06cc\u0631 \u062f\u0633\u062a\u0631\u0633\u06cc \u062f\u0627\u0631\u062f.<br \/>\u0645\u06cc \u062a\u0648\u0627\u0646\u062f \u062a\u0645\u0627\u0633 \u0628\u06af\u06cc\u0631\u062f: <code>getUserStats<\/code>\u0628\u0627 <code>getHabitCompletions<\/code>\u0628\u0627 <code>calculateBonusPoints<\/code>\u0628\u0634\u0631<br \/>\u0628\u0627\u0632\u06af\u0634\u062a: <em>\u067e\u0627\u06cc\u0647<\/em>\u0628\u0627 <em>\u0632\u0646\u062c\u06cc\u0631\u0647 \u06a9\u0631\u0628\u0646<\/em>\u0628\u0627 <em>\u0631\u0632\u0645\u0646\u062f\u0647<\/em>\u0628\u0627 <em>\u0642\u0648\u0627\u0645<\/em>\u0628\u0627 <em>\u06a9\u0644\u0646\u06af<\/em>\u0628\u0627 <em>\u06a9\u0644\u06cc\u0627\u062a<\/em>\u0628\u0627 <em>\u062a\u0648\u0636\u06cc\u062d<\/em>: <code>${basePoints} base + ${chainBonus} chain + ${streakBonus} streak + ${consistencyBonus} consistency = ${totalPoints} total<\/code>\u0628\u0634\u0631<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight typescript\"><code><span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">AgentConfig<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/app\/types<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">getUserStats<\/span><span class=\"p\">,<\/span> <span class=\"nx\">getHabitCompletions<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/app\/utils\/agentDatabaseTools<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"kd\">const<\/span> <span class=\"nx\">pointsCalculator<\/span><span class=\"p\">:<\/span> <span class=\"nx\">AgentConfig<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">pointsCalculator<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">publicDescription<\/span><span class=\"p\">:<\/span>\n      <span class=\"dl\">\"<\/span><span class=\"s2\">Handles computing bonus points (chain, load, gradient) on top of the base award.<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">instructions<\/span><span class=\"p\">:<\/span>\n      <span class=\"s2\">`\n      # Personality and Tone\n      ... omitted for brevity.\n`<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">tools<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span>\n      <span class=\"p\">{<\/span>\n        <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">function<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getUserStats<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Get the user's current points balance and streak information<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{},<\/span>\n          <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[],<\/span>\n        <span class=\"p\">},<\/span>\n      <span class=\"p\">},<\/span>\n      <span class=\"p\">{<\/span>\n        <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">function<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getHabitCompletions<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Get the user's habit completion history for calculating bonuses<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n            <span class=\"na\">daysAgo<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n              <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">number<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n              <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Get completions from this many days ago (default 30)<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n            <span class=\"p\">},<\/span>\n          <span class=\"p\">},<\/span>\n          <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[],<\/span>\n        <span class=\"p\">},<\/span>\n      <span class=\"p\">},<\/span>\n      <span class=\"p\">{<\/span>\n        <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">function<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">calculateBonusPoints<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Calculate bonus points based on streak, consistency, and habit difficulty<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n            <span class=\"na\">habitId<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n              <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">string<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n              <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">The ID of the habit to calculate bonuses for<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n            <span class=\"p\">},<\/span>\n            <span class=\"na\">basePoints<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n              <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">number<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n              <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">The base points awarded for this habit<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n            <span class=\"p\">},<\/span>\n          <span class=\"p\">},<\/span>\n          <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">habitId<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">basePoints<\/span><span class=\"dl\">\"<\/span><span class=\"p\">],<\/span>\n        <span class=\"p\">},<\/span>\n      <span class=\"p\">},<\/span>\n    <span class=\"p\">],<\/span>\n    <span class=\"na\">toolLogic<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">getUserStats<\/span><span class=\"p\">:<\/span> <span class=\"k\">async <\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n          <span class=\"kd\">const<\/span> <span class=\"nx\">stats<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">getUserStats<\/span><span class=\"p\">();<\/span>\n          <span class=\"k\">return<\/span> <span class=\"nx\">stats<\/span><span class=\"p\">;<\/span>\n        <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n          <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Error getting user stats:<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n          <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> <span class=\"na\">error<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Failed to retrieve user stats<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">};<\/span>\n        <span class=\"p\">}<\/span>\n      <span class=\"p\">},<\/span>\n      <span class=\"na\">getHabitCompletions<\/span><span class=\"p\">:<\/span> <span class=\"k\">async <\/span><span class=\"p\">({<\/span> <span class=\"nx\">daysAgo<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">30<\/span> <span class=\"p\">})<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n          <span class=\"kd\">const<\/span> <span class=\"nx\">completions<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">getHabitCompletions<\/span><span class=\"p\">(<\/span><span class=\"nx\">daysAgo<\/span><span class=\"p\">);<\/span>\n          <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">completions<\/span> <span class=\"p\">};<\/span>\n        <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n          <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Error getting habit completions:<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n          <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> <span class=\"na\">error<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Failed to retrieve habit completions<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">};<\/span>\n        <span class=\"p\">}<\/span>\n      <span class=\"p\">},<\/span>\n      <span class=\"na\">calculateBonusPoints<\/span><span class=\"p\">:<\/span> <span class=\"k\">async <\/span><span class=\"p\">({<\/span> <span class=\"nx\">habitId<\/span><span class=\"p\">,<\/span> <span class=\"nx\">basePoints<\/span> <span class=\"p\">})<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n          <span class=\"c1\">\/\/ Get user's habit completions to calculate streaks and consistency<\/span>\n          <span class=\"kd\">const<\/span> <span class=\"nx\">completions<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">getHabitCompletions<\/span><span class=\"p\">(<\/span><span class=\"mi\">30<\/span><span class=\"p\">);<\/span>\n\n          <span class=\"c1\">\/\/ Filter completions for this specific habit<\/span>\n          <span class=\"kd\">const<\/span> <span class=\"nx\">habitCompletions<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">completions<\/span><span class=\"p\">.<\/span><span class=\"nf\">filter<\/span><span class=\"p\">(<\/span>\n            <span class=\"nx\">completion<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">completion<\/span><span class=\"p\">.<\/span><span class=\"nx\">habitId<\/span> <span class=\"o\">===<\/span> <span class=\"nx\">habitId<\/span>\n          <span class=\"p\">);<\/span>\n\n          <span class=\"c1\">\/\/ Get user stats for streak information<\/span>\n          <span class=\"kd\">const<\/span> <span class=\"nx\">stats<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">getUserStats<\/span><span class=\"p\">();<\/span>\n\n          <span class=\"c1\">\/\/ Calculate chain bonus (consecutive days)<\/span>\n          <span class=\"kd\">let<\/span> <span class=\"nx\">chainBonus<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span><span class=\"p\">;<\/span>\n          <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">habitCompletions<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n            <span class=\"c1\">\/\/ Sort by date, newest first<\/span>\n            <span class=\"kd\">const<\/span> <span class=\"nx\">sortedCompletions<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[...<\/span><span class=\"nx\">habitCompletions<\/span><span class=\"p\">].<\/span><span class=\"nf\">sort<\/span><span class=\"p\">(<\/span>\n              <span class=\"p\">(<\/span><span class=\"nx\">a<\/span><span class=\"p\">,<\/span> <span class=\"nx\">b<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(<\/span><span class=\"nx\">b<\/span><span class=\"p\">.<\/span><span class=\"nx\">completedAt<\/span><span class=\"p\">).<\/span><span class=\"nf\">getTime<\/span><span class=\"p\">()<\/span> <span class=\"o\">-<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(<\/span><span class=\"nx\">a<\/span><span class=\"p\">.<\/span><span class=\"nx\">completedAt<\/span><span class=\"p\">).<\/span><span class=\"nf\">getTime<\/span><span class=\"p\">()<\/span>\n            <span class=\"p\">);<\/span>\n\n            <span class=\"c1\">\/\/ Check if there was a completion yesterday<\/span>\n            <span class=\"kd\">const<\/span> <span class=\"nx\">yesterday<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">();<\/span>\n            <span class=\"nx\">yesterday<\/span><span class=\"p\">.<\/span><span class=\"nf\">setDate<\/span><span class=\"p\">(<\/span><span class=\"nx\">yesterday<\/span><span class=\"p\">.<\/span><span class=\"nf\">getDate<\/span><span class=\"p\">()<\/span> <span class=\"o\">-<\/span> <span class=\"mi\">1<\/span><span class=\"p\">);<\/span>\n            <span class=\"nx\">yesterday<\/span><span class=\"p\">.<\/span><span class=\"nf\">setHours<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"mi\">0<\/span><span class=\"p\">);<\/span>\n\n            <span class=\"kd\">const<\/span> <span class=\"nx\">yesterdayCompletion<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">sortedCompletions<\/span><span class=\"p\">.<\/span><span class=\"nf\">find<\/span><span class=\"p\">(<\/span><span class=\"nx\">completion<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n              <span class=\"kd\">const<\/span> <span class=\"nx\">completionDate<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(<\/span><span class=\"nx\">completion<\/span><span class=\"p\">.<\/span><span class=\"nx\">completedAt<\/span><span class=\"p\">);<\/span>\n              <span class=\"nx\">completionDate<\/span><span class=\"p\">.<\/span><span class=\"nf\">setHours<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"mi\">0<\/span><span class=\"p\">);<\/span>\n              <span class=\"k\">return<\/span> <span class=\"nx\">completionDate<\/span><span class=\"p\">.<\/span><span class=\"nf\">getTime<\/span><span class=\"p\">()<\/span> <span class=\"o\">===<\/span> <span class=\"nx\">yesterday<\/span><span class=\"p\">.<\/span><span class=\"nf\">getTime<\/span><span class=\"p\">();<\/span>\n            <span class=\"p\">});<\/span>\n\n            <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">yesterdayCompletion<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n              <span class=\"nx\">chainBonus<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">min<\/span><span class=\"p\">(<\/span><span class=\"mi\">3<\/span><span class=\"p\">,<\/span> <span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">floor<\/span><span class=\"p\">(<\/span><span class=\"nx\">habitCompletions<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">\/<\/span> <span class=\"mi\">2<\/span><span class=\"p\">));<\/span>\n            <span class=\"p\">}<\/span>\n          <span class=\"p\">}<\/span>\n\n          <span class=\"c1\">\/\/ Calculate streak bonus<\/span>\n          <span class=\"kd\">const<\/span> <span class=\"nx\">streakBonus<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">min<\/span><span class=\"p\">(<\/span><span class=\"mi\">5<\/span><span class=\"p\">,<\/span> <span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">floor<\/span><span class=\"p\">(<\/span><span class=\"nx\">stats<\/span><span class=\"p\">.<\/span><span class=\"nx\">streakDays<\/span> <span class=\"o\">\/<\/span> <span class=\"mi\">3<\/span><span class=\"p\">));<\/span>\n\n          <span class=\"c1\">\/\/ Calculate consistency bonus (based on completion frequency)<\/span>\n          <span class=\"kd\">const<\/span> <span class=\"nx\">today<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">();<\/span>\n          <span class=\"nx\">today<\/span><span class=\"p\">.<\/span><span class=\"nf\">setHours<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"mi\">0<\/span><span class=\"p\">);<\/span>\n          <span class=\"kd\">const<\/span> <span class=\"nx\">lastWeekCompletions<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">completions<\/span><span class=\"p\">.<\/span><span class=\"nf\">filter<\/span><span class=\"p\">(<\/span><span class=\"nx\">completion<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n            <span class=\"kd\">const<\/span> <span class=\"nx\">completionDate<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(<\/span><span class=\"nx\">completion<\/span><span class=\"p\">.<\/span><span class=\"nx\">completedAt<\/span><span class=\"p\">);<\/span>\n            <span class=\"kd\">const<\/span> <span class=\"nx\">daysDiff<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">floor<\/span><span class=\"p\">((<\/span><span class=\"nx\">today<\/span><span class=\"p\">.<\/span><span class=\"nf\">getTime<\/span><span class=\"p\">()<\/span> <span class=\"o\">-<\/span> <span class=\"nx\">completionDate<\/span><span class=\"p\">.<\/span><span class=\"nf\">getTime<\/span><span class=\"p\">())<\/span> <span class=\"o\">\/<\/span> <span class=\"p\">(<\/span><span class=\"mi\">1000<\/span> <span class=\"o\">*<\/span> <span class=\"mi\">60<\/span> <span class=\"o\">*<\/span> <span class=\"mi\">60<\/span> <span class=\"o\">*<\/span> <span class=\"mi\">24<\/span><span class=\"p\">));<\/span>\n            <span class=\"k\">return<\/span> <span class=\"nx\">daysDiff<\/span> <span class=\"o\">&lt;<\/span> <span class=\"mi\">7<\/span><span class=\"p\">;<\/span>\n          <span class=\"p\">});<\/span>\n\n          <span class=\"kd\">const<\/span> <span class=\"nx\">consistencyBonus<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">min<\/span><span class=\"p\">(<\/span><span class=\"mi\">2<\/span><span class=\"p\">,<\/span> <span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">floor<\/span><span class=\"p\">(<\/span><span class=\"nx\">lastWeekCompletions<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">\/<\/span> <span class=\"mi\">3<\/span><span class=\"p\">));<\/span>\n\n          <span class=\"c1\">\/\/ Calculate total bonus<\/span>\n          <span class=\"kd\">const<\/span> <span class=\"nx\">totalBonus<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">chainBonus<\/span> <span class=\"o\">+<\/span> <span class=\"nx\">streakBonus<\/span> <span class=\"o\">+<\/span> <span class=\"nx\">consistencyBonus<\/span><span class=\"p\">;<\/span>\n          <span class=\"kd\">const<\/span> <span class=\"nx\">totalPoints<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">basePoints<\/span> <span class=\"o\">+<\/span> <span class=\"nx\">totalBonus<\/span><span class=\"p\">;<\/span>\n\n          <span class=\"k\">return<\/span> <span class=\"p\">{<\/span>\n            <span class=\"nx\">basePoints<\/span><span class=\"p\">,<\/span>\n            <span class=\"nx\">chainBonus<\/span><span class=\"p\">,<\/span>\n            <span class=\"nx\">streakBonus<\/span><span class=\"p\">,<\/span>\n            <span class=\"nx\">consistencyBonus<\/span><span class=\"p\">,<\/span>\n            <span class=\"nx\">totalBonus<\/span><span class=\"p\">,<\/span>\n            <span class=\"nx\">totalPoints<\/span><span class=\"p\">,<\/span>\n            <span class=\"na\">explanation<\/span><span class=\"p\">:<\/span> <span class=\"s2\">`<\/span><span class=\"p\">${<\/span><span class=\"nx\">basePoints<\/span><span class=\"p\">}<\/span><span class=\"s2\"> base + <\/span><span class=\"p\">${<\/span><span class=\"nx\">chainBonus<\/span><span class=\"p\">}<\/span><span class=\"s2\"> chain + <\/span><span class=\"p\">${<\/span><span class=\"nx\">streakBonus<\/span><span class=\"p\">}<\/span><span class=\"s2\"> streak + <\/span><span class=\"p\">${<\/span><span class=\"nx\">consistencyBonus<\/span><span class=\"p\">}<\/span><span class=\"s2\"> consistency = <\/span><span class=\"p\">${<\/span><span class=\"nx\">totalPoints<\/span><span class=\"p\">}<\/span><span class=\"s2\"> total`<\/span>\n          <span class=\"p\">};<\/span>\n        <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n          <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Error calculating bonus points:<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n          <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> \n            <span class=\"na\">error<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Failed to calculate bonus points<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n            <span class=\"nx\">basePoints<\/span><span class=\"p\">,<\/span>\n            <span class=\"na\">totalPoints<\/span><span class=\"p\">:<\/span> <span class=\"nx\">basePoints<\/span>\n          <span class=\"p\">};<\/span>\n        <span class=\"p\">}<\/span>\n      <span class=\"p\">}<\/span>\n    <span class=\"p\">},<\/span>\n  <span class=\"p\">};<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"nx\">pointsCalculator<\/span><span class=\"p\">;<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<blockquote>\n<p>\u0645\u06a9\u0627\u0646 \u0641\u0627\u06cc\u0644: <code>app\/agentConfigs\/wellbeing\/points-calculator.ts<\/code><\/p>\n<\/blockquote>\n<h3><span class=\"ez-toc-section\" id=\"%D8%B9%D8%A7%D9%85%D9%84_%D9%85%D8%AF%DB%8C%D8%B1_%D8%B9%D8%A7%D8%AF%D8%AA\"><\/span>\n<p>  \u0639\u0627\u0645\u0644 \u0645\u062f\u06cc\u0631 \u0639\u0627\u062f\u062a<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0627\u06cc\u0646 \u0646\u0645\u0627\u06cc\u0646\u062f\u0647 \u0645\u0633\u0626\u0648\u0644 \u0645\u062f\u06cc\u0631\u06cc\u062a \u0639\u0627\u062f\u0627\u062a \u0627\u0633\u062a.<br \/>\u0627\u06cc\u0646 \u062f\u0633\u062a\u0631\u0633\u06cc \u0628\u0647 \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u067e\u0631\u0648\u0641\u0627\u06cc\u0644 \u06a9\u0627\u0631\u0628\u0631 \u060c \u0639\u0627\u062f\u0627\u062a \u060c \u062a\u06a9\u0645\u06cc\u0644 \u060c \u0627\u0645\u062a\u06cc\u0627\u0632 \u060c \u062e\u0637 \u0648 \u0641\u0639\u0627\u0644\u06cc\u062a \u0647\u0627\u06cc \u0627\u062e\u06cc\u0631 \u062f\u0633\u062a\u0631\u0633\u06cc \u062f\u0627\u0631\u062f.<br \/>\u0645\u06cc \u062a\u0648\u0627\u0646\u062f \u062a\u0645\u0627\u0633 \u0628\u06af\u06cc\u0631\u062f: <code>getUserHabits<\/code>\u0628\u0627 <code>getHabitCompletions<\/code>\u0628\u0627 <code>completeHabit<\/code>\u0628\u0634\u0631<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight typescript\"><code><span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">AgentConfig<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/app\/types<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">getUserHabits<\/span><span class=\"p\">,<\/span> <span class=\"nx\">getHabitCompletions<\/span><span class=\"p\">,<\/span> <span class=\"nx\">completeHabit<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/app\/utils\/agentDatabaseTools<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"kd\">const<\/span> <span class=\"nx\">habitTracker<\/span><span class=\"p\">:<\/span> <span class=\"nx\">AgentConfig<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n  <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">habitTracker<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n  <span class=\"na\">publicDescription<\/span><span class=\"p\">:<\/span>\n    <span class=\"dl\">\"<\/span><span class=\"s2\">Logs user activities and awards base points for each habit.<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n  <span class=\"na\">instructions<\/span><span class=\"p\">:<\/span>\n    <span class=\"s2\">`# Personality and Tone\n## Identity\nYou\\'re Wei\\'s meticulous assistant\u2014calm, precise, and detail-oriented\u2014dedicated to tracking every healthy choice the user makes.\n... omitted for brevity.\n`<\/span><span class=\"p\">,<\/span>\n  <span class=\"na\">tools<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span>\n    <span class=\"p\">{<\/span>\n      <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">function<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getUserHabits<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Get the list of habits the user has created<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{},<\/span>\n        <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[],<\/span>\n      <span class=\"p\">},<\/span>\n    <span class=\"p\">},<\/span>\n    <span class=\"p\">{<\/span>\n      <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">function<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getHabitCompletions<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Get the list of habit completions for the past X days<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">daysAgo<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n            <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">number<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n            <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Get completions from this many days ago (default 30)<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"p\">},<\/span>\n        <span class=\"p\">},<\/span>\n        <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[],<\/span>\n      <span class=\"p\">},<\/span>\n    <span class=\"p\">},<\/span>\n    <span class=\"p\">{<\/span>\n      <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">function<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">completeHabit<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Mark a habit as complete and award points to the user<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">habitId<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n            <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">string<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n            <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">The ID of the habit to mark as complete<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"p\">},<\/span>\n        <span class=\"p\">},<\/span>\n        <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">habitId<\/span><span class=\"dl\">\"<\/span><span class=\"p\">],<\/span>\n      <span class=\"p\">},<\/span>\n    <span class=\"p\">},<\/span>\n  <span class=\"p\">],<\/span>\n  <span class=\"na\">toolLogic<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">getUserHabits<\/span><span class=\"p\">:<\/span> <span class=\"k\">async <\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">habits<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">getUserHabits<\/span><span class=\"p\">();<\/span>\n        <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">habits<\/span> <span class=\"p\">};<\/span>\n      <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Error getting user habits:<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n        <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> <span class=\"na\">error<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Failed to retrieve habits<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">};<\/span>\n      <span class=\"p\">}<\/span>\n    <span class=\"p\">},<\/span>\n    <span class=\"na\">getHabitCompletions<\/span><span class=\"p\">:<\/span> <span class=\"k\">async <\/span><span class=\"p\">({<\/span> <span class=\"nx\">daysAgo<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">30<\/span> <span class=\"p\">})<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">completions<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">getHabitCompletions<\/span><span class=\"p\">(<\/span><span class=\"nx\">daysAgo<\/span><span class=\"p\">);<\/span>\n        <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">completions<\/span> <span class=\"p\">};<\/span>\n      <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Error getting habit completions:<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n        <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> <span class=\"na\">error<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Failed to retrieve habit completions<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">};<\/span>\n      <span class=\"p\">}<\/span>\n    <span class=\"p\">},<\/span>\n    <span class=\"na\">completeHabit<\/span><span class=\"p\">:<\/span> <span class=\"k\">async <\/span><span class=\"p\">({<\/span> <span class=\"nx\">habitId<\/span> <span class=\"p\">})<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">result<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">completeHabit<\/span><span class=\"p\">(<\/span><span class=\"nx\">habitId<\/span><span class=\"p\">);<\/span>\n        <span class=\"k\">return<\/span> <span class=\"nx\">result<\/span><span class=\"p\">;<\/span>\n      <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Error completing habit:<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n        <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> <span class=\"na\">success<\/span><span class=\"p\">:<\/span> <span class=\"kc\">false<\/span><span class=\"p\">,<\/span> <span class=\"na\">message<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Failed to complete habit<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">};<\/span>\n      <span class=\"p\">}<\/span>\n    <span class=\"p\">},<\/span>\n  <span class=\"p\">},<\/span>\n<span class=\"p\">};<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"nx\">habitTracker<\/span><span class=\"p\">;<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<blockquote>\n<p>\u0645\u06a9\u0627\u0646 \u0641\u0627\u06cc\u0644: <code>app\/agentConfigs\/wellbeing\/habit-tracker.ts<\/code><\/p>\n<\/blockquote>\n<h3><span class=\"ez-toc-section\" id=\"%D8%B9%D8%A7%D9%85%D9%84_%DA%A9%D8%A7%D8%B1%D8%A8%D8%B1_%D8%B3%D8%A7%D8%AF%D9%87\"><\/span>\n<p>  \u0639\u0627\u0645\u0644 \u06a9\u0627\u0631\u0628\u0631 \u0633\u0627\u062f\u0647<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0627\u06cc\u0646 \u0646\u0645\u0627\u06cc\u0646\u062f\u0647 \u0648\u0638\u06cc\u0641\u0647 \u0627\u0631\u0627\u0626\u0647 \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u062f\u0631 \u0645\u0648\u0631\u062f \u062f\u0627\u062f\u0647 \u0647\u0627\u06cc \u062e\u0648\u062f \u0631\u0627 \u0628\u0631 \u0639\u0647\u062f\u0647 \u062f\u0627\u0631\u062f.<br \/>\u0627\u06cc\u0646 \u0645\u06cc \u062a\u0648\u0627\u0646\u062f \u06a9\u0646\u062a\u0631\u0644 \u0631\u0627 \u0628\u0647 \u0628\u0642\u06cc\u0647 \u0639\u0648\u0627\u0645\u0644 \u0645\u0646\u062a\u0642\u0644 \u06a9\u0646\u062f.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight typescript\"><code><span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">AgentConfig<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/app\/types<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"cm\">\/**\n * This agent specializes in providing users with information about their data\n * It can answer questions about points, habits, streaks, etc.\n *\/<\/span>\n<span class=\"kd\">const<\/span> <span class=\"nx\">userDataAgent<\/span><span class=\"p\">:<\/span> <span class=\"nx\">AgentConfig<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n  <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">user-data-agent<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n  <span class=\"na\">publicDescription<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Helps users understand their data, points, habits, and rewards<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n  <span class=\"na\">instructions<\/span><span class=\"p\">:<\/span> <span class=\"s2\">`You are Wei's user data specialist. Your primary role is to help users access and understand their data.\n  ... omitted for brevity.\n`<\/span><span class=\"p\">,<\/span>\n  <span class=\"na\">tools<\/span><span class=\"p\">:<\/span> <span class=\"p\">[],<\/span>\n<span class=\"p\">};<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"nx\">userDataAgent<\/span><span class=\"p\">;<\/span> \n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<blockquote>\n<p>\u0645\u06a9\u0627\u0646 \u0641\u0627\u06cc\u0644: <code>app\/agentConfigs\/wellbeing\/user-data-agent.ts<\/code><\/p>\n<\/blockquote>\n<h3><span class=\"ez-toc-section\" id=\"%D9%82%D9%88%D8%A7%D9%86%DB%8C%D9%86_%D8%A7%D9%86%D8%AA%D9%82%D8%A7%D9%84\"><\/span>\n<p>  \u0642\u0648\u0627\u0646\u06cc\u0646 \u0627\u0646\u062a\u0642\u0627\u0644<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0631\u0648\u0627\u0628\u0637 \u0627\u0646\u062a\u0642\u0627\u0644 \u0628\u06cc\u0646 \u0639\u0648\u0627\u0645\u0644 \u0631\u0627 \u062a\u0646\u0638\u06cc\u0645 \u06a9\u0646\u06cc\u062f. <br \/>\u0633\u067e\u0633 \u0627\u0628\u0632\u0627\u0631\u0647\u0627\u06cc \u0627\u0646\u062a\u0642\u0627\u0644 \u0631\u0627 \u0628\u0631\u0627\u06cc \u0647\u0645\u0647 \u0639\u0648\u0627\u0645\u0644 \u0627\u0639\u0645\u0627\u0644 \u06a9\u0646\u06cc\u062f.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight typescript\"><code><span class=\"k\">import<\/span> <span class=\"nx\">rewardsManager<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/rewards-manager<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">pointsCalculator<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/points-calculator<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">habitTracker<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/habit-tracker<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">userDataAgent<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/user-data-agent<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">injectTransferTools<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">..\/utils<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"c1\">\/\/ Set up the transfer relationships between agents<\/span>\n<span class=\"nx\">rewardsManager<\/span><span class=\"p\">.<\/span><span class=\"nx\">downstreamAgents<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span><span class=\"nx\">pointsCalculator<\/span><span class=\"p\">,<\/span> <span class=\"nx\">habitTracker<\/span><span class=\"p\">,<\/span> <span class=\"nx\">userDataAgent<\/span><span class=\"p\">];<\/span>\n<span class=\"nx\">pointsCalculator<\/span><span class=\"p\">.<\/span><span class=\"nx\">downstreamAgents<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span><span class=\"nx\">rewardsManager<\/span><span class=\"p\">,<\/span> <span class=\"nx\">habitTracker<\/span><span class=\"p\">,<\/span> <span class=\"nx\">userDataAgent<\/span><span class=\"p\">];<\/span>\n<span class=\"nx\">habitTracker<\/span><span class=\"p\">.<\/span><span class=\"nx\">downstreamAgents<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span><span class=\"nx\">rewardsManager<\/span><span class=\"p\">,<\/span> <span class=\"nx\">pointsCalculator<\/span><span class=\"p\">,<\/span> <span class=\"nx\">userDataAgent<\/span><span class=\"p\">];<\/span>\n<span class=\"nx\">userDataAgent<\/span><span class=\"p\">.<\/span><span class=\"nx\">downstreamAgents<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span><span class=\"nx\">rewardsManager<\/span><span class=\"p\">,<\/span> <span class=\"nx\">pointsCalculator<\/span><span class=\"p\">,<\/span> <span class=\"nx\">habitTracker<\/span><span class=\"p\">];<\/span>\n\n<span class=\"c1\">\/\/ Apply transfer tools to all agents<\/span>\n<span class=\"kd\">const<\/span> <span class=\"nx\">agents<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">injectTransferTools<\/span><span class=\"p\">([<\/span>\n  <span class=\"nx\">rewardsManager<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">pointsCalculator<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">habitTracker<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">userDataAgent<\/span><span class=\"p\">,<\/span>\n<span class=\"p\">]);<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"nx\">agents<\/span><span class=\"p\">;<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<blockquote>\n<p>\u0645\u06a9\u0627\u0646 \u0641\u0627\u06cc\u0644: <code>app\/agentConfigs\/wellbeing\/index.ts<\/code><\/p>\n<\/blockquote>\n<h3><span class=\"ez-toc-section\" id=\"%D9%87%D9%85%D9%87_%D8%B9%D9%88%D8%A7%D9%85%D9%84\"><\/span>\n<p>  \u0647\u0645\u0647 \u0639\u0648\u0627\u0645\u0644<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0645\u0627 \u0628\u0627\u06cc\u062f \u0647\u0645\u0647 \u0639\u0648\u0627\u0645\u0644 \u0631\u0627 \u0635\u0627\u062f\u0631 \u06a9\u0646\u06cc\u0645 \u062a\u0627 \u062f\u0631 \u0628\u0631\u0646\u0627\u0645\u0647 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0634\u0648\u062f.<br \/>\u0631\u0641\u0627\u0647 \u0631\u0627 \u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u0639\u0627\u0645\u0644 \u067e\u06cc\u0634 \u0641\u0631\u0636 \u062a\u0646\u0638\u06cc\u0645 \u06a9\u0646\u06cc\u062f \u0632\u06cc\u0631\u0627 \u062d\u0627\u0648\u06cc \u0639\u0627\u0645\u0644 \u062f\u0627\u062f\u0647 \u06a9\u0627\u0631\u0628\u0631 \u0645\u0627 \u0627\u0633\u062a.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight typescript\"><code><span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">AllAgentConfigsType<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/app\/types<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">greeter<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/greeter<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">wellbeing<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/wellbeing<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kd\">const<\/span> <span class=\"nx\">allAgentSets<\/span><span class=\"p\">:<\/span> <span class=\"nx\">AllAgentConfigsType<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nx\">wellbeing<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">greeter<\/span><span class=\"p\">,<\/span>\n<span class=\"p\">};<\/span>\n\n<span class=\"c1\">\/\/ Set wellbeing as the default agent set since it contains our user data agent<\/span>\n<span class=\"k\">export<\/span> <span class=\"kd\">const<\/span> <span class=\"nx\">defaultAgentSetKey<\/span> <span class=\"o\">=<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">wellbeing<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<blockquote>\n<p>\u0645\u06a9\u0627\u0646 \u0641\u0627\u06cc\u0644: <code>app\/agentConfigs\/index.ts<\/code><\/p>\n<\/blockquote>\n<h3><span class=\"ez-toc-section\" id=\"%D9%85%D9%86%D8%B7%D9%82_%D8%B9%D9%88%D8%A7%D9%85%D9%84_%D8%AC%D8%A7%D9%85%D8%B9\"><\/span>\n<p>  \u0645\u0646\u0637\u0642 \u0639\u0648\u0627\u0645\u0644 \u062c\u0627\u0645\u0639<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0645\u0627 \u0628\u0627\u06cc\u062f \u0627\u0628\u0632\u0627\u0631\u0647\u0627\u06cc \u0627\u0646\u062a\u0642\u0627\u0644 \u0631\u0627 \u0628\u0647 \u0647\u0645\u0647 \u0639\u0648\u0627\u0645\u0644 \u062a\u0632\u0631\u06cc\u0642 \u06a9\u0646\u06cc\u0645.<br \/><code>injectTransferTools<\/code>  \u0627\u0628\u0632\u0627\u0631 &#8220;\u0627\u0646\u062a\u0642\u0627\u0644 \u062f\u0647\u0646\u062f\u0647 \u0647\u0627&#8221; \u0631\u0627 \u0628\u0647 \u0635\u0648\u0631\u062a \u067e\u0648\u06cc\u0627 \u0628\u0631 \u0627\u0633\u0627\u0633 \u067e\u0627\u06cc\u06cc\u0646 \u062f\u0633\u062a \u0645\u0634\u062e\u0635 \u0634\u062f\u0647 \u062f\u0631 \u0647\u0631 \u0639\u0627\u0645\u0644 \u062a\u0639\u0631\u06cc\u0641 \u0648 \u0627\u0636\u0627\u0641\u0647 \u0645\u06cc \u06a9\u0646\u062f.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight typescript\"><code><span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">AgentConfig<\/span><span class=\"p\">,<\/span> <span class=\"nx\">Tool<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/app\/types<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">UserCache<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/app\/contexts\/UserCacheContext<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"cm\">\/**\n * This defines and adds \"transferAgents\" tool dynamically based on the specified downstreamAgents on each agent.\n *\/<\/span>\n<span class=\"k\">export<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">injectTransferTools<\/span><span class=\"p\">(<\/span><span class=\"nx\">agentDefs<\/span><span class=\"p\">:<\/span> <span class=\"nx\">AgentConfig<\/span><span class=\"p\">[]):<\/span> <span class=\"nx\">AgentConfig<\/span><span class=\"p\">[]<\/span> <span class=\"p\">{<\/span>\n  <span class=\"c1\">\/\/ Iterate over each agent definition<\/span>\n  <span class=\"nx\">agentDefs<\/span><span class=\"p\">.<\/span><span class=\"nf\">forEach<\/span><span class=\"p\">((<\/span><span class=\"nx\">agentDef<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">downstreamAgents<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">agentDef<\/span><span class=\"p\">.<\/span><span class=\"nx\">downstreamAgents<\/span> <span class=\"o\">||<\/span> <span class=\"p\">[];<\/span>\n\n    <span class=\"c1\">\/\/ Only proceed if there are downstream agents<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">downstreamAgents<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"c1\">\/\/ Build a list of downstream agents and their descriptions for the prompt<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">availableAgentsList<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">downstreamAgents<\/span>\n        <span class=\"p\">.<\/span><span class=\"nf\">map<\/span><span class=\"p\">(<\/span>\n          <span class=\"p\">(<\/span><span class=\"nx\">dAgent<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span>\n            <span class=\"s2\">`- <\/span><span class=\"p\">${<\/span><span class=\"nx\">dAgent<\/span><span class=\"p\">.<\/span><span class=\"nx\">name<\/span><span class=\"p\">}<\/span><span class=\"s2\">: <\/span><span class=\"p\">${<\/span><span class=\"nx\">dAgent<\/span><span class=\"p\">.<\/span><span class=\"nx\">publicDescription<\/span> <span class=\"o\">??<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">No description<\/span><span class=\"dl\">\"<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span>\n        <span class=\"p\">)<\/span>\n        <span class=\"p\">.<\/span><span class=\"nf\">join<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"se\">\\n<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n\n      <span class=\"c1\">\/\/ Create the transfer_agent tool specific to this agent<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"na\">transferAgentTool<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Tool<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">function<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">transferAgents<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"s2\">`Triggers a transfer of the user to a more specialized agent. \n  Calls escalate to a more specialized LLM agent or to a human agent, with additional context. \n  Only call this function if one of the available agents is appropriate. Don't transfer to your own agent type.\n\n  Let the user know you're about to transfer them before doing so.\n\n  Available Agents:\n  <\/span><span class=\"p\">${<\/span><span class=\"nx\">availableAgentsList<\/span><span class=\"p\">}<\/span><span class=\"s2\">\n        `<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n            <span class=\"na\">rationale_for_transfer<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n              <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">string<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n              <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">The reasoning why this transfer is needed.<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n            <span class=\"p\">},<\/span>\n            <span class=\"na\">conversation_context<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n              <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">string<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n              <span class=\"na\">description<\/span><span class=\"p\">:<\/span>\n                <span class=\"dl\">\"<\/span><span class=\"s2\">Relevant context from the conversation that will help the recipient perform the correct action.<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n            <span class=\"p\">},<\/span>\n            <span class=\"na\">destination_agent<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n              <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">string<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n              <span class=\"na\">description<\/span><span class=\"p\">:<\/span>\n                <span class=\"dl\">\"<\/span><span class=\"s2\">The more specialized destination_agent that should handle the user's intended request.<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n              <span class=\"na\">enum<\/span><span class=\"p\">:<\/span> <span class=\"nx\">downstreamAgents<\/span><span class=\"p\">.<\/span><span class=\"nf\">map<\/span><span class=\"p\">((<\/span><span class=\"nx\">dAgent<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">dAgent<\/span><span class=\"p\">.<\/span><span class=\"nx\">name<\/span><span class=\"p\">),<\/span>\n            <span class=\"p\">},<\/span>\n          <span class=\"p\">},<\/span>\n          <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span>\n            <span class=\"dl\">\"<\/span><span class=\"s2\">rationale_for_transfer<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n            <span class=\"dl\">\"<\/span><span class=\"s2\">conversation_context<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n            <span class=\"dl\">\"<\/span><span class=\"s2\">destination_agent<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"p\">],<\/span>\n        <span class=\"p\">},<\/span>\n      <span class=\"p\">};<\/span>\n\n      <span class=\"c1\">\/\/ Ensure the agent has a tools array<\/span>\n      <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">agentDef<\/span><span class=\"p\">.<\/span><span class=\"nx\">tools<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">agentDef<\/span><span class=\"p\">.<\/span><span class=\"nx\">tools<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[];<\/span>\n      <span class=\"p\">}<\/span>\n\n      <span class=\"c1\">\/\/ Add the newly created tool to the current agent's tools<\/span>\n      <span class=\"nx\">agentDef<\/span><span class=\"p\">.<\/span><span class=\"nx\">tools<\/span><span class=\"p\">.<\/span><span class=\"nf\">push<\/span><span class=\"p\">(<\/span><span class=\"nx\">transferAgentTool<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c1\">\/\/ so .stringify doesn't break with circular dependencies<\/span>\n    <span class=\"nx\">agentDef<\/span><span class=\"p\">.<\/span><span class=\"nx\">downstreamAgents<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">agentDef<\/span><span class=\"p\">.<\/span><span class=\"nx\">downstreamAgents<\/span><span class=\"p\">?.<\/span><span class=\"nf\">map<\/span><span class=\"p\">(<\/span>\n      <span class=\"p\">({<\/span> <span class=\"nx\">name<\/span><span class=\"p\">,<\/span> <span class=\"nx\">publicDescription<\/span> <span class=\"p\">})<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">({<\/span>\n        <span class=\"nx\">name<\/span><span class=\"p\">,<\/span>\n        <span class=\"nx\">publicDescription<\/span><span class=\"p\">,<\/span>\n      <span class=\"p\">})<\/span>\n    <span class=\"p\">);<\/span>\n  <span class=\"p\">});<\/span>\n\n  <span class=\"k\">return<\/span> <span class=\"nx\">agentDefs<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<blockquote>\n<p>\u0645\u06a9\u0627\u0646 \u0641\u0627\u06cc\u0644: <code>app\/agentConfigs\/utils.ts<\/code><\/p>\n<\/blockquote>\n<h4><span class=\"ez-toc-section\" id=\"%D8%B2%D9%85%DB%8C%D9%86%D9%87_%DA%A9%D8%A7%D8%B1%D8%A8%D8%B1_%D8%B1%D8%A7_%D8%AA%D8%B2%D8%B1%DB%8C%D9%82_%DA%A9%D9%86%DB%8C%D8%AF\"><\/span>\n<p>  \u0632\u0645\u06cc\u0646\u0647 \u06a9\u0627\u0631\u0628\u0631 \u0631\u0627 \u062a\u0632\u0631\u06cc\u0642 \u06a9\u0646\u06cc\u062f<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>\u062f\u0633\u062a\u0648\u0631\u0627\u0644\u0639\u0645\u0644 \u0647\u0627\u06cc \u0639\u0627\u0645\u0644 \u0631\u0627 \u0628\u0627 \u062f\u0627\u062f\u0647 \u0647\u0627\u06cc \u06a9\u0627\u0631\u0628\u0631 \u0627\u0632 \u062d\u0627\u0641\u0638\u0647 \u0646\u0647\u0627\u0646 \u062a\u0642\u0648\u06cc\u062a \u0645\u06cc \u06a9\u0646\u062f. <br \/>\u0627\u06cc\u0646 \u0627\u0645\u0631 \u0628\u0647 \u0646\u0645\u0627\u06cc\u0646\u062f\u06af\u0627\u0646 \u0627\u062c\u0627\u0632\u0647 \u0645\u06cc \u062f\u0647\u062f \u062a\u0627 \u0632\u0645\u06cc\u0646\u0647 \u0634\u062e\u0635\u06cc \u0631\u0627 \u062f\u0631 \u0645\u0648\u0631\u062f \u06a9\u0627\u0631\u0628\u0631 \u062f\u0627\u0634\u062a\u0647 \u0628\u0627\u0634\u0646\u062f. <br \/>\u0647\u0645\u0686\u0646\u06cc\u0646 \u0627\u0628\u0632\u0627\u0631\u0647\u0627\u06cc \u062f\u0633\u062a\u0631\u0633\u06cc \u0628\u0647 \u062f\u0627\u062f\u0647 \u0647\u0627\u06cc \u06a9\u0627\u0631\u0628\u0631 \u0631\u0627 \u0628\u0647 \u0646\u0645\u0627\u06cc\u0646\u062f\u0647 \u0627\u0636\u0627\u0641\u0647 \u0645\u06cc \u06a9\u0646\u062f<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight typescript\"><code><span class=\"cm\">\/**\n * Enhances agent instructions with user data from cache\n * This allows agents to have personalized context about the user\n * Also adds user data access tools to the agent\n *\/<\/span>\n<span class=\"k\">export<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">injectUserContext<\/span><span class=\"p\">(<\/span><span class=\"nx\">agentDef<\/span><span class=\"p\">:<\/span> <span class=\"nx\">AgentConfig<\/span><span class=\"p\">,<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">:<\/span> <span class=\"nx\">UserCache<\/span><span class=\"p\">):<\/span> <span class=\"nx\">AgentConfig<\/span> <span class=\"p\">{<\/span>\n  <span class=\"c1\">\/\/ Create a deep copy to avoid mutating the original<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">enhancedAgent<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span> <span class=\"p\">...<\/span><span class=\"nx\">agentDef<\/span> <span class=\"p\">};<\/span>\n\n  <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">userCache<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">return<\/span> <span class=\"nx\">enhancedAgent<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">}<\/span>\n\n  <span class=\"c1\">\/\/ Create a user context section to append to instructions<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">userContextBlock<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">createUserContextBlock<\/span><span class=\"p\">(<\/span><span class=\"nx\">userCache<\/span><span class=\"p\">);<\/span>\n\n  <span class=\"c1\">\/\/ Append the user context to the agent's instructions<\/span>\n  <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">enhancedAgent<\/span><span class=\"p\">.<\/span><span class=\"nx\">instructions<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">enhancedAgent<\/span><span class=\"p\">.<\/span><span class=\"nx\">instructions<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">`<\/span><span class=\"p\">${<\/span><span class=\"nx\">enhancedAgent<\/span><span class=\"p\">.<\/span><span class=\"nx\">instructions<\/span><span class=\"p\">}<\/span><span class=\"s2\">\\n\\n# User Context\\n<\/span><span class=\"p\">${<\/span><span class=\"nx\">userContextBlock<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">}<\/span>\n\n  <span class=\"c1\">\/\/ Add user data access tools<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">userDataTools<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">createUserDataTools<\/span><span class=\"p\">();<\/span>\n\n  <span class=\"c1\">\/\/ Ensure the agent has a tools array<\/span>\n  <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">enhancedAgent<\/span><span class=\"p\">.<\/span><span class=\"nx\">tools<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">enhancedAgent<\/span><span class=\"p\">.<\/span><span class=\"nx\">tools<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[];<\/span>\n  <span class=\"p\">}<\/span>\n\n  <span class=\"c1\">\/\/ Add user data tools to the agent's tools<\/span>\n  <span class=\"nx\">enhancedAgent<\/span><span class=\"p\">.<\/span><span class=\"nx\">tools<\/span><span class=\"p\">.<\/span><span class=\"nf\">push<\/span><span class=\"p\">(...<\/span><span class=\"nx\">userDataTools<\/span><span class=\"p\">);<\/span>\n\n  <span class=\"k\">return<\/span> <span class=\"nx\">enhancedAgent<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<blockquote>\n<p>\u0645\u06a9\u0627\u0646 \u0641\u0627\u06cc\u0644: <code>app\/agentConfigs\/utils.ts<\/code><\/p>\n<\/blockquote>\n<h4><span class=\"ez-toc-section\" id=\"%D8%A8%D9%84%D9%88%DA%A9_%D8%B2%D9%85%DB%8C%D9%86%D9%87_%DA%A9%D8%A7%D8%B1%D8%A8%D8%B1_%D8%B1%D8%A7_%D8%A7%DB%8C%D8%AC%D8%A7%D8%AF_%DA%A9%D9%86%DB%8C%D8%AF\"><\/span>\n<p>  \u0628\u0644\u0648\u06a9 \u0632\u0645\u06cc\u0646\u0647 \u06a9\u0627\u0631\u0628\u0631 \u0631\u0627 \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>\u06cc\u06a9 \u0628\u0644\u0648\u06a9 \u0641\u0631\u0645\u062a \u0634\u062f\u0647 \u0627\u0632 \u0632\u0645\u06cc\u0646\u0647 \u06a9\u0627\u0631\u0628\u0631 \u0631\u0627 \u0627\u0632 \u062f\u0627\u062f\u0647 \u0647\u0627\u06cc \u062d\u0627\u0641\u0638\u0647 \u0646\u0647\u0627\u0646 \u0627\u06cc\u062c\u0627\u062f \u0645\u06cc \u06a9\u0646\u062f.<br \/>\u0628\u0647\u06cc\u0646\u0647 \u0634\u062f\u0647 \u0628\u0631\u0627\u06cc \u0627\u0631\u0627\u0626\u0647 \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u0645\u062e\u062a\u0635\u0631 \u0627\u0645\u0627 \u0645\u0641\u06cc\u062f.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight typescript\"><code><span class=\"cm\">\/**\n * Creates a formatted block of user context from cache data\n * Optimized to provide concise but useful information\n *\/<\/span>\n<span class=\"kd\">function<\/span> <span class=\"nf\">createUserContextBlock<\/span><span class=\"p\">(<\/span><span class=\"nx\">userCache<\/span><span class=\"p\">:<\/span> <span class=\"nx\">UserCache<\/span><span class=\"p\">):<\/span> <span class=\"kr\">string<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">userCache<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">return<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">No user data available.<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">}<\/span>\n\n  <span class=\"kd\">let<\/span> <span class=\"nx\">contextBlock<\/span> <span class=\"o\">=<\/span> <span class=\"dl\">''<\/span><span class=\"p\">;<\/span>\n\n  <span class=\"c1\">\/\/ Add user profile information<\/span>\n  <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">profile<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">contextBlock<\/span> <span class=\"o\">+=<\/span> <span class=\"s2\">`## User Profile\\n`<\/span><span class=\"p\">;<\/span>\n    <span class=\"nx\">contextBlock<\/span> <span class=\"o\">+=<\/span> <span class=\"s2\">`- Name: <\/span><span class=\"p\">${<\/span><span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">profile<\/span><span class=\"p\">.<\/span><span class=\"nx\">name<\/span> <span class=\"o\">||<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">Unknown<\/span><span class=\"dl\">'<\/span><span class=\"p\">}<\/span><span class=\"s2\">\\n`<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">profile<\/span><span class=\"p\">.<\/span><span class=\"nx\">bio<\/span><span class=\"p\">)<\/span> <span class=\"nx\">contextBlock<\/span> <span class=\"o\">+=<\/span> <span class=\"s2\">`- Bio: <\/span><span class=\"p\">${<\/span><span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">profile<\/span><span class=\"p\">.<\/span><span class=\"nx\">bio<\/span><span class=\"p\">}<\/span><span class=\"s2\">\\n`<\/span><span class=\"p\">;<\/span>\n    <span class=\"nx\">contextBlock<\/span> <span class=\"o\">+=<\/span> <span class=\"s2\">`- Member since: <\/span><span class=\"p\">${<\/span><span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">profile<\/span><span class=\"p\">.<\/span><span class=\"nx\">joinDate<\/span> <span class=\"o\">||<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">Unknown<\/span><span class=\"dl\">'<\/span><span class=\"p\">}<\/span><span class=\"s2\">\\n\\n`<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">}<\/span>\n\n  <span class=\"c1\">\/\/ Add points and streak information (most frequently asked)<\/span>\n  <span class=\"nx\">contextBlock<\/span> <span class=\"o\">+=<\/span> <span class=\"s2\">`## Summary Stats\\n`<\/span><span class=\"p\">;<\/span>\n  <span class=\"nx\">contextBlock<\/span> <span class=\"o\">+=<\/span> <span class=\"s2\">`- Current points: <\/span><span class=\"p\">${<\/span><span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">points<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">0<\/span><span class=\"p\">}<\/span><span class=\"s2\">\\n`<\/span><span class=\"p\">;<\/span>\n  <span class=\"nx\">contextBlock<\/span> <span class=\"o\">+=<\/span> <span class=\"s2\">`- Current streak: <\/span><span class=\"p\">${<\/span><span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">streak<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">0<\/span><span class=\"p\">}<\/span><span class=\"s2\"> days\\n`<\/span><span class=\"p\">;<\/span>\n\n  <span class=\"c1\">\/\/ Add habit count and category summary (not full details)<\/span>\n  <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">habits<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">habits<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">habitCategories<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">habits<\/span><span class=\"p\">.<\/span><span class=\"nf\">reduce<\/span><span class=\"p\">((<\/span><span class=\"nx\">acc<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Record<\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">string<\/span><span class=\"p\">,<\/span> <span class=\"kr\">number<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">,<\/span> <span class=\"nx\">habit<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">category<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">habit<\/span><span class=\"p\">.<\/span><span class=\"nx\">category<\/span> <span class=\"o\">||<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">Uncategorized<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n      <span class=\"nx\">acc<\/span><span class=\"p\">[<\/span><span class=\"nx\">category<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"nx\">acc<\/span><span class=\"p\">[<\/span><span class=\"nx\">category<\/span><span class=\"p\">]<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">0<\/span><span class=\"p\">)<\/span> <span class=\"o\">+<\/span> <span class=\"mi\">1<\/span><span class=\"p\">;<\/span>\n      <span class=\"k\">return<\/span> <span class=\"nx\">acc<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">},<\/span> <span class=\"p\">{});<\/span>\n\n    <span class=\"nx\">contextBlock<\/span> <span class=\"o\">+=<\/span> <span class=\"s2\">`- Active habits: <\/span><span class=\"p\">${<\/span><span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">habits<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span><span class=\"p\">}<\/span><span class=\"s2\"> habits\\n`<\/span><span class=\"p\">;<\/span>\n    <span class=\"nx\">contextBlock<\/span> <span class=\"o\">+=<\/span> <span class=\"s2\">`- Categories: <\/span><span class=\"p\">${<\/span><span class=\"nb\">Object<\/span><span class=\"p\">.<\/span><span class=\"nf\">entries<\/span><span class=\"p\">(<\/span><span class=\"nx\">habitCategories<\/span><span class=\"p\">).<\/span><span class=\"nf\">map<\/span><span class=\"p\">(([<\/span><span class=\"nx\">cat<\/span><span class=\"p\">,<\/span> <span class=\"nx\">count<\/span><span class=\"p\">])<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"s2\">`<\/span><span class=\"p\">${<\/span><span class=\"nx\">cat<\/span><span class=\"p\">}<\/span><span class=\"s2\"> (<\/span><span class=\"p\">${<\/span><span class=\"nx\">count<\/span><span class=\"p\">}<\/span><span class=\"s2\">)`<\/span><span class=\"p\">).<\/span><span class=\"nf\">join<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">, <\/span><span class=\"dl\">'<\/span><span class=\"p\">)}<\/span><span class=\"s2\">\\n\\n`<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">}<\/span>\n\n  <span class=\"c1\">\/\/ Add just 2-3 recent activities as examples (not all)<\/span>\n  <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">recentActivity<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">recentActivity<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">contextBlock<\/span> <span class=\"o\">+=<\/span> <span class=\"s2\">`## Recent Activity Examples\\n`<\/span><span class=\"p\">;<\/span>\n    <span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">recentActivity<\/span><span class=\"p\">.<\/span><span class=\"nf\">slice<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"mi\">3<\/span><span class=\"p\">).<\/span><span class=\"nf\">forEach<\/span><span class=\"p\">((<\/span><span class=\"nx\">activity<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">contextBlock<\/span> <span class=\"o\">+=<\/span> <span class=\"s2\">`- <\/span><span class=\"p\">${<\/span><span class=\"nx\">activity<\/span><span class=\"p\">.<\/span><span class=\"nx\">action<\/span><span class=\"p\">}<\/span><span class=\"s2\"> \"<\/span><span class=\"p\">${<\/span><span class=\"nx\">activity<\/span><span class=\"p\">.<\/span><span class=\"nx\">target<\/span><span class=\"p\">}<\/span><span class=\"s2\">\" (<\/span><span class=\"p\">${<\/span><span class=\"nx\">activity<\/span><span class=\"p\">.<\/span><span class=\"nx\">points<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span> <span class=\"p\">?<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">+<\/span><span class=\"dl\">'<\/span> <span class=\"p\">:<\/span> <span class=\"dl\">''<\/span><span class=\"p\">}${<\/span><span class=\"nx\">activity<\/span><span class=\"p\">.<\/span><span class=\"nx\">points<\/span><span class=\"p\">}<\/span><span class=\"s2\"> points) on <\/span><span class=\"p\">${<\/span><span class=\"nx\">activity<\/span><span class=\"p\">.<\/span><span class=\"nx\">date<\/span><span class=\"p\">}<\/span><span class=\"s2\">\\n`<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">});<\/span>\n    <span class=\"nx\">contextBlock<\/span> <span class=\"o\">+=<\/span> <span class=\"dl\">'<\/span><span class=\"se\">\\n<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">}<\/span>\n\n  <span class=\"c1\">\/\/ Add note about available tools<\/span>\n  <span class=\"nx\">contextBlock<\/span> <span class=\"o\">+=<\/span> <span class=\"s2\">`*Note: For detailed user information, use the provided user data access functions.*\\n`<\/span><span class=\"p\">;<\/span>\n\n  <span class=\"k\">return<\/span> <span class=\"nx\">contextBlock<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<blockquote>\n<p>\u0645\u06a9\u0627\u0646 \u0641\u0627\u06cc\u0644: <code>app\/agentConfigs\/utils.ts<\/code><\/p>\n<\/blockquote>\n<h4><span class=\"ez-toc-section\" id=\"%D8%A7%D8%A8%D8%B2%D8%A7%D8%B1%D9%87%D8%A7%DB%8C_%D8%AF%D8%A7%D8%AF%D9%87_%DA%A9%D8%A7%D8%B1%D8%A8%D8%B1_%D8%B1%D8%A7_%D8%A7%DB%8C%D8%AC%D8%A7%D8%AF_%DA%A9%D9%86%DB%8C%D8%AF\"><\/span>\n<p>  \u0627\u0628\u0632\u0627\u0631\u0647\u0627\u06cc \u062f\u0627\u062f\u0647 \u06a9\u0627\u0631\u0628\u0631 \u0631\u0627 \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>\u0645\u062c\u0645\u0648\u0639\u0647 \u0627\u06cc \u0627\u0632 \u0627\u0628\u0632\u0627\u0631\u0647\u0627\u06cc\u06cc \u0631\u0627 \u0627\u06cc\u062c\u0627\u062f \u0645\u06cc \u06a9\u0646\u062f \u06a9\u0647 \u0628\u0647 \u0639\u0627\u0645\u0644 \u0627\u0645\u06a9\u0627\u0646 \u062f\u0633\u062a\u0631\u0633\u06cc \u0628\u0647 \u062f\u0627\u062f\u0647 \u0647\u0627\u06cc \u062e\u0627\u0635 \u06a9\u0627\u0631\u0628\u0631 \u0631\u0627 \u0645\u06cc \u062f\u0647\u062f.<br \/>\u062a\u0648\u062c\u0647: \u0627\u062c\u0631\u0627\u06cc \u0648\u0627\u0642\u0639\u06cc \u0627\u06cc\u0646 \u0627\u0628\u0632\u0627\u0631\u0647\u0627 \u062f\u0631 \u06a9\u0646\u062a\u0631\u0644 \u0645\u0633\u06cc\u0631 API \u0627\u0633\u062a. <br \/>\u062f\u0631 \u0627\u06cc\u0646\u062c\u0627: <code>app\/api\/chat\/completions\/route.ts<\/code>\u0628\u0634\u0631<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight typescript\"><code><span class=\"cm\">\/**\n * Creates a set of tools that allow the agent to access specific user data\n * Note: The actual implementation of these tools is in the API route handler\n *\/<\/span>\n<span class=\"kd\">function<\/span> <span class=\"nf\">createUserDataTools<\/span><span class=\"p\">():<\/span> <span class=\"nx\">Tool<\/span><span class=\"p\">[]<\/span> <span class=\"p\">{<\/span>\n  <span class=\"c1\">\/\/ Prepare the tools array<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">tools<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Tool<\/span><span class=\"p\">[]<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[];<\/span>\n\n  <span class=\"c1\">\/\/ Get user profile info<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">getUserProfileTool<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Tool<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">function<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getUserProfile<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Get detailed user profile information<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">fields<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">array<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">items<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n            <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">string<\/span><span class=\"dl\">\"<\/span>\n          <span class=\"p\">},<\/span>\n          <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Optional array of specific profile fields to retrieve<\/span><span class=\"dl\">\"<\/span>\n        <span class=\"p\">}<\/span>\n      <span class=\"p\">},<\/span>\n      <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[]<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">};<\/span>\n  <span class=\"nx\">tools<\/span><span class=\"p\">.<\/span><span class=\"nf\">push<\/span><span class=\"p\">(<\/span><span class=\"nx\">getUserProfileTool<\/span><span class=\"p\">);<\/span>\n\n  <span class=\"c1\">\/\/ Get user points and streak<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">getUserStatsTool<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Tool<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">function<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getUserStats<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Get user's current points and streak information<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{},<\/span>\n      <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[]<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">};<\/span>\n  <span class=\"nx\">tools<\/span><span class=\"p\">.<\/span><span class=\"nf\">push<\/span><span class=\"p\">(<\/span><span class=\"nx\">getUserStatsTool<\/span><span class=\"p\">);<\/span>\n\n  <span class=\"c1\">\/\/ Get user habits<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">getUserHabitsTool<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Tool<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">function<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getUserHabits<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Get list of user's active habits with details<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">category<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">string<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Optional category to filter habits by<\/span><span class=\"dl\">\"<\/span>\n        <span class=\"p\">}<\/span>\n      <span class=\"p\">},<\/span>\n      <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[]<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">};<\/span>\n  <span class=\"nx\">tools<\/span><span class=\"p\">.<\/span><span class=\"nf\">push<\/span><span class=\"p\">(<\/span><span class=\"nx\">getUserHabitsTool<\/span><span class=\"p\">);<\/span>\n\n  <span class=\"c1\">\/\/ Get user recent activity<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">getUserActivityTool<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Tool<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">function<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getRecentActivity<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Get user's recent activity history<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">limit<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">number<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Number of activities to return (defaults to 5)<\/span><span class=\"dl\">\"<\/span>\n        <span class=\"p\">},<\/span>\n        <span class=\"na\">activityType<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">string<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Filter by activity type ('Completed' or 'Redeemed')<\/span><span class=\"dl\">\"<\/span>\n        <span class=\"p\">}<\/span>\n      <span class=\"p\">},<\/span>\n      <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[]<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">};<\/span>\n  <span class=\"nx\">tools<\/span><span class=\"p\">.<\/span><span class=\"nf\">push<\/span><span class=\"p\">(<\/span><span class=\"nx\">getUserActivityTool<\/span><span class=\"p\">);<\/span>\n\n  <span class=\"c1\">\/\/ Get user rewards<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">getUserRewardsTool<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Tool<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">function<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getUserRewards<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Get user's available rewards<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{},<\/span>\n      <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[]<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">};<\/span>\n  <span class=\"nx\">tools<\/span><span class=\"p\">.<\/span><span class=\"nf\">push<\/span><span class=\"p\">(<\/span><span class=\"nx\">getUserRewardsTool<\/span><span class=\"p\">);<\/span>\n\n  <span class=\"c1\">\/\/ Get reward redemptions<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">getRewardRedemptionsTool<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Tool<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">function<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getRewardRedemptions<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Get the user's past reward redemptions<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">daysAgo<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">number<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Get redemptions from this many days ago (default 30)<\/span><span class=\"dl\">\"<\/span>\n        <span class=\"p\">}<\/span>\n      <span class=\"p\">},<\/span>\n      <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[]<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">};<\/span>\n  <span class=\"nx\">tools<\/span><span class=\"p\">.<\/span><span class=\"nf\">push<\/span><span class=\"p\">(<\/span><span class=\"nx\">getRewardRedemptionsTool<\/span><span class=\"p\">);<\/span>\n\n  <span class=\"k\">return<\/span> <span class=\"nx\">tools<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<blockquote>\n<p>\u0645\u06a9\u0627\u0646 \u0641\u0627\u06cc\u0644: <code>app\/agentConfigs\/utils.ts<\/code><\/p>\n<\/blockquote>\n<p>\u062a\u0628\u0631\u06cc\u06a9 \u0645\u06cc \u06af\u0648\u06cc\u0645! \u0634\u0645\u0627 \u0641\u0642\u0637 \u06cc\u06a9 \u0645\u0646\u0637\u0642 \u062c\u0627\u0645\u0639 \u0639\u0648\u0627\u0645\u0644 \u0628\u0631\u0627\u06cc \u0648\u06cc \u0627\u06cc\u062c\u0627\u062f \u06a9\u0631\u062f\u0647 \u0627\u06cc\u062f.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"API\"><\/span>\n<p>  API<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0645\u0627 \u0628\u0627\u06cc\u062f API \u0631\u0627 \u0628\u0633\u0627\u0632\u06cc\u0645 \u062a\u0627 \u0645\u0646\u0637\u0642 \u0639\u0627\u0645\u0644 \u0631\u0627 \u0627\u062f\u0627\u0631\u0647 \u06a9\u0646\u06cc\u0645.<\/p>\n<p>\u06cc\u06a9 \u0641\u0627\u06cc\u0644 \u062c\u062f\u06cc\u062f \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f <code>app\/api\/chat\/completions\/route.ts<\/code>\u0628\u0634\u0631<\/p>\n<h3><span class=\"ez-toc-section\" id=\"%D8%AA%D9%88%D8%A7%D8%A8%D8%B9_%D9%BE%DB%8C%D8%B4_%D9%81%D8%B1%D8%B6\"><\/span>\n<p>  \u062a\u0648\u0627\u0628\u0639 \u067e\u06cc\u0634 \u0641\u0631\u0636<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u062a\u0648\u0627\u0628\u0639 \u067e\u06cc\u0634 \u0641\u0631\u0636 \u0631\u0627 \u062a\u0639\u0631\u06cc\u0641 \u06a9\u0646\u06cc\u062f \u06a9\u0647 \u0647\u0645\u0647 \u0639\u0648\u0627\u0645\u0644 AI \u0645\u06cc \u062a\u0648\u0627\u0646\u0646\u062f \u0628\u0647 \u0622\u0646 \u062f\u0633\u062a\u0631\u0633\u06cc \u067e\u06cc\u062f\u0627 \u06a9\u0646\u0646\u062f.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight typescript\"><code><span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">NextResponse<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">next\/server<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">OpenAI<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">openai<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"kd\">const<\/span> <span class=\"nx\">openai<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">OpenAI<\/span><span class=\"p\">();<\/span>\n\n<span class=\"c1\">\/\/ Define default functions that all agents can access<\/span>\n<span class=\"kd\">const<\/span> <span class=\"nx\">defaultFunctions<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span>\n  <span class=\"p\">{<\/span>\n    <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getUserProfile<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Get the user's profile information<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">fields<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">array<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">items<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n            <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">string<\/span><span class=\"dl\">\"<\/span>\n          <span class=\"p\">},<\/span>\n          <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Optional array of specific profile fields to retrieve<\/span><span class=\"dl\">\"<\/span>\n        <span class=\"p\">}<\/span>\n      <span class=\"p\">},<\/span>\n      <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[]<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">},<\/span>\n  <span class=\"p\">{<\/span>\n    <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getUserHabits<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Get the list of habits the user has created<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{},<\/span>\n      <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[]<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">},<\/span>\n  <span class=\"p\">{<\/span>\n    <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getHabitCompletions<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Get the list of habit completions for the past X days<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">daysAgo<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">number<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Get completions from this many days ago (default 30)<\/span><span class=\"dl\">\"<\/span>\n        <span class=\"p\">}<\/span>\n      <span class=\"p\">},<\/span>\n      <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[]<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">},<\/span>\n  <span class=\"p\">{<\/span>\n    <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">completeHabit<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Mark a habit as complete and award points to the user<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">habitId<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">string<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">The ID of the habit to mark as complete<\/span><span class=\"dl\">\"<\/span>\n        <span class=\"p\">}<\/span>\n      <span class=\"p\">},<\/span>\n      <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">habitId<\/span><span class=\"dl\">\"<\/span><span class=\"p\">]<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">},<\/span>\n  <span class=\"p\">{<\/span>\n    <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getUserStats<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Get the user's current points balance and streak information<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{},<\/span>\n      <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[]<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">},<\/span>\n  <span class=\"p\">{<\/span>\n    <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getUserRewards<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Get the list of rewards available to the user<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{},<\/span>\n      <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[]<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">},<\/span>\n  <span class=\"p\">{<\/span>\n    <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getRewardRedemptions<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Get the user's past reward redemptions<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">daysAgo<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">number<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Get redemptions from this many days ago (default 30)<\/span><span class=\"dl\">\"<\/span>\n        <span class=\"p\">}<\/span>\n      <span class=\"p\">},<\/span>\n      <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[]<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">},<\/span>\n  <span class=\"p\">{<\/span>\n    <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">redeemReward<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Redeem a reward for the user, deducting points from their balance<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">rewardId<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">string<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">The ID of the reward to redeem<\/span><span class=\"dl\">\"<\/span>\n        <span class=\"p\">}<\/span>\n      <span class=\"p\">},<\/span>\n      <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">rewardId<\/span><span class=\"dl\">\"<\/span><span class=\"p\">]<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">},<\/span>\n  <span class=\"p\">{<\/span>\n    <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">calculateBonusPoints<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Calculate bonus points based on streak, consistency, and habit difficulty<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">parameters<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">object<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">properties<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">habitId<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">string<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">The ID of the habit to calculate bonuses for<\/span><span class=\"dl\">\"<\/span>\n        <span class=\"p\">},<\/span>\n        <span class=\"na\">basePoints<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">number<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">The base points awarded for this habit<\/span><span class=\"dl\">\"<\/span>\n        <span class=\"p\">}<\/span>\n      <span class=\"p\">},<\/span>\n      <span class=\"na\">required<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">habitId<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">basePoints<\/span><span class=\"dl\">\"<\/span><span class=\"p\">]<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"p\">];<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<blockquote>\n<p>\u0645\u06a9\u0627\u0646 \u0641\u0627\u06cc\u0644: <code>app\/api\/chat\/completions\/route.ts<\/code><\/p>\n<\/blockquote>\n<h3><span class=\"ez-toc-section\" id=\"%DA%A9%D9%86%D8%AA%D8%B1%D9%84_%DA%A9%D9%86%D9%86%D8%AF%D9%87_%D9%85%D8%B3%DB%8C%D8%B1_API\"><\/span>\n<p>  \u06a9\u0646\u062a\u0631\u0644 \u06a9\u0646\u0646\u062f\u0647 \u0645\u0633\u06cc\u0631 API<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n[POST request]: \u062f\u0631\u062e\u0648\u0627\u0633\u062a API \u0631\u0627 \u0627\u0632 \u0645\u0634\u062a\u0631\u06cc \u0627\u0646\u062c\u0627\u0645 \u062f\u0647\u06cc\u062f.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight typescript\"><code><span class=\"k\">export<\/span> <span class=\"k\">async<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">POST<\/span><span class=\"p\">(<\/span><span class=\"nx\">req<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Request<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n    <span class=\"c1\">\/\/ Extract request parameters<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">model<\/span><span class=\"p\">,<\/span> <span class=\"nx\">messages<\/span><span class=\"p\">,<\/span> <span class=\"nx\">functions<\/span><span class=\"p\">,<\/span> <span class=\"nx\">function_call<\/span><span class=\"p\">,<\/span> <span class=\"nx\">userCache<\/span> <span class=\"p\">}<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">req<\/span><span class=\"p\">.<\/span><span class=\"nf\">json<\/span><span class=\"p\">();<\/span>\n\n    <span class=\"c1\">\/\/ Set up the completion options<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"na\">completionOptions<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">model<\/span><span class=\"p\">,<\/span>\n      <span class=\"nx\">messages<\/span><span class=\"p\">,<\/span>\n    <span class=\"p\">};<\/span>\n\n    <span class=\"c1\">\/\/ Use client-provided functions or default functions<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">functions<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">completionOptions<\/span><span class=\"p\">.<\/span><span class=\"nx\">functions<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">functions<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">else<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">completionOptions<\/span><span class=\"p\">.<\/span><span class=\"nx\">functions<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">defaultFunctions<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c1\">\/\/ Handle function_call parameter<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">function_call<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">completionOptions<\/span><span class=\"p\">.<\/span><span class=\"nx\">function_call<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">function_call<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">else<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">completionOptions<\/span><span class=\"p\">.<\/span><span class=\"nx\">function_call<\/span> <span class=\"o\">=<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">auto<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c1\">\/\/ Make the API call<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">completion<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">openai<\/span><span class=\"p\">.<\/span><span class=\"nx\">chat<\/span><span class=\"p\">.<\/span><span class=\"nx\">completions<\/span><span class=\"p\">.<\/span><span class=\"nf\">create<\/span><span class=\"p\">(<\/span><span class=\"nx\">completionOptions<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"c1\">\/\/ Check if the model has generated a function call<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">message<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">completion<\/span><span class=\"p\">.<\/span><span class=\"nx\">choices<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">].<\/span><span class=\"nx\">message<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">message<\/span><span class=\"p\">.<\/span><span class=\"nx\">function_call<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"c1\">\/\/ Handle the function call using cached data if available<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">functionResponse<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">handleFunctionCall<\/span><span class=\"p\">(<\/span><span class=\"nx\">message<\/span><span class=\"p\">.<\/span><span class=\"nx\">function_call<\/span><span class=\"p\">,<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">);<\/span>\n\n      <span class=\"c1\">\/\/ Add the function call and result to the messages for a follow-up<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">newMessages<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span>\n        <span class=\"p\">...<\/span><span class=\"nx\">messages<\/span><span class=\"p\">,<\/span>\n        <span class=\"p\">{<\/span>\n          <span class=\"na\">role<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">assistant<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">content<\/span><span class=\"p\">:<\/span> <span class=\"kc\">null<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">function_call<\/span><span class=\"p\">:<\/span> <span class=\"nx\">message<\/span><span class=\"p\">.<\/span><span class=\"nx\">function_call<\/span>\n        <span class=\"p\">},<\/span>\n        <span class=\"p\">{<\/span>\n          <span class=\"na\">role<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">function<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"nx\">message<\/span><span class=\"p\">.<\/span><span class=\"nx\">function_call<\/span><span class=\"p\">.<\/span><span class=\"nx\">name<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">content<\/span><span class=\"p\">:<\/span> <span class=\"nx\">functionResponse<\/span>\n        <span class=\"p\">}<\/span>\n      <span class=\"p\">];<\/span>\n\n      <span class=\"c1\">\/\/ Call the model again with the function result<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">followUpCompletion<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">openai<\/span><span class=\"p\">.<\/span><span class=\"nx\">chat<\/span><span class=\"p\">.<\/span><span class=\"nx\">completions<\/span><span class=\"p\">.<\/span><span class=\"nf\">create<\/span><span class=\"p\">({<\/span>\n        <span class=\"nx\">model<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">messages<\/span><span class=\"p\">:<\/span> <span class=\"nx\">newMessages<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">functions<\/span><span class=\"p\">:<\/span> <span class=\"nx\">completionOptions<\/span><span class=\"p\">.<\/span><span class=\"nx\">functions<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">function_call<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">auto<\/span><span class=\"dl\">'<\/span>\n      <span class=\"p\">});<\/span>\n\n      <span class=\"k\">return<\/span> <span class=\"nx\">NextResponse<\/span><span class=\"p\">.<\/span><span class=\"nf\">json<\/span><span class=\"p\">(<\/span><span class=\"nx\">followUpCompletion<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">message<\/span><span class=\"p\">.<\/span><span class=\"nx\">tool_calls<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"c1\">\/\/ Handle tool calls in the OpenAI format<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">toolResponse<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">handleToolCalls<\/span><span class=\"p\">(<\/span><span class=\"nx\">message<\/span><span class=\"p\">.<\/span><span class=\"nx\">tool_calls<\/span><span class=\"p\">,<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">);<\/span>\n\n      <span class=\"c1\">\/\/ Add the tool calls and result to messages for follow-up<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">newMessages<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span>\n        <span class=\"p\">...<\/span><span class=\"nx\">messages<\/span><span class=\"p\">,<\/span>\n        <span class=\"p\">{<\/span>\n          <span class=\"na\">role<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">assistant<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">content<\/span><span class=\"p\">:<\/span> <span class=\"kc\">null<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">tool_calls<\/span><span class=\"p\">:<\/span> <span class=\"nx\">message<\/span><span class=\"p\">.<\/span><span class=\"nx\">tool_calls<\/span>\n        <span class=\"p\">}<\/span>\n      <span class=\"p\">];<\/span>\n\n      <span class=\"c1\">\/\/ Add each tool response<\/span>\n      <span class=\"k\">for <\/span><span class=\"p\">(<\/span><span class=\"kd\">const<\/span> <span class=\"nx\">toolCall<\/span> <span class=\"k\">of<\/span> <span class=\"nx\">toolResponse<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">newMessages<\/span><span class=\"p\">.<\/span><span class=\"nf\">push<\/span><span class=\"p\">({<\/span>\n          <span class=\"na\">role<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">tool<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">tool_call_id<\/span><span class=\"p\">:<\/span> <span class=\"nx\">toolCall<\/span><span class=\"p\">.<\/span><span class=\"nx\">tool_call_id<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">content<\/span><span class=\"p\">:<\/span> <span class=\"nx\">toolCall<\/span><span class=\"p\">.<\/span><span class=\"nx\">content<\/span>\n        <span class=\"p\">});<\/span>\n      <span class=\"p\">}<\/span>\n\n      <span class=\"c1\">\/\/ Call the model again with the tool results<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">followUpCompletion<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">openai<\/span><span class=\"p\">.<\/span><span class=\"nx\">chat<\/span><span class=\"p\">.<\/span><span class=\"nx\">completions<\/span><span class=\"p\">.<\/span><span class=\"nf\">create<\/span><span class=\"p\">({<\/span>\n        <span class=\"nx\">model<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">messages<\/span><span class=\"p\">:<\/span> <span class=\"nx\">newMessages<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">tools<\/span><span class=\"p\">:<\/span> <span class=\"nx\">completionOptions<\/span><span class=\"p\">.<\/span><span class=\"nx\">functions<\/span><span class=\"p\">.<\/span><span class=\"nf\">map<\/span><span class=\"p\">((<\/span><span class=\"na\">fn<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">({<\/span> <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">function<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"na\">function<\/span><span class=\"p\">:<\/span> <span class=\"nx\">fn<\/span> <span class=\"p\">})),<\/span>\n        <span class=\"na\">tool_choice<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">auto<\/span><span class=\"dl\">'<\/span>\n      <span class=\"p\">});<\/span>\n\n      <span class=\"k\">return<\/span> <span class=\"nx\">NextResponse<\/span><span class=\"p\">.<\/span><span class=\"nf\">json<\/span><span class=\"p\">(<\/span><span class=\"nx\">followUpCompletion<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"nx\">NextResponse<\/span><span class=\"p\">.<\/span><span class=\"nf\">json<\/span><span class=\"p\">(<\/span><span class=\"nx\">completion<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Error in \/chat\/completions:<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">return<\/span> <span class=\"nx\">NextResponse<\/span><span class=\"p\">.<\/span><span class=\"nf\">json<\/span><span class=\"p\">({<\/span> <span class=\"na\">error<\/span><span class=\"p\">:<\/span> <span class=\"nx\">error<\/span><span class=\"p\">.<\/span><span class=\"nx\">message<\/span> <span class=\"p\">},<\/span> <span class=\"p\">{<\/span> <span class=\"na\">status<\/span><span class=\"p\">:<\/span> <span class=\"mi\">500<\/span> <span class=\"p\">});<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0627\u06af\u0631 \u062f\u0631 \u0628\u0627\u0644\u0627 \u0645\u062a\u0648\u062c\u0647 \u0634\u062f\u0647 \u0627\u06cc\u062f \u060c \u0645\u0627 \u0627\u0632 \u062f\u0627\u062f\u0647 \u0647\u0627\u06cc \u0630\u062e\u06cc\u0631\u0647 \u0634\u062f\u0647 \u06a9\u0627\u0631\u0628\u0631 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u06a9\u0646\u06cc\u0645. <br \/>\u0627\u0632 \u0622\u0646\u062c\u0627 \u06a9\u0647 IndexedBD \u0637\u0631\u0641 \u0645\u0634\u062a\u0631\u06cc \u0627\u0633\u062a \u060c \u0645\u0627 \u0628\u0627\u06cc\u062f \u062f\u0627\u062f\u0647 \u0647\u0627 \u0631\u0627 \u0628\u0647 \u0637\u0648\u0631 \u0645\u062a\u0641\u0627\u0648\u062a\u06cc \u0627\u062f\u0627\u0631\u0647 \u06a9\u0646\u06cc\u0645.<br \/>\u062f\u0631 \u063a\u06cc\u0631 \u0627\u06cc\u0646 \u0635\u0648\u0631\u062a \u060c \u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u0645\u062b\u0627\u0644 supabase \u060c \u0645\u0627 \u0627\u0632 \u062a\u0648\u0627\u0628\u0639 Edge \u0633\u0627\u062f\u0647 \u0628\u0631\u0627\u06cc \u0648\u0627\u06a9\u0634\u06cc \u062f\u0627\u062f\u0647 \u0647\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u06a9\u0646\u06cc\u0645.<\/p>\n<blockquote>\n<p>\u0645\u06a9\u0627\u0646 \u0641\u0627\u06cc\u0644: <code>app\/api\/chat\/completions\/route.ts<\/code><\/p>\n<\/blockquote>\n<h3><span class=\"ez-toc-section\" id=\"%D8%AA%D9%85%D8%A7%D8%B3_%D8%A8%D8%A7_%D8%B9%D9%85%D9%84%DA%A9%D8%B1%D8%AF_%D8%B9%D9%85%D9%84%DA%A9%D8%B1%D8%AF\"><\/span>\n<p>  \u062a\u0645\u0627\u0633 \u0628\u0627 \u0639\u0645\u0644\u06a9\u0631\u062f \u0639\u0645\u0644\u06a9\u0631\u062f<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u062a\u0645\u0627\u0633 \u0628\u0627 \u0639\u0645\u0644\u06a9\u0631\u062f \u0639\u0645\u0644\u06a9\u0631\u062f \u0628\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 \u062f\u0627\u062f\u0647 \u0647\u0627\u06cc \u0630\u062e\u06cc\u0631\u0647 \u0634\u062f\u0647.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight typescript\"><code><span class=\"k\">async<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">handleFunctionCall<\/span><span class=\"p\">(<\/span><span class=\"nx\">functionCall<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">,<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">name<\/span><span class=\"p\">,<\/span> <span class=\"na\">arguments<\/span><span class=\"p\">:<\/span> <span class=\"nx\">argsString<\/span> <span class=\"p\">}<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">functionCall<\/span><span class=\"p\">;<\/span>\n  <span class=\"kd\">let<\/span> <span class=\"nx\">args<\/span><span class=\"p\">;<\/span>\n\n  <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">args<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">parse<\/span><span class=\"p\">(<\/span><span class=\"nx\">argsString<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">e<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">return<\/span> <span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">stringify<\/span><span class=\"p\">({<\/span> <span class=\"na\">error<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Invalid function arguments<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">});<\/span>\n  <span class=\"p\">}<\/span>\n\n  <span class=\"c1\">\/\/ If we have userCache, use it for function responses<\/span>\n  <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">userCache<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">return<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">handleDatabaseFunction<\/span><span class=\"p\">(<\/span><span class=\"nx\">name<\/span><span class=\"p\">,<\/span> <span class=\"nx\">args<\/span><span class=\"p\">,<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">}<\/span>\n\n  <span class=\"c1\">\/\/ Otherwise return a message that the function isn't available without cached data<\/span>\n  <span class=\"k\">return<\/span> <span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">stringify<\/span><span class=\"p\">({<\/span>\n    <span class=\"na\">error<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">This function requires user data that is not currently available.<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">message<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Please try refreshing the page to load your latest data.<\/span><span class=\"dl\">\"<\/span>\n  <span class=\"p\">});<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"c1\">\/\/ Handle tool calls using cached data<\/span>\n<span class=\"k\">async<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">handleToolCalls<\/span><span class=\"p\">(<\/span><span class=\"nx\">toolCalls<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">,<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">responses<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[];<\/span>\n\n  <span class=\"k\">for <\/span><span class=\"p\">(<\/span><span class=\"kd\">const<\/span> <span class=\"nx\">toolCall<\/span> <span class=\"k\">of<\/span> <span class=\"nx\">toolCalls<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">toolCall<\/span><span class=\"p\">.<\/span><span class=\"kd\">type<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">function<\/span><span class=\"dl\">'<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">name<\/span><span class=\"p\">,<\/span> <span class=\"na\">arguments<\/span><span class=\"p\">:<\/span> <span class=\"nx\">argsString<\/span> <span class=\"p\">}<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">toolCall<\/span><span class=\"p\">.<\/span><span class=\"kd\">function<\/span><span class=\"p\">;<\/span>\n      <span class=\"kd\">let<\/span> <span class=\"nx\">args<\/span><span class=\"p\">;<\/span>\n\n      <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">args<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">parse<\/span><span class=\"p\">(<\/span><span class=\"nx\">argsString<\/span><span class=\"p\">);<\/span>\n      <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">e<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">responses<\/span><span class=\"p\">.<\/span><span class=\"nf\">push<\/span><span class=\"p\">({<\/span>\n          <span class=\"na\">tool_call_id<\/span><span class=\"p\">:<\/span> <span class=\"nx\">toolCall<\/span><span class=\"p\">.<\/span><span class=\"nx\">id<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">content<\/span><span class=\"p\">:<\/span> <span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">stringify<\/span><span class=\"p\">({<\/span> <span class=\"na\">error<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Invalid function arguments<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">})<\/span>\n        <span class=\"p\">});<\/span>\n        <span class=\"k\">continue<\/span><span class=\"p\">;<\/span>\n      <span class=\"p\">}<\/span>\n\n      <span class=\"kd\">const<\/span> <span class=\"nx\">result<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">handleDatabaseFunction<\/span><span class=\"p\">(<\/span><span class=\"nx\">name<\/span><span class=\"p\">,<\/span> <span class=\"nx\">args<\/span><span class=\"p\">,<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">);<\/span>\n      <span class=\"nx\">responses<\/span><span class=\"p\">.<\/span><span class=\"nf\">push<\/span><span class=\"p\">({<\/span>\n        <span class=\"na\">tool_call_id<\/span><span class=\"p\">:<\/span> <span class=\"nx\">toolCall<\/span><span class=\"p\">.<\/span><span class=\"nx\">id<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">content<\/span><span class=\"p\">:<\/span> <span class=\"nx\">result<\/span>\n      <span class=\"p\">});<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">}<\/span>\n\n  <span class=\"k\">return<\/span> <span class=\"nx\">responses<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<blockquote>\n<p>\u0645\u06a9\u0627\u0646 \u0641\u0627\u06cc\u0644: <code>app\/api\/chat\/completions\/route.ts<\/code><\/p>\n<\/blockquote>\n<h3><span class=\"ez-toc-section\" id=\"%D8%B9%D9%85%D9%84%DA%A9%D8%B1%D8%AF%D9%87%D8%A7%DB%8C_%D9%BE%D8%A7%DB%8C%DA%AF%D8%A7%D9%87_%D8%AF%D8%A7%D8%AF%D9%87_%D8%B1%D8%A7_%DA%A9%D9%86%D8%AA%D8%B1%D9%84_%DA%A9%D9%86%DB%8C%D8%AF\"><\/span>\n<p>  \u0639\u0645\u0644\u06a9\u0631\u062f\u0647\u0627\u06cc \u067e\u0627\u06cc\u06af\u0627\u0647 \u062f\u0627\u062f\u0647 \u0631\u0627 \u06a9\u0646\u062a\u0631\u0644 \u06a9\u0646\u06cc\u062f<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u06a9\u0646\u062a\u0631\u0644 \u06a9\u0646\u0646\u062f\u0647 \u0645\u0631\u06a9\u0632\u06cc \u0628\u0631\u0627\u06cc \u06a9\u0644\u06cc\u0647 \u062a\u0648\u0627\u0628\u0639 \u067e\u0627\u06cc\u06af\u0627\u0647 \u062f\u0627\u062f\u0647 \u0628\u0627 \u062d\u0627\u0641\u0638\u0647 \u0646\u0647\u0627\u0646 \u06a9\u0627\u0631\u0628\u0631.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight typescript\"><code><span class=\"k\">async<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">handleDatabaseFunction<\/span><span class=\"p\">(<\/span><span class=\"nx\">name<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">,<\/span> <span class=\"nx\">args<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">,<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">switch <\/span><span class=\"p\">(<\/span><span class=\"nx\">name<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">case<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getUserProfile<\/span><span class=\"dl\">\"<\/span><span class=\"p\">:<\/span>\n      <span class=\"c1\">\/\/ Return the user profile with optional field filtering<\/span>\n      <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">args<\/span><span class=\"p\">.<\/span><span class=\"nx\">fields<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nb\">Array<\/span><span class=\"p\">.<\/span><span class=\"nf\">isArray<\/span><span class=\"p\">(<\/span><span class=\"nx\">args<\/span><span class=\"p\">.<\/span><span class=\"nx\">fields<\/span><span class=\"p\">)<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">args<\/span><span class=\"p\">.<\/span><span class=\"nx\">fields<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">filteredProfile<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Record<\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">string<\/span><span class=\"p\">,<\/span> <span class=\"kr\">any<\/span><span class=\"o\">&gt;<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{};<\/span>\n        <span class=\"k\">for <\/span><span class=\"p\">(<\/span><span class=\"kd\">const<\/span> <span class=\"nx\">field<\/span> <span class=\"k\">of<\/span> <span class=\"nx\">args<\/span><span class=\"p\">.<\/span><span class=\"nx\">fields<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n          <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">profile<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">profile<\/span><span class=\"p\">[<\/span><span class=\"nx\">field<\/span><span class=\"p\">]<\/span> <span class=\"o\">!==<\/span> <span class=\"kc\">undefined<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n            <span class=\"nx\">filteredProfile<\/span><span class=\"p\">[<\/span><span class=\"nx\">field<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">profile<\/span><span class=\"p\">[<\/span><span class=\"nx\">field<\/span><span class=\"p\">];<\/span>\n          <span class=\"p\">}<\/span>\n        <span class=\"p\">}<\/span>\n        <span class=\"k\">return<\/span> <span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">stringify<\/span><span class=\"p\">(<\/span><span class=\"nx\">filteredProfile<\/span><span class=\"p\">);<\/span>\n      <span class=\"p\">}<\/span>\n      <span class=\"c1\">\/\/ Return the complete profile if no fields specified<\/span>\n      <span class=\"k\">return<\/span> <span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">stringify<\/span><span class=\"p\">(<\/span><span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">profile<\/span> <span class=\"o\">||<\/span> <span class=\"p\">{<\/span> <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Unknown User<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">});<\/span>\n\n    <span class=\"k\">case<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getUserHabits<\/span><span class=\"dl\">\"<\/span><span class=\"p\">:<\/span>\n      <span class=\"c1\">\/\/ Filter habits by category if specified<\/span>\n      <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">args<\/span><span class=\"p\">.<\/span><span class=\"nx\">category<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">habits<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">filteredHabits<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">habits<\/span><span class=\"p\">.<\/span><span class=\"nf\">filter<\/span><span class=\"p\">((<\/span><span class=\"nx\">habit<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">habit<\/span><span class=\"p\">.<\/span><span class=\"nx\">category<\/span> <span class=\"o\">===<\/span> <span class=\"nx\">args<\/span><span class=\"p\">.<\/span><span class=\"nx\">category<\/span><span class=\"p\">);<\/span>\n        <span class=\"k\">return<\/span> <span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">stringify<\/span><span class=\"p\">({<\/span>\n          <span class=\"na\">habits<\/span><span class=\"p\">:<\/span> <span class=\"nx\">filteredHabits<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">count<\/span><span class=\"p\">:<\/span> <span class=\"nx\">filteredHabits<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span>\n        <span class=\"p\">});<\/span>\n      <span class=\"p\">}<\/span>\n      <span class=\"c1\">\/\/ Return all habits if no category filter<\/span>\n      <span class=\"k\">return<\/span> <span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">stringify<\/span><span class=\"p\">({<\/span>\n        <span class=\"na\">habits<\/span><span class=\"p\">:<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">habits<\/span> <span class=\"o\">||<\/span> <span class=\"p\">[],<\/span>\n        <span class=\"na\">count<\/span><span class=\"p\">:<\/span> <span class=\"p\">(<\/span><span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">habits<\/span> <span class=\"o\">||<\/span> <span class=\"p\">[]).<\/span><span class=\"nx\">length<\/span>\n      <span class=\"p\">});<\/span>\n\n    <span class=\"k\">case<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getHabitCompletions<\/span><span class=\"dl\">\"<\/span><span class=\"p\">:<\/span>\n      <span class=\"c1\">\/\/ Get completions from the past X days<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">daysAgo<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">args<\/span><span class=\"p\">.<\/span><span class=\"nx\">daysAgo<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">30<\/span><span class=\"p\">;<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">cutoffDate<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">();<\/span>\n      <span class=\"nx\">cutoffDate<\/span><span class=\"p\">.<\/span><span class=\"nf\">setDate<\/span><span class=\"p\">(<\/span><span class=\"nx\">cutoffDate<\/span><span class=\"p\">.<\/span><span class=\"nf\">getDate<\/span><span class=\"p\">()<\/span> <span class=\"o\">-<\/span> <span class=\"nx\">daysAgo<\/span><span class=\"p\">);<\/span>\n\n      <span class=\"c1\">\/\/ Filter completions by date<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">filteredCompletions<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">completions<\/span>\n        <span class=\"p\">?<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">completions<\/span><span class=\"p\">.<\/span><span class=\"nf\">filter<\/span><span class=\"p\">(<\/span>\n            <span class=\"p\">(<\/span><span class=\"nx\">completion<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(<\/span><span class=\"nx\">completion<\/span><span class=\"p\">.<\/span><span class=\"nx\">completedAt<\/span><span class=\"p\">)<\/span> <span class=\"o\">&gt;=<\/span> <span class=\"nx\">cutoffDate<\/span>\n          <span class=\"p\">)<\/span>\n        <span class=\"p\">:<\/span> <span class=\"p\">[];<\/span>\n\n      <span class=\"k\">return<\/span> <span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">stringify<\/span><span class=\"p\">({<\/span>\n        <span class=\"na\">completions<\/span><span class=\"p\">:<\/span> <span class=\"nx\">filteredCompletions<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">count<\/span><span class=\"p\">:<\/span> <span class=\"nx\">filteredCompletions<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span>\n      <span class=\"p\">});<\/span>\n\n    <span class=\"k\">case<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getUserStats<\/span><span class=\"dl\">\"<\/span><span class=\"p\">:<\/span>\n      <span class=\"c1\">\/\/ Return points and streak<\/span>\n      <span class=\"k\">return<\/span> <span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">stringify<\/span><span class=\"p\">({<\/span>\n        <span class=\"na\">points<\/span><span class=\"p\">:<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">points<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">0<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">streak<\/span><span class=\"p\">:<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">streak<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">0<\/span>\n      <span class=\"p\">});<\/span>\n\n    <span class=\"k\">case<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getUserRewards<\/span><span class=\"dl\">\"<\/span><span class=\"p\">:<\/span>\n      <span class=\"c1\">\/\/ Return all rewards<\/span>\n      <span class=\"k\">return<\/span> <span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">stringify<\/span><span class=\"p\">({<\/span>\n        <span class=\"na\">rewards<\/span><span class=\"p\">:<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">rewards<\/span> <span class=\"o\">||<\/span> <span class=\"p\">[],<\/span>\n        <span class=\"na\">count<\/span><span class=\"p\">:<\/span> <span class=\"p\">(<\/span><span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">rewards<\/span> <span class=\"o\">||<\/span> <span class=\"p\">[]).<\/span><span class=\"nx\">length<\/span>\n      <span class=\"p\">});<\/span>\n\n    <span class=\"k\">case<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getRewardRedemptions<\/span><span class=\"dl\">\"<\/span><span class=\"p\">:<\/span>\n      <span class=\"c1\">\/\/ Get redemptions from the past X days<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">redemptionDaysAgo<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">args<\/span><span class=\"p\">.<\/span><span class=\"nx\">daysAgo<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">30<\/span><span class=\"p\">;<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">redemptionCutoffDate<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">();<\/span>\n      <span class=\"nx\">redemptionCutoffDate<\/span><span class=\"p\">.<\/span><span class=\"nf\">setDate<\/span><span class=\"p\">(<\/span><span class=\"nx\">redemptionCutoffDate<\/span><span class=\"p\">.<\/span><span class=\"nf\">getDate<\/span><span class=\"p\">()<\/span> <span class=\"o\">-<\/span> <span class=\"nx\">redemptionDaysAgo<\/span><span class=\"p\">);<\/span>\n\n      <span class=\"c1\">\/\/ Filter redemptions by date<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">filteredRedemptions<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">redemptions<\/span>\n        <span class=\"p\">?<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">redemptions<\/span><span class=\"p\">.<\/span><span class=\"nf\">filter<\/span><span class=\"p\">(<\/span>\n            <span class=\"p\">(<\/span><span class=\"nx\">redemption<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(<\/span><span class=\"nx\">redemption<\/span><span class=\"p\">.<\/span><span class=\"nx\">redeemedAt<\/span><span class=\"p\">)<\/span> <span class=\"o\">&gt;=<\/span> <span class=\"nx\">redemptionCutoffDate<\/span>\n          <span class=\"p\">)<\/span>\n        <span class=\"p\">:<\/span> <span class=\"p\">[];<\/span>\n\n      <span class=\"k\">return<\/span> <span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">stringify<\/span><span class=\"p\">({<\/span>\n        <span class=\"na\">redemptions<\/span><span class=\"p\">:<\/span> <span class=\"nx\">filteredRedemptions<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">count<\/span><span class=\"p\">:<\/span> <span class=\"nx\">filteredRedemptions<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span>\n      <span class=\"p\">});<\/span>\n\n    <span class=\"k\">case<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">getRecentActivity<\/span><span class=\"dl\">\"<\/span><span class=\"p\">:<\/span>\n      <span class=\"c1\">\/\/ Get recent activity with optional filtering<\/span>\n      <span class=\"kd\">let<\/span> <span class=\"nx\">activities<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">recentActivity<\/span> <span class=\"o\">||<\/span> <span class=\"p\">[];<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">limit<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">args<\/span><span class=\"p\">.<\/span><span class=\"nx\">limit<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">5<\/span><span class=\"p\">;<\/span>\n\n      <span class=\"c1\">\/\/ Filter by activity type if provided<\/span>\n      <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">args<\/span><span class=\"p\">.<\/span><span class=\"nx\">activityType<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">activities<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">activities<\/span><span class=\"p\">.<\/span><span class=\"nf\">filter<\/span><span class=\"p\">((<\/span><span class=\"nx\">activity<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">activity<\/span><span class=\"p\">.<\/span><span class=\"nx\">action<\/span> <span class=\"o\">===<\/span> <span class=\"nx\">args<\/span><span class=\"p\">.<\/span><span class=\"nx\">activityType<\/span><span class=\"p\">);<\/span>\n      <span class=\"p\">}<\/span>\n\n      <span class=\"k\">return<\/span> <span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">stringify<\/span><span class=\"p\">({<\/span>\n        <span class=\"na\">activities<\/span><span class=\"p\">:<\/span> <span class=\"nx\">activities<\/span><span class=\"p\">.<\/span><span class=\"nf\">slice<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"nx\">limit<\/span><span class=\"p\">),<\/span>\n        <span class=\"na\">count<\/span><span class=\"p\">:<\/span> <span class=\"nx\">activities<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span>\n      <span class=\"p\">});<\/span>\n\n    <span class=\"k\">case<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">completeHabit<\/span><span class=\"dl\">\"<\/span><span class=\"p\">:<\/span>\n      <span class=\"c1\">\/\/ This would normally update the database, but in this context<\/span>\n      <span class=\"c1\">\/\/ we're just returning a success message since we can't modify the DB from here<\/span>\n      <span class=\"k\">return<\/span> <span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">stringify<\/span><span class=\"p\">({<\/span>\n        <span class=\"na\">success<\/span><span class=\"p\">:<\/span> <span class=\"kc\">true<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">message<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Habit marked as complete (simulation only, database not updated)<\/span><span class=\"dl\">\"<\/span>\n      <span class=\"p\">});<\/span>\n\n    <span class=\"k\">case<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">redeemReward<\/span><span class=\"dl\">\"<\/span><span class=\"p\">:<\/span>\n      <span class=\"c1\">\/\/ This would normally update the database, but in this context<\/span>\n      <span class=\"c1\">\/\/ we're just returning a success message since we can't modify the DB from here<\/span>\n      <span class=\"k\">return<\/span> <span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">stringify<\/span><span class=\"p\">({<\/span>\n        <span class=\"na\">success<\/span><span class=\"p\">:<\/span> <span class=\"kc\">true<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">message<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Reward redeemed (simulation only, database not updated)<\/span><span class=\"dl\">\"<\/span>\n      <span class=\"p\">});<\/span>\n\n    <span class=\"k\">case<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">calculateBonusPoints<\/span><span class=\"dl\">\"<\/span><span class=\"p\">:<\/span>\n      <span class=\"c1\">\/\/ Get the habit from cache<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">habit<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">habits<\/span>\n        <span class=\"p\">?<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">habits<\/span><span class=\"p\">.<\/span><span class=\"nf\">find<\/span><span class=\"p\">((<\/span><span class=\"nx\">h<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">h<\/span><span class=\"p\">.<\/span><span class=\"nx\">id<\/span> <span class=\"o\">===<\/span> <span class=\"nx\">args<\/span><span class=\"p\">.<\/span><span class=\"nx\">habitId<\/span><span class=\"p\">)<\/span>\n        <span class=\"p\">:<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n\n      <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">habit<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">return<\/span> <span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">stringify<\/span><span class=\"p\">({<\/span>\n          <span class=\"na\">error<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Habit not found<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">bonusPoints<\/span><span class=\"p\">:<\/span> <span class=\"mi\">0<\/span>\n        <span class=\"p\">});<\/span>\n      <span class=\"p\">}<\/span>\n\n      <span class=\"c1\">\/\/ Calculate a simple bonus based on streak<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">streakBonus<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">min<\/span><span class=\"p\">(<\/span><span class=\"mi\">50<\/span><span class=\"p\">,<\/span> <span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">floor<\/span><span class=\"p\">(<\/span><span class=\"nx\">userCache<\/span><span class=\"p\">.<\/span><span class=\"nx\">streak<\/span> <span class=\"o\">\/<\/span> <span class=\"mi\">2<\/span><span class=\"p\">));<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">difficultyBonus<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">habit<\/span><span class=\"p\">.<\/span><span class=\"nx\">difficulty<\/span> <span class=\"p\">?<\/span> <span class=\"p\">(<\/span><span class=\"nx\">habit<\/span><span class=\"p\">.<\/span><span class=\"nx\">difficulty<\/span> <span class=\"o\">*<\/span> <span class=\"mi\">5<\/span><span class=\"p\">)<\/span> <span class=\"p\">:<\/span> <span class=\"mi\">0<\/span><span class=\"p\">;<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">totalBonus<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">streakBonus<\/span> <span class=\"o\">+<\/span> <span class=\"nx\">difficultyBonus<\/span><span class=\"p\">;<\/span>\n\n      <span class=\"k\">return<\/span> <span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">stringify<\/span><span class=\"p\">({<\/span>\n        <span class=\"na\">basePoints<\/span><span class=\"p\">:<\/span> <span class=\"nx\">args<\/span><span class=\"p\">.<\/span><span class=\"nx\">basePoints<\/span><span class=\"p\">,<\/span>\n        <span class=\"nx\">streakBonus<\/span><span class=\"p\">,<\/span>\n        <span class=\"nx\">difficultyBonus<\/span><span class=\"p\">,<\/span> \n        <span class=\"nx\">totalBonus<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">totalPoints<\/span><span class=\"p\">:<\/span> <span class=\"nx\">args<\/span><span class=\"p\">.<\/span><span class=\"nx\">basePoints<\/span> <span class=\"o\">+<\/span> <span class=\"nx\">totalBonus<\/span>\n      <span class=\"p\">});<\/span>\n\n    <span class=\"nl\">default<\/span><span class=\"p\">:<\/span>\n      <span class=\"k\">return<\/span> <span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">stringify<\/span><span class=\"p\">({<\/span>\n        <span class=\"na\">error<\/span><span class=\"p\">:<\/span> <span class=\"s2\">`Unknown function: <\/span><span class=\"p\">${<\/span><span class=\"nx\">name<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">message<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">This function is not supported.<\/span><span class=\"dl\">\"<\/span>\n      <span class=\"p\">});<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<blockquote>\n<p>\u0645\u06a9\u0627\u0646 \u0641\u0627\u06cc\u0644: <code>app\/api\/chat\/completions\/route.ts<\/code><\/p>\n<\/blockquote>\n<p>\u0645\u0627 \u0628\u0627 API \u06a9\u0627\u0645\u0644\u0627\u064b \u062a\u0645\u0627\u0645 \u0634\u062f\u0647 \u0627\u06cc\u0645.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"%D8%B3%D8%A7%D8%AE%D8%AA%D9%86_%D8%B9%D8%A7%D9%85%D9%84_WEI_AI\"><\/span>\n<p>  \u0633\u0627\u062e\u062a\u0646 \u0639\u0627\u0645\u0644 WEI AI<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0627\u0648\u0644\u06cc\u0646 \u0686\u06cc\u0632\u06cc \u06a9\u0647 \u0628\u0631\u0627\u06cc \u0648\u0627\u0631\u062f \u06a9\u0631\u062f\u0646 \u062a\u0645\u0627\u0645 \u0645\u0624\u0644\u0641\u0647 \u0647\u0627\u06cc UI \u0646\u06cc\u0627\u0632 \u062f\u0627\u0631\u06cc\u0645.<br \/><code>shadcn\/ui<\/code>\u0628\u0627 <code>motion-primitives<\/code>\u0648\u062a <code>prompt-kit<\/code>\u0628\u0634\u0631<br \/>\u0628\u0631\u0627\u06cc \u0627\u0646\u062c\u0627\u0645 \u0627\u06cc\u0646 \u06a9\u0627\u0631 \u060c \u0627\u06cc\u0646 \u062f\u0633\u062a\u0648\u0631 \u0631\u0627 \u062f\u0631 \u062a\u0631\u0645\u06cc\u0646\u0627\u0644 \u062e\u0648\u062f \u0627\u062c\u0631\u0627 \u06a9\u0646\u06cc\u062f:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code>npx shadcn@latest add <span class=\"nt\">--all<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0627\u06cc\u0646 \u0647\u0645\u0647 \u0627\u062c\u0632\u0627\u06cc Shadcn\/UI \u0631\u0627 \u0628\u0647 <code>components\/ui\/<\/code> \u067e\u0648\u0634\u0647<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code>npx shadcn@latest add <span class=\"nt\">--all<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0633\u067e\u0633 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f <code>motion-primitives<\/code>\u0628\u0634\u0631<br \/>\u0627\u0648\u0644 \u0646\u0635\u0628 <code>motion<\/code> \u062e\u0648\u062f<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code>npm <span class=\"nb\">install <\/span>motion\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0627\u06a9\u0646\u0648\u0646 \u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u0645 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0631\u062f\u0646 \u0627\u062c\u0632\u0627\u06cc \u06cc\u06a9 \u0628\u0647 \u06cc\u06a9 \u0631\u0627 \u0634\u0631\u0648\u0639 \u06a9\u0646\u06cc\u0645.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code>npx motion-primitives@latest add text-effect text-shimmer glow-effect\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>&#8230; \u0648 \u063a\u06cc\u0631\u0647<\/p>\n<p>\u0645\u0634\u0627\u0628\u0647 \u0628\u0627 <code>prompt-kit<\/code>\u0628\u0634\u0631<br \/>\u0645\u0627 \u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u0645 \u0627\u062c\u0632\u0627\u06cc \u0633\u0631\u06cc\u0639 \u06a9\u06cc\u062a \u0631\u0627 \u0628\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 Shadcn CLI \u0646\u0635\u0628 \u06a9\u0646\u06cc\u0645.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code>npx shadcn@latest add <span class=\"s2\">\"https:\/\/prompt-kit.com\/c\/[COMPONENT].json\"<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"%D8%B1%D8%A7%D8%A8%D8%B7_%DA%AF%D9%BE\"><\/span>\n<p>  \u0631\u0627\u0628\u0637 \u06af\u067e<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p><img decoding=\"async\" src=\"https:\/\/media2.dev.to\/dynamic\/image\/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto\/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fki7yiqo122u4bz76znxm.png\" alt=\"\u0648\u06cc\u0698\u06af\u06cc \u0647\u0627\u06cc \u0648\u06cc\" loading=\"lazy\" width=\"800\" height=\"450\" title=\"\"><\/p>\n<p>\u0631\u0627\u0628\u0637 \u0686\u062a \u0645\u0624\u0644\u0641\u0647 \u0627\u0635\u0644\u06cc \u0627\u0633\u062a \u06a9\u0647 \u067e\u06cc\u0627\u0645 \u0647\u0627\u06cc \u06af\u067e \u060c \u0648\u0631\u0648\u062f\u06cc \u0648 \u062a\u0627\u0631\u06cc\u062e \u0631\u0627 \u0627\u062f\u0627\u0631\u0647 \u0645\u06cc \u06a9\u0646\u062f.<\/p>\n<p>\u06cc\u06a9 \u0641\u0627\u06cc\u0644 \u062c\u062f\u06cc\u062f \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f <code>app\/components\/chat\/ChatInterface.tsx<\/code>\u0628\u0634\u0631<\/p>\n<p>\u062a\u0645\u0627\u0645 \u0645\u0624\u0644\u0641\u0647 \u0647\u0627\u06cc \u0644\u0627\u0632\u0645 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"dl\">\"<\/span><span class=\"s2\">use client<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">useState<\/span><span class=\"p\">,<\/span> <span class=\"nx\">useRef<\/span><span class=\"p\">,<\/span> <span class=\"nx\">useEffect<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">react<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">usePathname<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">next\/navigation<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">useChat<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/app\/contexts\/ChatContext<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">Card<\/span><span class=\"p\">,<\/span> <span class=\"nx\">CardFooter<\/span><span class=\"p\">,<\/span> <span class=\"nx\">CardHeader<\/span><span class=\"p\">,<\/span> <span class=\"nx\">CardTitle<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/components\/ui\/card<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">Button<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/components\/ui\/button<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">ScrollArea<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/components\/ui\/scroll-area<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">Avatar<\/span><span class=\"p\">,<\/span> <span class=\"nx\">AvatarFallback<\/span><span class=\"p\">,<\/span> <span class=\"nx\">AvatarImage<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/components\/ui\/avatar<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">ChatMessage<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/ChatMessage<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">ChatHistory<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/ChatHistory<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nx\">Drawer<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">DrawerContent<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">DrawerHeader<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">DrawerTitle<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">DrawerTrigger<\/span><span class=\"p\">,<\/span>\n<span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/components\/ui\/drawer<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">ChatInput<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">..\/chat-input\/chat-input<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">ArrowLeft<\/span><span class=\"p\">,<\/span> <span class=\"nx\">ListMagnifyingGlass<\/span><span class=\"p\">,<\/span> <span class=\"nx\">PencilSimpleLine<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@phosphor-icons\/react\/dist\/ssr<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">useRouter<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">next\/navigation<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">TextShimmer<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/components\/motion-primitives\/text-shimmer<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0631\u0627\u0628\u0637 \u06af\u067e \u060c \u0645\u062a\u063a\u06cc\u0631\u0647\u0627\u06cc \u062d\u0627\u0644\u062a \u0648 \u0631\u0648\u062a\u0631 \u0631\u0627 \u0627\u0648\u0644\u06cc\u0647 \u06a9\u0646\u06cc\u062f.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code>\n<span class=\"kr\">interface<\/span> <span class=\"nx\">ChatInterfaceProps<\/span> <span class=\"p\">{}<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">ChatInterface<\/span><span class=\"p\">({<\/span> <span class=\"p\">}:<\/span> <span class=\"nx\">ChatInterfaceProps<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">messages<\/span><span class=\"p\">,<\/span> <span class=\"nx\">isTyping<\/span><span class=\"p\">,<\/span> <span class=\"nx\">sendMessage<\/span><span class=\"p\">,<\/span> <span class=\"nx\">clearMessages<\/span><span class=\"p\">,<\/span> <span class=\"nx\">loadConversation<\/span><span class=\"p\">,<\/span> <span class=\"nx\">currentConversationId<\/span> <span class=\"p\">}<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useChat<\/span><span class=\"p\">();<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">inputValue<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setInputValue<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useState<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"\"<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">isSending<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setIsSending<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useState<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">isDrawerOpen<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setIsDrawerOpen<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useState<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">scrollAreaRef<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useRef<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">HTMLDivElement<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">pathname<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">usePathname<\/span><span class=\"p\">();<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">router<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useRouter<\/span><span class=\"p\">();<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0647\u0646\u06af\u0627\u0645 \u0627\u0641\u0632\u0648\u062f\u0646 \u067e\u06cc\u0627\u0645 \u0647\u0627\u06cc \u062c\u062f\u06cc\u062f \u060c UseEffect \u0631\u0627 \u0628\u0647 \u067e\u0627\u06cc\u06cc\u0646 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code>  <span class=\"c1\">\/\/ Scroll to bottom when messages change<\/span>\n  <span class=\"nf\">useEffect<\/span><span class=\"p\">(()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">scrollAreaRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">scrollAreaRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span><span class=\"p\">.<\/span><span class=\"nx\">scrollTop<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">scrollAreaRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span><span class=\"p\">.<\/span><span class=\"nx\">scrollHeight<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">},<\/span> <span class=\"p\">[<\/span><span class=\"nx\">messages<\/span><span class=\"p\">]);<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">handleSendMessage<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async <\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">inputValue<\/span><span class=\"p\">.<\/span><span class=\"nf\">trim<\/span><span class=\"p\">()<\/span> <span class=\"o\">||<\/span> <span class=\"nx\">isSending<\/span><span class=\"p\">)<\/span> <span class=\"k\">return<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"nf\">setIsSending<\/span><span class=\"p\">(<\/span><span class=\"kc\">true<\/span><span class=\"p\">);<\/span>\n    <span class=\"nf\">setInputValue<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"\"<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">await<\/span> <span class=\"nf\">sendMessage<\/span><span class=\"p\">(<\/span><span class=\"nx\">inputValue<\/span><span class=\"p\">.<\/span><span class=\"nf\">trim<\/span><span class=\"p\">());<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Failed to send message:<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">finally<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nf\">setIsSending<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">};<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u06cc\u06a9 \u062a\u0627\u0628\u0639 \u0631\u0627 \u0628\u0631\u0627\u06cc \u0628\u0627\u0631\u06af\u0630\u0627\u0631\u06cc \u0645\u06a9\u0627\u0644\u0645\u0627\u062a \u0642\u062f\u06cc\u0645\u06cc \u0627\u0632 \u067e\u0627\u06cc\u06af\u0627\u0647 \u062f\u0627\u062f\u0647 \u062a\u0639\u0631\u06cc\u0641 \u06a9\u0646\u06cc\u062f.<br \/><code>loadConversation()<\/code>  \u0627\u0632 <code>useChat<\/code> \u0647\u0648\u06a9 \u060c \u06a9\u0647 \u062a\u0648\u0633\u0637 <code>ChatContext<\/code>\u0628\u0627 <code>ChatProvider<\/code>\u0628\u0634\u0631<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code>  <span class=\"kd\">const<\/span> <span class=\"nx\">handleLoadConversation<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"nx\">conversation<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"c1\">\/\/ Load the conversation messages to the chat<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">conversation<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">conversation<\/span><span class=\"p\">.<\/span><span class=\"nx\">messages<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"c1\">\/\/ Exclude the welcome message (first message) from the conversation<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">messagesToLoad<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">conversation<\/span><span class=\"p\">.<\/span><span class=\"nx\">messages<\/span><span class=\"p\">.<\/span><span class=\"nf\">slice<\/span><span class=\"p\">(<\/span><span class=\"mi\">1<\/span><span class=\"p\">);<\/span>\n\n      <span class=\"c1\">\/\/ Load messages into the chat<\/span>\n      <span class=\"nf\">loadConversation<\/span><span class=\"p\">(<\/span><span class=\"nx\">messagesToLoad<\/span><span class=\"p\">);<\/span>\n\n      <span class=\"c1\">\/\/ Close drawer<\/span>\n      <span class=\"nf\">setIsDrawerOpen<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">};<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>UI \u0631\u0627 \u062a\u0639\u0631\u06cc\u0641 \u06a9\u0646\u06cc\u062f.<br \/>\u0645\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u06a9\u0646\u06cc\u0645 <code>Drawer<\/code> \u0628\u0631\u0627\u06cc \u0627\u0631\u0627\u0626\u0647 \u062a\u062c\u0631\u0628\u0647 \u062e\u0648\u0628 \u062a\u0627\u0631\u06cc\u062e \u0645\u06a9\u0627\u0644\u0645\u0647 \u0628\u0647 \u06a9\u0627\u0631\u0628\u0631.<br \/>\u0648 \u062c\u062f\u0627\u06af\u0627\u0646\u0647 <code>ChatInput<\/code> \u0645\u0624\u0644\u0641\u0647 \u0628\u0631\u0627\u06cc \u0631\u0633\u06cc\u062f\u06af\u06cc \u0628\u0647 \u0648\u0631\u0648\u062f\u06cc \u0686\u062a \u0686\u0646\u062f \u0645\u0646\u0638\u0648\u0631\u0647.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code>  <span class=\"k\">return <\/span><span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nc\">Card<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"s2\">`flex gap-4 bg-transparent border-none shadow-none flex-col p-2 h-[100dvh]`<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nc\">CardHeader<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"pb-0 pt-0 px-0 border-b border-border [.border-b]:pb-2\"<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"flex items-center justify-between\"<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nc\">CardTitle<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"flex items-center gap-2\"<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nc\">Button<\/span> \n              <span class=\"na\">variant<\/span><span class=\"p\">=<\/span><span class=\"s\">\"ghost\"<\/span> \n              <span class=\"na\">size<\/span><span class=\"p\">=<\/span><span class=\"s\">\"icon\"<\/span> \n              <span class=\"na\">onClick<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">router<\/span><span class=\"p\">.<\/span><span class=\"nf\">back<\/span><span class=\"p\">()<\/span><span class=\"si\">}<\/span>\n              <span class=\"na\">title<\/span><span class=\"p\">=<\/span><span class=\"s\">\"Back to dashboard\"<\/span>\n            <span class=\"p\">&gt;<\/span>\n              <span class=\"p\">&lt;<\/span><span class=\"nc\">ArrowLeft<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"size-4\"<\/span> <span class=\"p\">\/&gt;<\/span>\n            <span class=\"p\"\/><span class=\"nc\">Button<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nc\">Avatar<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"h-8 w-8 bg-gradient-to-br from-pink-500 to-rose-500\"<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"p\">&lt;<\/span><span class=\"nc\">AvatarImage<\/span> <span class=\"na\">src<\/span><span class=\"p\">=<\/span><span class=\"s\">\"\/wei-icon.png\"<\/span> <span class=\"na\">alt<\/span><span class=\"p\">=<\/span><span class=\"s\">\"Wei Icon\"<\/span> <span class=\"p\">\/&gt;<\/span>\n              <span class=\"p\">&lt;<\/span><span class=\"nc\">AvatarFallback<\/span><span class=\"p\">&gt;<\/span>WEI<span class=\"p\"\/><span class=\"nc\">AvatarFallback<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\"\/><span class=\"nc\">Avatar<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">span<\/span><span class=\"p\">&gt;<\/span>Chat with Wei<span class=\"p\"\/><span class=\"nt\">span<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\"\/><span class=\"nc\">CardTitle<\/span><span class=\"p\">&gt;<\/span>\n\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"flex items-center gap-2\"<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nc\">Drawer<\/span> <span class=\"na\">open<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">isDrawerOpen<\/span><span class=\"si\">}<\/span> <span class=\"na\">onOpenChange<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">setIsDrawerOpen<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"p\">&lt;<\/span><span class=\"nc\">DrawerTrigger<\/span> <span class=\"na\">asChild<\/span><span class=\"p\">&gt;<\/span>\n                <span class=\"p\">&lt;<\/span><span class=\"nc\">Button<\/span> \n                  <span class=\"na\">variant<\/span><span class=\"p\">=<\/span><span class=\"s\">\"ghost\"<\/span> \n                  <span class=\"na\">size<\/span><span class=\"p\">=<\/span><span class=\"s\">\"icon\"<\/span> \n                  <span class=\"na\">title<\/span><span class=\"p\">=<\/span><span class=\"s\">\"Chat History\"<\/span>\n                <span class=\"p\">&gt;<\/span>\n                  <span class=\"p\">&lt;<\/span><span class=\"nc\">ListMagnifyingGlass<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"size-4\"<\/span> <span class=\"p\">\/&gt;<\/span>\n                <span class=\"p\"\/><span class=\"nc\">Button<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"p\"\/><span class=\"nc\">DrawerTrigger<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"p\">&lt;<\/span><span class=\"nc\">DrawerContent<\/span><span class=\"p\">&gt;<\/span>\n                <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"mx-auto w-full max-w-sm\"<\/span><span class=\"p\">&gt;<\/span>\n                  <span class=\"p\">&lt;<\/span><span class=\"nc\">DrawerHeader<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"text-center\"<\/span><span class=\"p\">&gt;<\/span>\n                    <span class=\"p\">&lt;<\/span><span class=\"nc\">DrawerTitle<\/span><span class=\"p\">&gt;<\/span>Conversation History<span class=\"p\"\/><span class=\"nc\">DrawerTitle<\/span><span class=\"p\">&gt;<\/span>\n                  <span class=\"p\"\/><span class=\"nc\">DrawerHeader<\/span><span class=\"p\">&gt;<\/span>\n\n                  <span class=\"p\">&lt;<\/span><span class=\"nc\">ChatHistory<\/span> <span class=\"na\">onSelectConversation<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">handleLoadConversation<\/span><span class=\"si\">}<\/span> <span class=\"p\">\/&gt;<\/span>\n\n                <span class=\"p\"\/><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"p\"\/><span class=\"nc\">DrawerContent<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\"\/><span class=\"nc\">Drawer<\/span><span class=\"p\">&gt;<\/span>\n\n            <span class=\"p\">&lt;<\/span><span class=\"nc\">Button<\/span> <span class=\"na\">variant<\/span><span class=\"p\">=<\/span><span class=\"s\">\"ghost\"<\/span> <span class=\"na\">size<\/span><span class=\"p\">=<\/span><span class=\"s\">\"icon\"<\/span> <span class=\"na\">onClick<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">clearMessages<\/span><span class=\"si\">}<\/span> <span class=\"na\">title<\/span><span class=\"p\">=<\/span><span class=\"s\">\"Reset chat\"<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"p\">&lt;<\/span><span class=\"nc\">PencilSimpleLine<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"size-4\"<\/span> <span class=\"p\">\/&gt;<\/span>\n            <span class=\"p\"\/><span class=\"nc\">Button<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\"\/><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\"\/><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\"\/><span class=\"nc\">CardHeader<\/span><span class=\"p\">&gt;<\/span>\n\n      <span class=\"p\">&lt;<\/span><span class=\"nc\">ScrollArea<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"flex-1 px-0 overflow-y-auto\"<\/span> <span class=\"na\">ref<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">scrollAreaRef<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"space-y-4 py-4\"<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"si\">{<\/span><span class=\"nx\">messages<\/span><span class=\"p\">.<\/span><span class=\"nf\">map<\/span><span class=\"p\">((<\/span><span class=\"nx\">message<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">(<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nc\">ChatMessage<\/span> \n              <span class=\"na\">key<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">message<\/span><span class=\"p\">.<\/span><span class=\"nx\">id<\/span><span class=\"si\">}<\/span> \n              <span class=\"na\">message<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">message<\/span><span class=\"si\">}<\/span> \n            <span class=\"p\">\/&gt;<\/span>\n          <span class=\"p\">))<\/span><span class=\"si\">}<\/span>\n\n          <span class=\"si\">{<\/span><span class=\"nx\">isTyping<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"p\">(<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"flex items-center gap-2 animate-pulse\"<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"p\">&lt;<\/span><span class=\"nc\">Avatar<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"h-8 w-8 bg-gradient-to-br from-pink-500 to-rose-500\"<\/span><span class=\"p\">&gt;<\/span>\n                <span class=\"p\">&lt;<\/span><span class=\"nc\">AvatarImage<\/span> <span class=\"na\">src<\/span><span class=\"p\">=<\/span><span class=\"s\">\"\/wei-icon.png\"<\/span> <span class=\"na\">alt<\/span><span class=\"p\">=<\/span><span class=\"s\">\"Wei Icon\"<\/span> <span class=\"p\">\/&gt;<\/span>\n                <span class=\"p\">&lt;<\/span><span class=\"nc\">AvatarFallback<\/span><span class=\"p\">&gt;<\/span>WEI<span class=\"p\"\/><span class=\"nc\">AvatarFallback<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"p\"\/><span class=\"nc\">Avatar<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"p\">&lt;<\/span><span class=\"nt\">span<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"text-sm text-muted-foreground\"<\/span><span class=\"p\">&gt;<\/span>\n                <span class=\"p\">&lt;<\/span><span class=\"nc\">TextShimmer<\/span><span class=\"p\">&gt;<\/span>\n                  Wei is typing...\n                <span class=\"p\"\/><span class=\"nc\">TextShimmer<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"p\"\/><span class=\"nt\">span<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\"\/><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n        <span class=\"p\"\/><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\"\/><span class=\"nc\">ScrollArea<\/span><span class=\"p\">&gt;<\/span>\n\n      <span class=\"p\">&lt;<\/span><span class=\"nc\">CardFooter<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"pt-0 px-0 w-full\"<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nc\">ChatInput<\/span>\n          <span class=\"na\">value<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">inputValue<\/span><span class=\"si\">}<\/span>\n          <span class=\"na\">onValueChange<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">setInputValue<\/span><span class=\"si\">}<\/span>\n          <span class=\"na\">onSend<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">handleSendMessage<\/span><span class=\"si\">}<\/span>\n          <span class=\"na\">isSubmitting<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">isSending<\/span><span class=\"si\">}<\/span>\n          <span class=\"na\">files<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"p\">[]<\/span><span class=\"si\">}<\/span>\n          <span class=\"na\">onFileUpload<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{}<\/span><span class=\"si\">}<\/span>\n          <span class=\"na\">onFileRemove<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{}<\/span><span class=\"si\">}<\/span>\n          <span class=\"na\">stop<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{}<\/span><span class=\"si\">}<\/span>\n          <span class=\"na\">status<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">isSending<\/span> <span class=\"p\">?<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">submitted<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">ready<\/span><span class=\"dl\">\"<\/span><span class=\"si\">}<\/span>\n          <span class=\"na\">connected<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"kc\">true<\/span><span class=\"si\">}<\/span>\n          <span class=\"na\">partnerDisconnected<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"kc\">false<\/span><span class=\"si\">}<\/span>\n        <span class=\"p\">\/&gt;<\/span>\n      <span class=\"p\"\/><span class=\"nc\">CardFooter<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\"\/><span class=\"nc\">Card<\/span><span class=\"p\">&gt;<\/span>\n  <span class=\"p\">);<\/span>\n<span class=\"p\">}<\/span> \n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"%D9%88%D8%B1%D9%88%D8%AF%DB%8C_%DA%AF%D9%BE\"><\/span>\n<p>  \u0648\u0631\u0648\u062f\u06cc \u06af\u067e<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0648\u0631\u0648\u062f\u06cc \u0686\u062a \u0645\u0624\u0644\u0641\u0647 \u0627\u06cc \u0627\u0633\u062a \u06a9\u0647 \u0648\u0631\u0648\u062f\u06cc \u0686\u062a \u0686\u0646\u062f \u0645\u0646\u0638\u0648\u0631\u0647 \u0631\u0627 \u06a9\u0646\u062a\u0631\u0644 \u0645\u06cc \u06a9\u0646\u062f.<\/p>\n<p>\u06cc\u06a9 \u0641\u0627\u06cc\u0644 \u062c\u062f\u06cc\u062f \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f <code>app\/components\/chat-input\/chat-input.tsx<\/code>\u0628\u0634\u0631<\/p>\n<p>\u062a\u0645\u0627\u0645 \u0645\u0624\u0644\u0641\u0647 \u0647\u0627\u06cc \u0644\u0627\u0632\u0645 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"dl\">\"<\/span><span class=\"s2\">use client<\/span><span class=\"dl\">\"<\/span>\n\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nx\">PromptInput<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">PromptInputAction<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">PromptInputActions<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">PromptInputTextarea<\/span><span class=\"p\">,<\/span>\n<span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/components\/prompt-kit\/prompt-input<\/span><span class=\"dl\">\"<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">Button<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/components\/ui\/button<\/span><span class=\"dl\">\"<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">ArrowUp<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@phosphor-icons\/react\/dist\/ssr<\/span><span class=\"dl\">\"<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">React<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">useCallback<\/span><span class=\"p\">,<\/span> <span class=\"nx\">useEffect<\/span><span class=\"p\">,<\/span> <span class=\"nx\">useRef<\/span><span class=\"p\">,<\/span> <span class=\"nx\">useState<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">react<\/span><span class=\"dl\">\"<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">ButtonFileUpload<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/button-file-upload<\/span><span class=\"dl\">\"<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">ButtonVideoChat<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/button-video-chat<\/span><span class=\"dl\">\"<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">FileList<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/file-list<\/span><span class=\"dl\">\"<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">ButtonEmojiPicker<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/button-emoji-picker<\/span><span class=\"dl\">\"<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">ButtonGifPicker<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/button-gif-picker<\/span><span class=\"dl\">\"<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">toast<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">sonner<\/span><span class=\"dl\">\"<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">Stop<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@phosphor-icons\/react<\/span><span class=\"dl\">\"<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">ButtonRecord<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/button-record<\/span><span class=\"dl\">\"<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u063a\u0631\u0641\u0647 \u0647\u0627\u06cc \u0648\u0631\u0648\u062f\u06cc \u0686\u062a \u0631\u0627 \u062a\u0639\u0631\u06cc\u0641 \u06a9\u0646\u06cc\u062f.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"kd\">type<\/span> <span class=\"nx\">ChatInputProps<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n  <span class=\"na\">value<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span>\n  <span class=\"na\">onValueChange<\/span><span class=\"p\">:<\/span> <span class=\"p\">(<\/span><span class=\"na\">value<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"k\">void<\/span>\n  <span class=\"na\">onSend<\/span><span class=\"p\">:<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"k\">void<\/span>\n  <span class=\"nx\">isSubmitting<\/span><span class=\"p\">?:<\/span> <span class=\"nx\">boolean<\/span>\n  <span class=\"na\">files<\/span><span class=\"p\">:<\/span> <span class=\"nx\">File<\/span><span class=\"p\">[]<\/span>\n  <span class=\"na\">onFileUpload<\/span><span class=\"p\">:<\/span> <span class=\"p\">(<\/span><span class=\"na\">files<\/span><span class=\"p\">:<\/span> <span class=\"nx\">File<\/span><span class=\"p\">[])<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"k\">void<\/span>\n  <span class=\"na\">onFileRemove<\/span><span class=\"p\">:<\/span> <span class=\"p\">(<\/span><span class=\"na\">file<\/span><span class=\"p\">:<\/span> <span class=\"nx\">File<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"k\">void<\/span>\n  <span class=\"na\">stop<\/span><span class=\"p\">:<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"k\">void<\/span>\n  <span class=\"nx\">status<\/span><span class=\"p\">?:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">submitted<\/span><span class=\"dl\">\"<\/span> <span class=\"o\">|<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">streaming<\/span><span class=\"dl\">\"<\/span> <span class=\"o\">|<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">ready<\/span><span class=\"dl\">\"<\/span> <span class=\"o\">|<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">error<\/span><span class=\"dl\">\"<\/span>\n  <span class=\"nx\">connected<\/span><span class=\"p\">?:<\/span> <span class=\"nx\">boolean<\/span>\n  <span class=\"nx\">partnerDisconnected<\/span><span class=\"p\">?:<\/span> <span class=\"nx\">boolean<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0645\u0624\u0644\u0641\u0647 \u0648\u0631\u0648\u062f\u06cc \u0686\u062a \u0631\u0627 \u062a\u0639\u0631\u06cc\u0641 \u06a9\u0646\u06cc\u062f.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"k\">export<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">ChatInput<\/span><span class=\"p\">({<\/span>\n  <span class=\"nx\">value<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">onValueChange<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">onSend<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">isSubmitting<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">files<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">onFileUpload<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">onFileRemove<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">stop<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">status<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">connected<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">true<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">partnerDisconnected<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">false<\/span><span class=\"p\">,<\/span>\n<span class=\"p\">}:<\/span> <span class=\"nx\">ChatInputProps<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">textareaRef<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useRef<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">HTMLTextAreaElement<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n\n  <span class=\"c1\">\/\/ Textarea auto-resize<\/span>\n  <span class=\"nf\">useEffect<\/span><span class=\"p\">(()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">textarea<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">textareaRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">textarea<\/span><span class=\"p\">)<\/span> <span class=\"k\">return<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"kd\">const<\/span> <span class=\"nx\">adjustHeight<\/span> <span class=\"o\">=<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">textarea<\/span><span class=\"p\">.<\/span><span class=\"nx\">style<\/span><span class=\"p\">.<\/span><span class=\"nx\">height<\/span> <span class=\"o\">=<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">auto<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n      <span class=\"nx\">textarea<\/span><span class=\"p\">.<\/span><span class=\"nx\">style<\/span><span class=\"p\">.<\/span><span class=\"nx\">height<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">`<\/span><span class=\"p\">${<\/span><span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">min<\/span><span class=\"p\">(<\/span><span class=\"nx\">textarea<\/span><span class=\"p\">.<\/span><span class=\"nx\">scrollHeight<\/span><span class=\"p\">,<\/span> <span class=\"mi\">200<\/span><span class=\"p\">)}<\/span><span class=\"s2\">px`<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">};<\/span>\n\n    <span class=\"nx\">textarea<\/span><span class=\"p\">.<\/span><span class=\"nf\">addEventListener<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">input<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">adjustHeight<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"k\">return <\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">textarea<\/span><span class=\"p\">.<\/span><span class=\"nf\">removeEventListener<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">input<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">adjustHeight<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">};<\/span>\n  <span class=\"p\">},<\/span> <span class=\"p\">[]);<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">handleKeyDown<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useCallback<\/span><span class=\"p\">(<\/span>\n    <span class=\"p\">(<\/span><span class=\"nx\">e<\/span><span class=\"p\">:<\/span> <span class=\"nx\">React<\/span><span class=\"p\">.<\/span><span class=\"nx\">KeyboardEvent<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">isSubmitting<\/span><span class=\"p\">)<\/span> <span class=\"k\">return<\/span>\n\n      <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">e<\/span><span class=\"p\">.<\/span><span class=\"nx\">key<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Enter<\/span><span class=\"dl\">\"<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"o\">!<\/span><span class=\"nx\">e<\/span><span class=\"p\">.<\/span><span class=\"nx\">shiftKey<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">e<\/span><span class=\"p\">.<\/span><span class=\"nf\">preventDefault<\/span><span class=\"p\">()<\/span>\n        <span class=\"nf\">onSend<\/span><span class=\"p\">()<\/span>\n      <span class=\"p\">}<\/span>\n    <span class=\"p\">},<\/span>\n    <span class=\"p\">[<\/span><span class=\"nx\">onSend<\/span><span class=\"p\">,<\/span> <span class=\"nx\">isSubmitting<\/span><span class=\"p\">]<\/span>\n  <span class=\"p\">)<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">handleInputChange<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"nx\">newValue<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">pendingAttachment<\/span><span class=\"p\">)<\/span> <span class=\"k\">return<\/span><span class=\"p\">;<\/span> <span class=\"c1\">\/\/ Disable text input if image is selected<\/span>\n\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">newValue<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">1000<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nf\">toast<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Message too long<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span> \n        <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Please keep your message under 1000 characters.<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">duration<\/span><span class=\"p\">:<\/span> <span class=\"mi\">2000<\/span><span class=\"p\">,<\/span>\n      <span class=\"p\">});<\/span>\n      <span class=\"k\">return<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"nf\">onValueChange<\/span><span class=\"p\">(<\/span><span class=\"nx\">newValue<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">handleMainButtonClick<\/span> <span class=\"o\">=<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">isSubmitting<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">status<\/span> <span class=\"o\">!==<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">streaming<\/span><span class=\"dl\">\"<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">return<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">isSubmitting<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">status<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">streaming<\/span><span class=\"dl\">\"<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nf\">stop<\/span><span class=\"p\">();<\/span>\n      <span class=\"k\">return<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"nf\">onSend<\/span><span class=\"p\">();<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"k\">return <\/span><span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"w-full relative order-2 px-0 sm:px-0 pb-0 md:order-1\"<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nc\">PromptInput<\/span>\n          <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"s2\">`rounded-xl border-input bg-card\/80 relative z-10 overflow-hidden border p-0 pb-2 shadow-xs backdrop-blur-xl`<\/span><span class=\"si\">}<\/span>\n          <span class=\"na\">maxHeight<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"mi\">200<\/span><span class=\"si\">}<\/span>\n          <span class=\"na\">value<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">value<\/span><span class=\"si\">}<\/span>\n          <span class=\"na\">onValueChange<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">handleInputChange<\/span><span class=\"si\">}<\/span>\n        <span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nc\">FileList<\/span> <span class=\"na\">files<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">files<\/span><span class=\"si\">}<\/span> <span class=\"na\">onFileRemove<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">onFileRemove<\/span><span class=\"si\">}<\/span> <span class=\"p\">\/&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nc\">PromptInputTextarea<\/span>\n            <span class=\"na\">placeholder<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">connected<\/span> <span class=\"p\">?<\/span> <span class=\"p\">(<\/span><span class=\"nx\">files<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span> <span class=\"p\">?<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Image selected. Click send to share it.<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Type a message...<\/span><span class=\"dl\">\"<\/span><span class=\"p\">)<\/span> <span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Connect to start chatting...<\/span><span class=\"dl\">\"<\/span><span class=\"si\">}<\/span>\n            <span class=\"na\">onKeyDown<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">handleKeyDown<\/span><span class=\"si\">}<\/span>\n            <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"mt-2 ml-2 min-h-[44px] max-h-[150px] text-sm leading-[1.3] sm:text-sm md:text-sm placeholder:text-sm\"<\/span>\n            <span class=\"na\">disabled<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">isSubmitting<\/span> <span class=\"o\">||<\/span> <span class=\"nx\">files<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span> <span class=\"o\">||<\/span> <span class=\"nx\">pendingAttachment<\/span> <span class=\"o\">!==<\/span> <span class=\"kc\">null<\/span><span class=\"si\">}<\/span>\n            <span class=\"na\">ref<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">textareaRef<\/span><span class=\"si\">}<\/span>\n          <span class=\"p\">\/&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nc\">PromptInputActions<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"mt-1 w-full justify-between px-2\"<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"flex gap-2\"<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"si\">{<\/span><span class=\"cm\">\/* File Upload *\/<\/span><span class=\"si\">}<\/span>\n              <span class=\"si\">{<\/span><span class=\"cm\">\/* Emoji Picker *\/<\/span><span class=\"si\">}<\/span>\n              <span class=\"si\">{<\/span><span class=\"cm\">\/* GIF Picker *\/<\/span><span class=\"si\">}<\/span>\n            <span class=\"p\"\/><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"flex gap-2\"<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"si\">{<\/span><span class=\"cm\">\/* Video Chat Button *\/<\/span><span class=\"si\">}<\/span>\n              <span class=\"si\">{<\/span><span class=\"cm\">\/* Record Button *\/<\/span><span class=\"si\">}<\/span>\n              <span class=\"si\">{<\/span><span class=\"cm\">\/* Send Message Button *\/<\/span><span class=\"si\">}<\/span>\n              <span class=\"p\">&lt;<\/span><span class=\"nc\">PromptInputAction<\/span>\n                <span class=\"na\">tooltip<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">isSubmitting<\/span> <span class=\"p\">?<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Stop generating<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">:<\/span> <span class=\"p\">(<\/span><span class=\"nx\">value<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span> <span class=\"o\">||<\/span> <span class=\"nx\">files<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span> <span class=\"p\">?<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Send message<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Enter a message<\/span><span class=\"dl\">\"<\/span><span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n              <span class=\"p\">&gt;<\/span>\n                <span class=\"p\">&lt;<\/span><span class=\"nc\">Button<\/span>\n                  <span class=\"na\">variant<\/span><span class=\"p\">=<\/span><span class=\"s\">\"default\"<\/span>\n                  <span class=\"na\">size<\/span><span class=\"p\">=<\/span><span class=\"s\">\"icon\"<\/span>\n                  <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"s2\">`size-8 rounded-lg transition-all duration-300 ease-out <\/span><span class=\"p\">${<\/span><span class=\"nx\">isSubmitting<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">cursor-wait<\/span><span class=\"dl\">\"<\/span><span class=\"p\">}<\/span><span class=\"s2\"> <\/span><span class=\"p\">${(<\/span><span class=\"nx\">value<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span> <span class=\"o\">||<\/span> <span class=\"nx\">files<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span><span class=\"p\">)<\/span> <span class=\"p\">?<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">cursor-pointer<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">cursor-not-allowed<\/span><span class=\"dl\">\"<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span><span class=\"si\">}<\/span>\n                  <span class=\"na\">onClick<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">handleMainButtonClick<\/span><span class=\"si\">}<\/span>\n                  <span class=\"na\">disabled<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"o\">!<\/span><span class=\"p\">(<\/span><span class=\"nx\">value<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span> <span class=\"o\">||<\/span> <span class=\"nx\">files<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span><span class=\"p\">)<\/span> <span class=\"o\">||<\/span> <span class=\"o\">!<\/span><span class=\"nx\">connected<\/span> <span class=\"o\">||<\/span> <span class=\"nx\">partnerDisconnected<\/span> <span class=\"o\">||<\/span> <span class=\"p\">(<\/span><span class=\"nx\">isSubmitting<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">status<\/span> <span class=\"o\">!==<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">streaming<\/span><span class=\"dl\">\"<\/span><span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n                  <span class=\"na\">type<\/span><span class=\"p\">=<\/span><span class=\"s\">\"button\"<\/span>\n                  <span class=\"na\">aria-label<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">isSubmitting<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">status<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">streaming<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">?<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Stop generating<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Send message<\/span><span class=\"dl\">\"<\/span><span class=\"si\">}<\/span>\n                <span class=\"p\">&gt;<\/span>\n                  <span class=\"si\">{<\/span><span class=\"nx\">isSubmitting<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">status<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">streaming<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">?<\/span> <span class=\"p\">(<\/span>\n                    <span class=\"p\">&lt;<\/span><span class=\"nc\">Stop<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"size-4\"<\/span> <span class=\"na\">weight<\/span><span class=\"p\">=<\/span><span class=\"s\">\"fill\"<\/span><span class=\"p\">\/&gt;<\/span>\n                  <span class=\"p\">)<\/span> <span class=\"p\">:<\/span> <span class=\"p\">(<\/span>\n                    <span class=\"p\">&lt;<\/span><span class=\"nc\">ArrowUp<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"size-4\"<\/span> <span class=\"p\">\/&gt;<\/span>\n                  <span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n                <span class=\"p\"\/><span class=\"nc\">Button<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"p\"\/><span class=\"nc\">PromptInputAction<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\"\/><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\"\/><span class=\"nc\">PromptInputActions<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\"\/><span class=\"nc\">PromptInput<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\"\/><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&gt;<\/span>\n  <span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h4><span class=\"ez-toc-section\" id=\"%D9%BE%DB%8C%D8%B4%D8%B1%D9%81%D8%AA_%D9%87%D8%A7%DB%8C_%D8%A8%DB%8C%D8%B4%D8%AA%D8%B1_%D9%88%D8%B1%D9%88%D8%AF%DB%8C_%DA%86%D8%AA\"><\/span>\n<p>  \u067e\u06cc\u0634\u0631\u0641\u062a \u0647\u0627\u06cc \u0628\u06cc\u0634\u062a\u0631 (\u0648\u0631\u0648\u062f\u06cc \u0686\u062a)<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>\u0634\u0645\u0627 \u0645\u0645\u06a9\u0646 \u0627\u0633\u062a \u0627\u0642\u062f\u0627\u0645\u0627\u062a \u0648\u0631\u0648\u062f\u06cc \u0686\u062a \u0631\u0627 \u0628\u06cc\u0634\u062a\u0631 \u062a\u0642\u0648\u06cc\u062a \u06a9\u0646\u06cc\u062f.<\/p>\n<p>\u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u0645\u062b\u0627\u0644 \u0627\u0631\u0633\u0627\u0644 \u0627\u06cc\u0645\u0648\u062c\u06cc \u0647\u0627 \u0648 GIF. <br \/>\u062f\u06a9\u0645\u0647 \u0628\u0627\u0631\u06af\u0630\u0627\u0631\u06cc \u067e\u0631\u0648\u0646\u062f\u0647 \u0631\u0627 \u0642\u0631\u0627\u0631 \u062f\u0647\u06cc\u062f.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code>\n<span class=\"c1\">\/\/ functions<\/span>\n\n<span class=\"kd\">const<\/span> <span class=\"nx\">handleEmojiClick<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"nx\">emoji<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">log<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Handling emoji click in ChatInput:<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">emoji<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">pendingAttachment<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">log<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Ignoring emoji - pending attachment exists<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n      <span class=\"k\">return<\/span><span class=\"p\">;<\/span> <span class=\"c1\">\/\/ Disable emoji if image is selected<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n      <span class=\"c1\">\/\/ Get current cursor position<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">cursorPosition<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">textareaRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span><span class=\"p\">?.<\/span><span class=\"nx\">selectionStart<\/span> <span class=\"o\">||<\/span> <span class=\"nx\">value<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span><span class=\"p\">;<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">newValue<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">value<\/span><span class=\"p\">.<\/span><span class=\"nf\">slice<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"nx\">cursorPosition<\/span><span class=\"p\">)<\/span> <span class=\"o\">+<\/span> <span class=\"nx\">emoji<\/span> <span class=\"o\">+<\/span> <span class=\"nx\">value<\/span><span class=\"p\">.<\/span><span class=\"nf\">slice<\/span><span class=\"p\">(<\/span><span class=\"nx\">cursorPosition<\/span><span class=\"p\">);<\/span>\n\n      <span class=\"c1\">\/\/ Update value<\/span>\n      <span class=\"nf\">onValueChange<\/span><span class=\"p\">(<\/span><span class=\"nx\">newValue<\/span><span class=\"p\">);<\/span>\n\n      <span class=\"c1\">\/\/ Focus the textarea and set cursor position after the inserted emoji<\/span>\n      <span class=\"nf\">setTimeout<\/span><span class=\"p\">(()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">textareaRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n          <span class=\"nx\">textareaRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span><span class=\"p\">.<\/span><span class=\"nf\">focus<\/span><span class=\"p\">();<\/span>\n          <span class=\"kd\">const<\/span> <span class=\"nx\">newPosition<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">cursorPosition<\/span> <span class=\"o\">+<\/span> <span class=\"nx\">emoji<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span><span class=\"p\">;<\/span>\n          <span class=\"nx\">textareaRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span><span class=\"p\">.<\/span><span class=\"nf\">setSelectionRange<\/span><span class=\"p\">(<\/span><span class=\"nx\">newPosition<\/span><span class=\"p\">,<\/span> <span class=\"nx\">newPosition<\/span><span class=\"p\">);<\/span>\n        <span class=\"p\">}<\/span>\n      <span class=\"p\">},<\/span> <span class=\"mi\">10<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Error inserting emoji:<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">handleGifSelect<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"nx\">gif<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"c1\">\/\/ Fetch the GIF as a blob<\/span>\n    <span class=\"nf\">fetch<\/span><span class=\"p\">(<\/span><span class=\"nx\">gif<\/span><span class=\"p\">.<\/span><span class=\"nx\">images<\/span><span class=\"p\">.<\/span><span class=\"nx\">original<\/span><span class=\"p\">.<\/span><span class=\"nx\">url<\/span><span class=\"p\">)<\/span>\n      <span class=\"p\">.<\/span><span class=\"nf\">then<\/span><span class=\"p\">(<\/span><span class=\"nx\">response<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">response<\/span><span class=\"p\">.<\/span><span class=\"nx\">ok<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n          <span class=\"k\">throw<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Error<\/span><span class=\"p\">(<\/span><span class=\"s2\">`Failed to fetch GIF: <\/span><span class=\"p\">${<\/span><span class=\"nx\">response<\/span><span class=\"p\">.<\/span><span class=\"nx\">status<\/span><span class=\"p\">}<\/span><span class=\"s2\"> <\/span><span class=\"p\">${<\/span><span class=\"nx\">response<\/span><span class=\"p\">.<\/span><span class=\"nx\">statusText<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span><span class=\"p\">);<\/span>\n        <span class=\"p\">}<\/span>\n        <span class=\"k\">return<\/span> <span class=\"nx\">response<\/span><span class=\"p\">.<\/span><span class=\"nf\">blob<\/span><span class=\"p\">();<\/span>\n      <span class=\"p\">})<\/span>\n      <span class=\"p\">.<\/span><span class=\"nf\">then<\/span><span class=\"p\">(<\/span><span class=\"nx\">blob<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n        <span class=\"c1\">\/\/ Convert blob to file<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">file<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">File<\/span><span class=\"p\">([<\/span><span class=\"nx\">blob<\/span><span class=\"p\">],<\/span> <span class=\"s2\">`giphy-<\/span><span class=\"p\">${<\/span><span class=\"nx\">gif<\/span><span class=\"p\">.<\/span><span class=\"nx\">id<\/span><span class=\"p\">}<\/span><span class=\"s2\">.gif`<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span> <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">image\/gif<\/span><span class=\"dl\">'<\/span> <span class=\"p\">});<\/span>\n        <span class=\"nf\">onFileUpload<\/span><span class=\"p\">([<\/span><span class=\"nx\">file<\/span><span class=\"p\">]);<\/span>\n\n        <span class=\"nx\">toast<\/span><span class=\"p\">.<\/span><span class=\"nf\">success<\/span><span class=\"p\">(<\/span>\n          <span class=\"dl\">\"<\/span><span class=\"s2\">GIF selected<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">GIF ready to send. Click send to share it.<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">duration<\/span><span class=\"p\">:<\/span> <span class=\"mi\">2000<\/span><span class=\"p\">,<\/span>\n        <span class=\"p\">});<\/span>\n      <span class=\"p\">})<\/span>\n      <span class=\"p\">.<\/span><span class=\"k\">catch<\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">toast<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Failed to load GIF<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Please try another one.<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"p\">});<\/span>\n      <span class=\"p\">});<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"c1\">\/\/ UI<\/span>\n\n  <span class=\"p\">{<\/span><span class=\"cm\">\/* Emoji Picker *\/<\/span><span class=\"p\">}<\/span>\n  <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nc\">ButtonEmojiPicker<\/span>\n      <span class=\"na\">onEmojiSelect<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"p\">(<\/span><span class=\"nx\">emoji<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">log<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Emoji selected in chat input:<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">emoji<\/span><span class=\"p\">);<\/span>\n        <span class=\"nx\">toast<\/span><span class=\"p\">.<\/span><span class=\"nf\">info<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Emoji picker is Premium feature<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n        <span class=\"c1\">\/\/ handleEmojiClick(emoji);<\/span>\n      <span class=\"p\">}<\/span><span class=\"si\">}<\/span>\n      <span class=\"na\">disabled<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">isSubmitting<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">status<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">submitted<\/span><span class=\"dl\">\"<\/span><span class=\"si\">}<\/span>\n    <span class=\"p\">\/&gt;<\/span>\n  <span class=\"p\"\/><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n\n  <span class=\"p\">{<\/span><span class=\"cm\">\/* GIF Picker *\/<\/span><span class=\"p\">}<\/span>\n  <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nc\">ButtonGifPicker<\/span>\n      <span class=\"na\">onGifSelect<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"p\">(<\/span><span class=\"nx\">gif<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">log<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">GIF selected in chat input:<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">gif<\/span><span class=\"p\">.<\/span><span class=\"nx\">id<\/span><span class=\"p\">);<\/span>\n        <span class=\"nx\">toast<\/span><span class=\"p\">.<\/span><span class=\"nf\">info<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">GIF picker is Premium feature<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n        <span class=\"c1\">\/\/ handleGifSelect(gif);<\/span>\n      <span class=\"p\">}<\/span><span class=\"si\">}<\/span>\n      <span class=\"na\">disabled<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">isSubmitting<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">status<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">submitted<\/span><span class=\"dl\">\"<\/span><span class=\"si\">}<\/span>\n    <span class=\"p\">\/&gt;<\/span>\n  <span class=\"p\"\/><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u0645\u062b\u0627\u0644: \u067e\u062e\u0634 \u0641\u06cc\u0644\u0645 \u062f\u0631 \u0632\u0645\u0627\u0646 \u0648\u0627\u0642\u0639\u06cc \u0628\u0627 \u0639\u0648\u0627\u0645\u0644 AI.<br \/>\u06cc\u0627 \u0648\u06cc\u0698\u06af\u06cc \u0636\u0628\u0637 \u0635\u062f\u0627 \u0648 \u0631\u0648\u0646\u0648\u06cc\u0633\u06cc.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code>  <span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">useVideoChat<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">..\/video-chat\/video-chat-provider<\/span><span class=\"dl\">\"<\/span> \n\n  <span class=\"kd\">const<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">startVideoChat<\/span><span class=\"p\">,<\/span> <span class=\"nx\">isVideoChatActive<\/span> <span class=\"p\">}<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useVideoChat<\/span><span class=\"p\">();<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">handleStartVideoChat<\/span> <span class=\"o\">=<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">connected<\/span> <span class=\"o\">||<\/span> <span class=\"nx\">partnerDisconnected<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">toast<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Cannot start video chat<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">You need to be connected to start a video chat.<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"p\">});<\/span>\n      <span class=\"k\">return<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">partnerId<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">toast<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Cannot start video chat<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">No partner available for video chat.<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"p\">});<\/span>\n      <span class=\"k\">return<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c1\">\/\/ Start the video chat with partner info<\/span>\n    <span class=\"nf\">startVideoChat<\/span><span class=\"p\">(<\/span>\n      <span class=\"nx\">partnerId<\/span><span class=\"p\">,<\/span> \n      <span class=\"nx\">partnerUsername<\/span> <span class=\"o\">||<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Partner<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> \n      <span class=\"nx\">isGroupChat<\/span><span class=\"p\">,<\/span> \n      <span class=\"nx\">groupCode<\/span>\n    <span class=\"p\">);<\/span>\n\n    <span class=\"nx\">toast<\/span><span class=\"p\">.<\/span><span class=\"nf\">info<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Starting video chat<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Connecting to peer...<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"p\">});<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"c1\">\/\/ UI<\/span>\n    <span class=\"p\">{<\/span><span class=\"cm\">\/* Video Chat Button *\/<\/span><span class=\"p\">}<\/span>\n  <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nc\">ButtonVideoChat<\/span>\n      <span class=\"na\">onStartVideoChat<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">toast<\/span><span class=\"p\">.<\/span><span class=\"nf\">info<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Video chat is Premium feature<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n      <span class=\"p\">}<\/span><span class=\"si\">}<\/span>\n      <span class=\"na\">disabled<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"o\">!<\/span><span class=\"nx\">connected<\/span> <span class=\"o\">||<\/span> <span class=\"nx\">partnerDisconnected<\/span><span class=\"si\">}<\/span>\n    <span class=\"p\">\/&gt;<\/span>\n  <span class=\"p\"\/><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n\n  <span class=\"p\">{<\/span><span class=\"cm\">\/* Record Button *\/<\/span><span class=\"p\">}<\/span>\n  <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nc\">ButtonRecord<\/span>\n      <span class=\"na\">onStartRecord<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">toast<\/span><span class=\"p\">.<\/span><span class=\"nf\">info<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Record is Premium feature<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n      <span class=\"p\">}<\/span><span class=\"si\">}<\/span>\n      <span class=\"na\">onStopRecord<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">toast<\/span><span class=\"p\">.<\/span><span class=\"nf\">info<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Record is Premium feature<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n      <span class=\"p\">}<\/span><span class=\"si\">}<\/span>\n      <span class=\"na\">isPTTUserSpeaking<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"kc\">false<\/span><span class=\"si\">}<\/span>\n      <span class=\"na\">isConnected<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">connected<\/span><span class=\"si\">}<\/span>\n      <span class=\"na\">disabled<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"o\">!<\/span><span class=\"nx\">connected<\/span> <span class=\"o\">||<\/span> <span class=\"nx\">partnerDisconnected<\/span><span class=\"si\">}<\/span>\n    <span class=\"p\">\/&gt;<\/span>\n  <span class=\"p\"\/><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u067e\u0627\u0633\u062e \u0628\u0647 \u067e\u06cc\u0627\u0645 \u0647\u0627\u06cc previoes:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code>  <span class=\"c1\">\/\/ Display reply feedback in the input<\/span>\n  <span class=\"nf\">useEffect<\/span><span class=\"p\">(()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">currentReplyTo<\/span> <span class=\"o\">!==<\/span> <span class=\"kc\">undefined<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">textareaRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">textareaRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span><span class=\"p\">.<\/span><span class=\"nx\">placeholder<\/span> <span class=\"o\">=<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Type your reply...<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n      <span class=\"nx\">textareaRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span><span class=\"p\">.<\/span><span class=\"nf\">focus<\/span><span class=\"p\">();<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">},<\/span> <span class=\"p\">[<\/span><span class=\"nx\">currentReplyTo<\/span><span class=\"p\">]);<\/span>\n\n<span class=\"kd\">const<\/span> <span class=\"nx\">handleCancelReply<\/span> <span class=\"o\">=<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">setReplyTo<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nf\">setReplyTo<\/span><span class=\"p\">(<\/span><span class=\"kc\">undefined<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">};<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0648\u06cc\u0698\u06af\u06cc \u0628\u0627\u0631\u06af\u0630\u0627\u0631\u06cc \u0641\u0627\u06cc\u0644 \u0631\u0627 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f.<br \/>\u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u0645\u062b\u0627\u0644: \u06af\u0632\u0627\u0631\u0634 \u0627\u0632 \u0633\u0627\u0639\u062a\u0647\u0627\u06cc \u0647\u0648\u0634\u0645\u0646\u062f \u0648 \u063a\u06cc\u0631\u0647<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code>  <span class=\"c1\">\/\/ Helper to validate image file types<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">isValidImageFile<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"nx\">file<\/span><span class=\"p\">:<\/span> <span class=\"nx\">File<\/span><span class=\"p\">):<\/span> <span class=\"nx\">boolean<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">validTypes<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">image\/jpeg<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">image\/jpg<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">image\/png<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">image\/gif<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">image\/webp<\/span><span class=\"dl\">'<\/span><span class=\"p\">];<\/span>\n    <span class=\"k\">return<\/span> <span class=\"nx\">validTypes<\/span><span class=\"p\">.<\/span><span class=\"nf\">includes<\/span><span class=\"p\">(<\/span><span class=\"nx\">file<\/span><span class=\"p\">.<\/span><span class=\"kd\">type<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">pendingAttachment<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setPendingAttachment<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">File<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">pendingAttachmentUrl<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setPendingAttachmentUrl<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">string<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n\n  <span class=\"c1\">\/\/ Reset pending attachment when files are cleared<\/span>\n  <span class=\"nf\">useEffect<\/span><span class=\"p\">(()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">files<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">===<\/span> <span class=\"mi\">0<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">pendingAttachment<\/span> <span class=\"o\">!==<\/span> <span class=\"kc\">null<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nf\">setPendingAttachment<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n      <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">pendingAttachmentUrl<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">URL<\/span><span class=\"p\">.<\/span><span class=\"nf\">revokeObjectURL<\/span><span class=\"p\">(<\/span><span class=\"nx\">pendingAttachmentUrl<\/span><span class=\"p\">);<\/span>\n        <span class=\"nf\">setPendingAttachmentUrl<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n      <span class=\"p\">}<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">},<\/span> <span class=\"p\">[<\/span><span class=\"nx\">files<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span><span class=\"p\">,<\/span> <span class=\"nx\">pendingAttachment<\/span><span class=\"p\">,<\/span> <span class=\"nx\">pendingAttachmentUrl<\/span><span class=\"p\">]);<\/span>\n\n  <span class=\"c1\">\/\/ Additional effect to reset pending attachment when status changes to ready<\/span>\n  <span class=\"nf\">useEffect<\/span><span class=\"p\">(()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">status<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">ready<\/span><span class=\"dl\">\"<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"o\">!<\/span><span class=\"nx\">isSubmitting<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">pendingAttachment<\/span> <span class=\"o\">!==<\/span> <span class=\"kc\">null<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nf\">setPendingAttachment<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n      <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">pendingAttachmentUrl<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">URL<\/span><span class=\"p\">.<\/span><span class=\"nf\">revokeObjectURL<\/span><span class=\"p\">(<\/span><span class=\"nx\">pendingAttachmentUrl<\/span><span class=\"p\">);<\/span>\n        <span class=\"nf\">setPendingAttachmentUrl<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n      <span class=\"p\">}<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">},<\/span> <span class=\"p\">[<\/span><span class=\"nx\">status<\/span><span class=\"p\">,<\/span> <span class=\"nx\">isSubmitting<\/span><span class=\"p\">,<\/span> <span class=\"nx\">pendingAttachment<\/span><span class=\"p\">,<\/span> <span class=\"nx\">pendingAttachmentUrl<\/span><span class=\"p\">]);<\/span>\n\n  <span class=\"c1\">\/\/ Helper function to read file as ArrayBuffer for sending images<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">readFileAsArrayBuffer<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"nx\">file<\/span><span class=\"p\">:<\/span> <span class=\"nx\">File<\/span><span class=\"p\">):<\/span> <span class=\"nb\">Promise<\/span><span class=\"o\">&lt;<\/span><span class=\"nb\">ArrayBuffer<\/span><span class=\"o\">&gt;<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">return<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Promise<\/span><span class=\"p\">((<\/span><span class=\"nx\">resolve<\/span><span class=\"p\">,<\/span> <span class=\"nx\">reject<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">reader<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">FileReader<\/span><span class=\"p\">();<\/span>\n      <span class=\"nx\">reader<\/span><span class=\"p\">.<\/span><span class=\"nx\">onload<\/span> <span class=\"o\">=<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">reader<\/span><span class=\"p\">.<\/span><span class=\"nx\">result<\/span> <span class=\"k\">instanceof<\/span> <span class=\"nb\">ArrayBuffer<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n          <span class=\"nf\">resolve<\/span><span class=\"p\">(<\/span><span class=\"nx\">reader<\/span><span class=\"p\">.<\/span><span class=\"nx\">result<\/span><span class=\"p\">);<\/span>\n        <span class=\"p\">}<\/span> <span class=\"k\">else<\/span> <span class=\"p\">{<\/span>\n          <span class=\"nf\">reject<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Failed to read file as ArrayBuffer.<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n        <span class=\"p\">}<\/span>\n      <span class=\"p\">};<\/span>\n      <span class=\"nx\">reader<\/span><span class=\"p\">.<\/span><span class=\"nx\">onerror<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">reject<\/span><span class=\"p\">;<\/span>\n      <span class=\"nx\">reader<\/span><span class=\"p\">.<\/span><span class=\"nf\">readAsArrayBuffer<\/span><span class=\"p\">(<\/span><span class=\"nx\">file<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">});<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">handleFileUploadInternal<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"nx\">files<\/span><span class=\"p\">:<\/span> <span class=\"nx\">File<\/span><span class=\"p\">[])<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">file<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">files<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]<\/span> <span class=\"o\">||<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">file<\/span><span class=\"p\">)<\/span> <span class=\"k\">return<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"c1\">\/\/ we support only image files for now<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nf\">isValidImageFile<\/span><span class=\"p\">(<\/span><span class=\"nx\">file<\/span><span class=\"p\">))<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">toast<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Invalid file type<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Only JPG, PNG, GIF, and WEBP files are supported.<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"p\">});<\/span>\n      <span class=\"k\">return<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">file<\/span><span class=\"p\">.<\/span><span class=\"nx\">size<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">5<\/span> <span class=\"o\">*<\/span> <span class=\"mi\">1024<\/span> <span class=\"o\">*<\/span> <span class=\"mi\">1024<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">toast<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">File too large<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Maximum file size is 5MB.<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"p\">});<\/span>\n      <span class=\"k\">return<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"nf\">setPendingAttachment<\/span><span class=\"p\">(<\/span><span class=\"nx\">file<\/span><span class=\"p\">);<\/span>\n    <span class=\"nf\">setPendingAttachmentUrl<\/span><span class=\"p\">(<\/span><span class=\"nx\">URL<\/span><span class=\"p\">.<\/span><span class=\"nf\">createObjectURL<\/span><span class=\"p\">(<\/span><span class=\"nx\">file<\/span><span class=\"p\">));<\/span>\n    <span class=\"nf\">onFileUpload<\/span><span class=\"p\">(<\/span><span class=\"nx\">files<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"c1\">\/\/ UI<\/span>\n  <span class=\"p\">{<\/span><span class=\"cm\">\/* File Upload *\/<\/span><span class=\"p\">}<\/span>\n  <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nc\">ButtonFileUpload<\/span>\n      <span class=\"na\">onFileUpload<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">log<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">File upload in chat input<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n        <span class=\"nx\">toast<\/span><span class=\"p\">.<\/span><span class=\"nf\">info<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">File upload is Premium feature<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n        <span class=\"c1\">\/\/ handleFileUploadInternal<\/span>\n      <span class=\"p\">}<\/span><span class=\"si\">}<\/span>\n      <span class=\"na\">disabled<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">isSubmitting<\/span> <span class=\"o\">||<\/span> <span class=\"o\">!<\/span><span class=\"nx\">connected<\/span> <span class=\"o\">||<\/span> <span class=\"nx\">partnerDisconnected<\/span> <span class=\"o\">||<\/span> <span class=\"nx\">files<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span><span class=\"si\">}<\/span>\n    <span class=\"p\">\/&gt;<\/span>\n  <span class=\"p\"\/><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"%D8%A7%D8%B1%D8%A7%D8%A6%D9%87_%D8%AF%D9%87%D9%86%D8%AF%D9%87_%DA%AF%D9%BE\"><\/span>\n<p>  \u0627\u0631\u0627\u0626\u0647 \u062f\u0647\u0646\u062f\u0647 \u06af\u067e<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0627\u06cc\u0646 \u0632\u0645\u06cc\u0646\u0647 \u0628\u0631\u0627\u06cc \u062a\u0639\u0627\u0645\u0644 \u0628\u0627 \u06af\u067e \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u0634\u0648\u062f.<br \/>\u0627\u0632 \u0622\u0646 \u0628\u0631\u0627\u06cc \u062f\u0631\u06cc\u0627\u0641\u062a \u067e\u06cc\u0627\u0645 \u060c \u0627\u0631\u0633\u0627\u0644 \u067e\u06cc\u0627\u0645 \u0648 \u063a\u06cc\u0631\u0647 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u0634\u0648\u062f.<\/p>\n<p>\u06cc\u06a9 \u0641\u0627\u06cc\u0644 \u062c\u062f\u06cc\u062f \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f <code>app\/contexts\/ChatContext.tsx<\/code>\u0628\u0634\u0631<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"dl\">\"<\/span><span class=\"s2\">use client<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">import<\/span> <span class=\"nx\">React<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">createContext<\/span><span class=\"p\">,<\/span> <span class=\"nx\">useContext<\/span><span class=\"p\">,<\/span> <span class=\"nx\">useState<\/span><span class=\"p\">,<\/span> <span class=\"nx\">useCallback<\/span><span class=\"p\">,<\/span> <span class=\"nx\">useEffect<\/span><span class=\"p\">,<\/span> <span class=\"nx\">ReactNode<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">react<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">useDatabase<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">.\/DatabaseContext<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">useUserCache<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">.\/UserCacheContext<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n\n<span class=\"kr\">interface<\/span> <span class=\"nx\">Message<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">id<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">sender<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">user<\/span><span class=\"dl\">'<\/span> <span class=\"o\">|<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">wei<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">content<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">timestamp<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Date<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"c1\">\/\/ Define the OpenAI message format<\/span>\n<span class=\"kr\">interface<\/span> <span class=\"nx\">OpenAIMessage<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">role<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">user<\/span><span class=\"dl\">'<\/span> <span class=\"o\">|<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">assistant<\/span><span class=\"dl\">'<\/span> <span class=\"o\">|<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">system<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">content<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"kr\">interface<\/span> <span class=\"nx\">ChatContextType<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">messages<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Message<\/span><span class=\"p\">[];<\/span>\n  <span class=\"nl\">isTyping<\/span><span class=\"p\">:<\/span> <span class=\"nx\">boolean<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">error<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">sendMessage<\/span><span class=\"p\">:<\/span> <span class=\"p\">(<\/span><span class=\"nx\">content<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nb\">Promise<\/span><span class=\"o\">&lt;<\/span><span class=\"k\">void<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">clearMessages<\/span><span class=\"p\">:<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"k\">void<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">getWeiResponse<\/span><span class=\"p\">:<\/span> <span class=\"p\">(<\/span><span class=\"nx\">content<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">,<\/span> <span class=\"nx\">agentName<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nb\">Promise<\/span><span class=\"o\">&lt;<\/span><span class=\"k\">void<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">loadConversation<\/span><span class=\"p\">:<\/span> <span class=\"p\">(<\/span><span class=\"nx\">conversationMessages<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Message<\/span><span class=\"p\">[],<\/span> <span class=\"nx\">conversationId<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"k\">void<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">currentConversationId<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"kd\">const<\/span> <span class=\"nx\">ChatContext<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">createContext<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">ChatContextType<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kd\">const<\/span> <span class=\"nx\">useChat<\/span> <span class=\"o\">=<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">context<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useContext<\/span><span class=\"p\">(<\/span><span class=\"nx\">ChatContext<\/span><span class=\"p\">);<\/span>\n  <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">context<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">throw<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">useChat must be used within a ChatProvider<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">}<\/span>\n  <span class=\"k\">return<\/span> <span class=\"nx\">context<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">};<\/span>\n\n<span class=\"c1\">\/\/ Helper function to convert our Message[] format to OpenAI's expected format<\/span>\n<span class=\"kd\">const<\/span> <span class=\"nx\">formatMessagesForAPI<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"nx\">messages<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Array<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">Message<\/span> <span class=\"o\">|<\/span> <span class=\"p\">{<\/span> <span class=\"na\">role<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span> <span class=\"nl\">content<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span> <span class=\"p\">}<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">):<\/span> <span class=\"nx\">OpenAIMessage<\/span><span class=\"p\">[]<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">return<\/span> <span class=\"nx\">messages<\/span><span class=\"p\">.<\/span><span class=\"nf\">map<\/span><span class=\"p\">(<\/span><span class=\"nx\">msg<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">sender<\/span><span class=\"dl\">'<\/span> <span class=\"k\">in<\/span> <span class=\"nx\">msg<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"c1\">\/\/ Convert our Message format to OpenAI format<\/span>\n      <span class=\"k\">return<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">role<\/span><span class=\"p\">:<\/span> <span class=\"nx\">msg<\/span><span class=\"p\">.<\/span><span class=\"nx\">sender<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">wei<\/span><span class=\"dl\">'<\/span> <span class=\"p\">?<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">assistant<\/span><span class=\"dl\">'<\/span> <span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">user<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">content<\/span><span class=\"p\">:<\/span> <span class=\"nx\">msg<\/span><span class=\"p\">.<\/span><span class=\"nx\">content<\/span>\n      <span class=\"p\">};<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">else<\/span> <span class=\"p\">{<\/span>\n      <span class=\"c1\">\/\/ Already in the expected format<\/span>\n      <span class=\"k\">return<\/span> <span class=\"nx\">msg<\/span> <span class=\"k\">as<\/span> <span class=\"nx\">OpenAIMessage<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">});<\/span>\n<span class=\"p\">};<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kd\">const<\/span> <span class=\"nx\">ChatProvider<\/span><span class=\"p\">:<\/span> <span class=\"nx\">React<\/span><span class=\"p\">.<\/span><span class=\"nx\">FC<\/span><span class=\"o\">&lt;<\/span><span class=\"p\">{<\/span> <span class=\"na\">children<\/span><span class=\"p\">:<\/span> <span class=\"nx\">ReactNode<\/span> <span class=\"p\">}<\/span><span class=\"o\">&gt;<\/span> <span class=\"o\">=<\/span> <span class=\"p\">({<\/span> <span class=\"nx\">children<\/span> <span class=\"p\">})<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">saveConversation<\/span><span class=\"p\">,<\/span> <span class=\"nx\">getConversations<\/span> <span class=\"p\">}<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useDatabase<\/span><span class=\"p\">();<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">cache<\/span><span class=\"p\">,<\/span> <span class=\"nx\">refreshCache<\/span> <span class=\"p\">}<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useUserCache<\/span><span class=\"p\">();<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">messages<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setMessages<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">Message<\/span><span class=\"p\">[]<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">([]);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">isTyping<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setIsTyping<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useState<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">error<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setError<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">string<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">currentConversationId<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setCurrentConversationId<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">string<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">pendingUserMessage<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setPendingUserMessage<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">Message<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n\n  <span class=\"c1\">\/\/ Initialize with welcome message<\/span>\n  <span class=\"nf\">useEffect<\/span><span class=\"p\">(()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"na\">welcomeMessage<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Message<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">id<\/span><span class=\"p\">:<\/span> <span class=\"s2\">`msg_<\/span><span class=\"p\">${<\/span><span class=\"nb\">Date<\/span><span class=\"p\">.<\/span><span class=\"nf\">now<\/span><span class=\"p\">()}<\/span><span class=\"s2\">`<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">sender<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">wei<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">content<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Hi there! <\/span><span class=\"se\">\\n<\/span><span class=\"s2\">I'm **Wei**, your personal habit assistant. _How can I help you today?_<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">timestamp<\/span><span class=\"p\">:<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">()<\/span>\n    <span class=\"p\">};<\/span>\n    <span class=\"nf\">setMessages<\/span><span class=\"p\">([<\/span><span class=\"nx\">welcomeMessage<\/span><span class=\"p\">]);<\/span>\n  <span class=\"p\">},<\/span> <span class=\"p\">[]);<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">saveCurrentConversation<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useCallback<\/span><span class=\"p\">(<\/span><span class=\"k\">async <\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">messages<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">&lt;=<\/span> <span class=\"mi\">1<\/span><span class=\"p\">)<\/span> <span class=\"k\">return<\/span><span class=\"p\">;<\/span> <span class=\"c1\">\/\/ Don't save if only welcome message exists<\/span>\n\n    <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">currentConversationId<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"c1\">\/\/ Update existing conversation<\/span>\n        <span class=\"k\">await<\/span> <span class=\"nf\">saveConversation<\/span><span class=\"p\">(<\/span><span class=\"nx\">messages<\/span><span class=\"p\">,<\/span> <span class=\"nx\">currentConversationId<\/span><span class=\"p\">);<\/span>\n      <span class=\"p\">}<\/span> <span class=\"k\">else<\/span> <span class=\"p\">{<\/span>\n        <span class=\"c1\">\/\/ Create new conversation<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">newId<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">saveConversation<\/span><span class=\"p\">(<\/span><span class=\"nx\">messages<\/span><span class=\"p\">);<\/span>\n        <span class=\"nf\">setCurrentConversationId<\/span><span class=\"p\">(<\/span><span class=\"nx\">newId<\/span><span class=\"p\">);<\/span>\n      <span class=\"p\">}<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">err<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Error saving conversation:<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">err<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">},<\/span> <span class=\"p\">[<\/span><span class=\"nx\">messages<\/span><span class=\"p\">,<\/span> <span class=\"nx\">currentConversationId<\/span><span class=\"p\">,<\/span> <span class=\"nx\">saveConversation<\/span><span class=\"p\">]);<\/span>\n\n  <span class=\"c1\">\/\/ Save conversation whenever messages change (but after the initial welcome message)<\/span>\n  <span class=\"nf\">useEffect<\/span><span class=\"p\">(()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">messages<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">1<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nf\">saveCurrentConversation<\/span><span class=\"p\">();<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">},<\/span> <span class=\"p\">[<\/span><span class=\"nx\">messages<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span><span class=\"p\">,<\/span> <span class=\"nx\">saveCurrentConversation<\/span><span class=\"p\">]);<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">getWeiResponse<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useCallback<\/span><span class=\"p\">(<\/span><span class=\"k\">async <\/span><span class=\"p\">(<\/span><span class=\"na\">content<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">,<\/span> <span class=\"nx\">agentName<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nf\">setIsTyping<\/span><span class=\"p\">(<\/span><span class=\"kc\">true<\/span><span class=\"p\">);<\/span>\n    <span class=\"nf\">setError<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n      <span class=\"c1\">\/\/ Refresh the cache to ensure we have the latest data<\/span>\n      <span class=\"k\">await<\/span> <span class=\"nf\">refreshCache<\/span><span class=\"p\">();<\/span>\n\n      <span class=\"c1\">\/\/ Get the current messages from state<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">currentMessages<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[...<\/span><span class=\"nx\">messages<\/span><span class=\"p\">];<\/span>\n\n      <span class=\"c1\">\/\/ Format messages for the API<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">formattedMessages<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">formatMessagesForAPI<\/span><span class=\"p\">(<\/span><span class=\"nx\">currentMessages<\/span><span class=\"p\">);<\/span>\n\n      <span class=\"c1\">\/\/ Get the agent config if specified<\/span>\n      <span class=\"kd\">let<\/span> <span class=\"nx\">functions<\/span><span class=\"p\">;<\/span>\n      <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">agentName<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n          <span class=\"kd\">const<\/span> <span class=\"nx\">agentModule<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"k\">import<\/span><span class=\"p\">(<\/span><span class=\"s2\">`..\/agentConfigs\/wellbeing\/<\/span><span class=\"p\">${<\/span><span class=\"nx\">agentName<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span><span class=\"p\">);<\/span>\n          <span class=\"nx\">functions<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">agentModule<\/span><span class=\"p\">.<\/span><span class=\"k\">default<\/span><span class=\"p\">?.<\/span><span class=\"nx\">functions<\/span><span class=\"p\">;<\/span>\n        <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">err<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n          <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"s2\">`Failed to load agent config: <\/span><span class=\"p\">${<\/span><span class=\"nx\">agentName<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span><span class=\"p\">,<\/span> <span class=\"nx\">err<\/span><span class=\"p\">);<\/span>\n        <span class=\"p\">}<\/span>\n      <span class=\"p\">}<\/span>\n\n      <span class=\"c1\">\/\/ Create a minimal user context system message if there isn't one already<\/span>\n      <span class=\"kd\">let<\/span> <span class=\"nx\">hasSystemMessage<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">false<\/span><span class=\"p\">;<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">updatedMessages<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[...<\/span><span class=\"nx\">formattedMessages<\/span><span class=\"p\">];<\/span>\n\n      <span class=\"k\">for <\/span><span class=\"p\">(<\/span><span class=\"kd\">const<\/span> <span class=\"nx\">message<\/span> <span class=\"k\">of<\/span> <span class=\"nx\">updatedMessages<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">message<\/span><span class=\"p\">.<\/span><span class=\"nx\">role<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">system<\/span><span class=\"dl\">'<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n          <span class=\"nx\">hasSystemMessage<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">true<\/span><span class=\"p\">;<\/span>\n          <span class=\"k\">break<\/span><span class=\"p\">;<\/span>\n        <span class=\"p\">}<\/span>\n      <span class=\"p\">}<\/span>\n\n      <span class=\"c1\">\/\/ Add minimal context if no system message exists<\/span>\n      <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">hasSystemMessage<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">cache<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"c1\">\/\/ Create a more descriptive system message with basic user info<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"na\">minimalContext<\/span><span class=\"p\">:<\/span> <span class=\"nx\">OpenAIMessage<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">role<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">system<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">content<\/span><span class=\"p\">:<\/span> <span class=\"s2\">`You are Wei, a helpful habit-building assistant. \nThe user's name is <\/span><span class=\"p\">${<\/span><span class=\"nx\">cache<\/span><span class=\"p\">.<\/span><span class=\"nx\">profile<\/span><span class=\"p\">?.<\/span><span class=\"nx\">name<\/span> <span class=\"o\">||<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">User<\/span><span class=\"dl\">'<\/span><span class=\"p\">}<\/span><span class=\"s2\">.\nThey currently have <\/span><span class=\"p\">${<\/span><span class=\"nx\">cache<\/span><span class=\"p\">.<\/span><span class=\"nx\">points<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">0<\/span><span class=\"p\">}<\/span><span class=\"s2\"> points and a streak of <\/span><span class=\"p\">${<\/span><span class=\"nx\">cache<\/span><span class=\"p\">.<\/span><span class=\"nx\">streak<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">0<\/span><span class=\"p\">}<\/span><span class=\"s2\"> days.\nThey have <\/span><span class=\"p\">${<\/span><span class=\"nx\">cache<\/span><span class=\"p\">.<\/span><span class=\"nx\">habits<\/span><span class=\"p\">?.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">0<\/span><span class=\"p\">}<\/span><span class=\"s2\"> active habits.\nUse getUserProfile, getUserStats, getUserHabits and other user data functions to get more details when needed.`<\/span>\n        <span class=\"p\">};<\/span>\n        <span class=\"nx\">updatedMessages<\/span><span class=\"p\">.<\/span><span class=\"nf\">unshift<\/span><span class=\"p\">(<\/span><span class=\"nx\">minimalContext<\/span><span class=\"p\">);<\/span>\n      <span class=\"p\">}<\/span>\n\n      <span class=\"c1\">\/\/ Make the API call - include userCache for function calling<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">response<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">fetch<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">\/api\/chat\/completions<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">method<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">POST<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">headers<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"dl\">'<\/span><span class=\"s1\">Content-Type<\/span><span class=\"dl\">'<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">application\/json<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n        <span class=\"p\">},<\/span>\n        <span class=\"na\">body<\/span><span class=\"p\">:<\/span> <span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">stringify<\/span><span class=\"p\">({<\/span>\n          <span class=\"na\">model<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">gpt-4o-mini<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">messages<\/span><span class=\"p\">:<\/span> <span class=\"nx\">updatedMessages<\/span><span class=\"p\">,<\/span>\n          <span class=\"nx\">functions<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">userCache<\/span><span class=\"p\">:<\/span> <span class=\"nx\">cache<\/span> <span class=\"c1\">\/\/ Include userCache for function calls, but keep it minimal in messages<\/span>\n        <span class=\"p\">}),<\/span>\n      <span class=\"p\">});<\/span>\n\n      <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">response<\/span><span class=\"p\">.<\/span><span class=\"nx\">ok<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">throw<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Error<\/span><span class=\"p\">(<\/span><span class=\"s2\">`API request failed with status <\/span><span class=\"p\">${<\/span><span class=\"nx\">response<\/span><span class=\"p\">.<\/span><span class=\"nx\">status<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span><span class=\"p\">);<\/span>\n      <span class=\"p\">}<\/span>\n\n      <span class=\"kd\">const<\/span> <span class=\"nx\">data<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">response<\/span><span class=\"p\">.<\/span><span class=\"nf\">json<\/span><span class=\"p\">();<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">newMessage<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">data<\/span><span class=\"p\">.<\/span><span class=\"nx\">choices<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">].<\/span><span class=\"nx\">message<\/span><span class=\"p\">;<\/span>\n\n      <span class=\"c1\">\/\/ Create and add the Wei's response message<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"na\">weiResponseMessage<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Message<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">id<\/span><span class=\"p\">:<\/span> <span class=\"s2\">`msg_<\/span><span class=\"p\">${<\/span><span class=\"nb\">Date<\/span><span class=\"p\">.<\/span><span class=\"nf\">now<\/span><span class=\"p\">()}<\/span><span class=\"s2\">_<\/span><span class=\"p\">${<\/span><span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">random<\/span><span class=\"p\">().<\/span><span class=\"nf\">toString<\/span><span class=\"p\">(<\/span><span class=\"mi\">36<\/span><span class=\"p\">).<\/span><span class=\"nf\">substr<\/span><span class=\"p\">(<\/span><span class=\"mi\">2<\/span><span class=\"p\">,<\/span> <span class=\"mi\">9<\/span><span class=\"p\">)}<\/span><span class=\"s2\">`<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">sender<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">wei<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">content<\/span><span class=\"p\">:<\/span> <span class=\"nx\">newMessage<\/span><span class=\"p\">.<\/span><span class=\"nx\">content<\/span> <span class=\"o\">||<\/span> <span class=\"dl\">''<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">timestamp<\/span><span class=\"p\">:<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">()<\/span>\n      <span class=\"p\">};<\/span>\n\n      <span class=\"c1\">\/\/ Add Wei's response to messages<\/span>\n      <span class=\"nf\">setMessages<\/span><span class=\"p\">(<\/span><span class=\"nx\">prev<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">[...<\/span><span class=\"nx\">prev<\/span><span class=\"p\">,<\/span> <span class=\"nx\">weiResponseMessage<\/span><span class=\"p\">]);<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">err<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Error getting response:<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">err<\/span><span class=\"p\">);<\/span>\n      <span class=\"nf\">setError<\/span><span class=\"p\">(<\/span><span class=\"nx\">err<\/span> <span class=\"k\">instanceof<\/span> <span class=\"nb\">Error<\/span> <span class=\"p\">?<\/span> <span class=\"nx\">err<\/span><span class=\"p\">.<\/span><span class=\"nx\">message<\/span> <span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">Unknown error occurred<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">finally<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nf\">setIsTyping<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">},<\/span> <span class=\"p\">[<\/span><span class=\"nx\">messages<\/span><span class=\"p\">,<\/span> <span class=\"nx\">refreshCache<\/span><span class=\"p\">,<\/span> <span class=\"nx\">cache<\/span><span class=\"p\">]);<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">sendMessage<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async <\/span><span class=\"p\">(<\/span><span class=\"na\">content<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"c1\">\/\/ Create the user message<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"na\">userMessage<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Message<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">id<\/span><span class=\"p\">:<\/span> <span class=\"s2\">`msg_<\/span><span class=\"p\">${<\/span><span class=\"nb\">Date<\/span><span class=\"p\">.<\/span><span class=\"nf\">now<\/span><span class=\"p\">()}<\/span><span class=\"s2\">_<\/span><span class=\"p\">${<\/span><span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">random<\/span><span class=\"p\">().<\/span><span class=\"nf\">toString<\/span><span class=\"p\">(<\/span><span class=\"mi\">36<\/span><span class=\"p\">).<\/span><span class=\"nf\">substr<\/span><span class=\"p\">(<\/span><span class=\"mi\">2<\/span><span class=\"p\">,<\/span> <span class=\"mi\">9<\/span><span class=\"p\">)}<\/span><span class=\"s2\">`<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">sender<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">user<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n      <span class=\"nx\">content<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">timestamp<\/span><span class=\"p\">:<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">()<\/span>\n    <span class=\"p\">};<\/span>\n\n    <span class=\"c1\">\/\/ Add user message to messages state directly<\/span>\n    <span class=\"nf\">setMessages<\/span><span class=\"p\">(<\/span><span class=\"nx\">prev<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">[...<\/span><span class=\"nx\">prev<\/span><span class=\"p\">,<\/span> <span class=\"nx\">userMessage<\/span><span class=\"p\">]);<\/span>\n\n    <span class=\"c1\">\/\/ Wait for the state to update before getting Wei's response<\/span>\n    <span class=\"nf\">setTimeout<\/span><span class=\"p\">(<\/span><span class=\"k\">async <\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">await<\/span> <span class=\"nf\">getWeiResponse<\/span><span class=\"p\">(<\/span><span class=\"nx\">content<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">},<\/span> <span class=\"mi\">100<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">clearMessages<\/span> <span class=\"o\">=<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"c1\">\/\/ Keep only the welcome message<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">welcomeMessage<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">messages<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">];<\/span>\n    <span class=\"nf\">setMessages<\/span><span class=\"p\">([<\/span><span class=\"nx\">welcomeMessage<\/span><span class=\"p\">]);<\/span>\n    <span class=\"c1\">\/\/ Reset the current conversation ID to start a new conversation<\/span>\n    <span class=\"nf\">setCurrentConversationId<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n    <span class=\"c1\">\/\/ Clear any pending message<\/span>\n    <span class=\"nf\">setPendingUserMessage<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">loadConversation<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"na\">conversationMessages<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Message<\/span><span class=\"p\">[],<\/span> <span class=\"nx\">conversationId<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"c1\">\/\/ If there are messages in the conversation, replace current messages<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">conversationMessages<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">conversationMessages<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"c1\">\/\/ Get the first welcome message from current chat<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">welcomeMessage<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">messages<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">];<\/span>\n\n      <span class=\"c1\">\/\/ Set the welcome message followed by the conversation messages<\/span>\n      <span class=\"nf\">setMessages<\/span><span class=\"p\">([<\/span><span class=\"nx\">welcomeMessage<\/span><span class=\"p\">,<\/span> <span class=\"p\">...<\/span><span class=\"nx\">conversationMessages<\/span><span class=\"p\">]);<\/span>\n\n      <span class=\"c1\">\/\/ Set the conversation ID if provided<\/span>\n      <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">conversationId<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nf\">setCurrentConversationId<\/span><span class=\"p\">(<\/span><span class=\"nx\">conversationId<\/span><span class=\"p\">);<\/span>\n      <span class=\"p\">}<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"k\">return <\/span><span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nc\">ChatContext<\/span><span class=\"p\">.<\/span><span class=\"nc\">Provider<\/span> <span class=\"na\">value<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"p\">{<\/span> \n      <span class=\"nx\">messages<\/span><span class=\"p\">,<\/span> \n      <span class=\"nx\">isTyping<\/span><span class=\"p\">,<\/span> \n      <span class=\"nx\">error<\/span><span class=\"p\">,<\/span> \n      <span class=\"nx\">sendMessage<\/span><span class=\"p\">,<\/span> \n      <span class=\"nx\">clearMessages<\/span><span class=\"p\">,<\/span>\n      <span class=\"nx\">getWeiResponse<\/span><span class=\"p\">,<\/span>\n      <span class=\"nx\">loadConversation<\/span><span class=\"p\">,<\/span>\n      <span class=\"nx\">currentConversationId<\/span>\n    <span class=\"p\">}<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"si\">{<\/span><span class=\"nx\">children<\/span><span class=\"si\">}<\/span>\n    <span class=\"p\"\/><span class=\"nc\">ChatContext<\/span><span class=\"p\">.<\/span><span class=\"nc\">Provider<\/span><span class=\"p\">&gt;<\/span>\n  <span class=\"p\">);<\/span>\n<span class=\"p\">};<\/span> \n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"%D8%A7%D8%B1%D8%A7%D8%A6%D9%87_%D8%AF%D9%87%D9%86%D8%AF%DA%AF%D8%A7%D9%86_%D8%A7%D8%B1%D8%A7%D8%A6%D9%87_%D8%AF%D9%87%D9%86%D8%AF%D9%87_%DA%AF%D9%BE\"><\/span>\n<p>  \u0627\u0631\u0627\u0626\u0647 \u062f\u0647\u0646\u062f\u06af\u0627\u0646 (\u0627\u0631\u0627\u0626\u0647 \u062f\u0647\u0646\u062f\u0647 \u06af\u067e)<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0628\u0631\u0646\u0627\u0645\u0647 \u0631\u0627 \u0628\u0627 <code>ChatProvider<\/code> \u0645\u0624\u0644\u0641\u0647 <br \/>\u0628\u0639\u062f\u0627\u064b \u0627\u0631\u0627\u0626\u0647 \u062f\u0647\u0646\u062f\u06af\u0627\u0646 \u0628\u06cc\u0634\u062a\u0631\u06cc \u0631\u0627 \u0628\u0647 \u0628\u0631\u0646\u0627\u0645\u0647 \u0627\u0636\u0627\u0641\u0647 \u062e\u0648\u0627\u0647\u06cc\u0645 \u06a9\u0631\u062f.<\/p>\n<p>\u0628\u0631\u0627\u06cc \u0627\u06cc\u0646\u06a9\u0647 \u0628\u062a\u0648\u0627\u0646\u06cc\u0645 \u0627\u0632 \u0627\u0631\u0627\u0626\u0647 \u062f\u0647\u0646\u062f\u0647 \u0686\u062a \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u06a9\u0646\u06cc\u0645 \u060c \u0628\u0627\u06cc\u062f \u0628\u0631\u0646\u0627\u0645\u0647 \u062e\u0648\u062f \u0631\u0627 \u0628\u0627 <code>ChatProvider<\/code> \u0645\u0624\u0644\u0641\u0647<br \/>\u062f\u0631 \u0627\u0635\u0644 \u060c \u0632\u0645\u06cc\u0646\u0647 \u0686\u062a \u0631\u0627 \u0628\u0647 \u0628\u0631\u0646\u0627\u0645\u0647 \u0627\u0631\u0627\u0626\u0647 \u0645\u06cc \u062f\u0647\u062f.<\/p>\n<p>\u06cc\u06a9 \u0641\u0627\u06cc\u0644 \u062c\u062f\u06cc\u062f \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f <code>app\/providers.tsx<\/code>\u0628\u0634\u0631<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"dl\">\"<\/span><span class=\"s2\">use client<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">import<\/span> <span class=\"nx\">React<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">react<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">ThemeProvider<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">next-themes<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">ChatProvider<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/contexts\/ChatContext<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">RealTimeStreamingMode<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/RealTimeStreamingMode<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">usePathname<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">next\/navigation<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">Providers<\/span><span class=\"p\">({<\/span> <span class=\"nx\">children<\/span> <span class=\"p\">}:<\/span> <span class=\"p\">{<\/span> <span class=\"nl\">children<\/span><span class=\"p\">:<\/span> <span class=\"nx\">React<\/span><span class=\"p\">.<\/span><span class=\"nx\">ReactNode<\/span> <span class=\"p\">})<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">pathname<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">usePathname<\/span><span class=\"p\">();<\/span>\n  <span class=\"k\">return <\/span><span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nc\">ThemeProvider<\/span> <span class=\"na\">attribute<\/span><span class=\"p\">=<\/span><span class=\"s\">\"class\"<\/span> <span class=\"na\">defaultTheme<\/span><span class=\"p\">=<\/span><span class=\"s\">\"dark\"<\/span> <span class=\"na\">enableSystem<\/span> <span class=\"na\">forcedTheme<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">pathname<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">\/<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">?<\/span> <span class=\"kc\">undefined<\/span> <span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">dark<\/span><span class=\"dl\">\"<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nc\">ChatProvider<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"si\">{<\/span><span class=\"nx\">children<\/span><span class=\"si\">}<\/span>\n        <span class=\"si\">{<\/span><span class=\"nx\">pathname<\/span> <span class=\"o\">!==<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">\/<\/span><span class=\"dl\">\"<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"p\">&lt;<\/span><span class=\"nc\">RealTimeStreamingMode<\/span> <span class=\"p\">\/&gt;<\/span><span class=\"si\">}<\/span>\n      <span class=\"p\"\/><span class=\"nc\">ChatProvider<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\"\/><span class=\"nc\">ThemeProvider<\/span><span class=\"p\">&gt;<\/span>\n  <span class=\"p\">);<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"%D8%B7%D8%B1%D8%AD_%D9%BE%D8%A7%DB%8C%DA%AF%D8%A7%D9%87_%D8%AF%D8%A7%D8%AF%D9%87_%D8%B1%D8%A7_%D8%AA%D8%B9%D8%B1%DB%8C%D9%81_%DA%A9%D9%86%DB%8C%D8%AF\"><\/span>\n<p>  \u0637\u0631\u062d \u067e\u0627\u06cc\u06af\u0627\u0647 \u062f\u0627\u062f\u0647 \u0631\u0627 \u062a\u0639\u0631\u06cc\u0641 \u06a9\u0646\u06cc\u062f<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0627\u06cc\u0646 \u0637\u0631\u062d \u0628\u0631\u0627\u06cc \u067e\u0627\u06cc\u06af\u0627\u0647 \u062f\u0627\u062f\u0647 \u0627\u0633\u062a.<br \/>\u0627\u0632 \u0622\u0646 \u0628\u0631\u0627\u06cc \u062a\u0639\u0631\u06cc\u0641 \u0633\u0627\u062e\u062a\u0627\u0631 \u067e\u0627\u06cc\u06af\u0627\u0647 \u062f\u0627\u062f\u0647 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u0634\u0648\u062f.<\/p>\n<p>\u06cc\u06a9 \u0641\u0627\u06cc\u0644 \u062c\u062f\u06cc\u062f \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f <code>app\/types\/database.ts<\/code>\u0628\u0634\u0631<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">DBSchema<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">idb<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n\n<span class=\"c1\">\/\/ Define our database schema<\/span>\n<span class=\"k\">export<\/span> <span class=\"kr\">interface<\/span> <span class=\"nx\">WeiDB<\/span> <span class=\"kd\">extends<\/span> <span class=\"nx\">DBSchema<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">habits<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">key<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">value<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">id<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">name<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">category<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">points<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">frequency<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">daily<\/span><span class=\"dl\">'<\/span> <span class=\"o\">|<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">weekly<\/span><span class=\"dl\">'<\/span> <span class=\"o\">|<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">monthly<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">createdAt<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Date<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">};<\/span>\n    <span class=\"nl\">indexes<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">by-category<\/span><span class=\"dl\">'<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span> <span class=\"p\">};<\/span>\n  <span class=\"p\">};<\/span>\n  <span class=\"nl\">completions<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">key<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">value<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">id<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">habitId<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">completedAt<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Date<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">points<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">};<\/span>\n    <span class=\"nl\">indexes<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">by-habit<\/span><span class=\"dl\">'<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">by-date<\/span><span class=\"dl\">'<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Date<\/span> <span class=\"p\">};<\/span>\n  <span class=\"p\">};<\/span>\n  <span class=\"nl\">rewards<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">key<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">value<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">id<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">name<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">description<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">cost<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">createdAt<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Date<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">};<\/span>\n  <span class=\"p\">};<\/span>\n  <span class=\"nl\">rewardRedemptions<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">key<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">value<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">id<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">rewardId<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">redeemedAt<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Date<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">cost<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">};<\/span>\n  <span class=\"p\">};<\/span>\n  <span class=\"nl\">user<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">key<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">value<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">id<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">name<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">points<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">streakDays<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">lastActive<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Date<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">};<\/span>\n  <span class=\"p\">};<\/span>\n  <span class=\"nl\">conversations<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">key<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">value<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">id<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">messages<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">id<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n        <span class=\"nl\">sender<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">user<\/span><span class=\"dl\">'<\/span> <span class=\"o\">|<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">wei<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n        <span class=\"nl\">content<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n        <span class=\"nl\">timestamp<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Date<\/span><span class=\"p\">;<\/span>\n      <span class=\"p\">}[];<\/span>\n      <span class=\"nl\">createdAt<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Date<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">updatedAt<\/span><span class=\"p\">?:<\/span> <span class=\"nb\">Date<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">};<\/span>\n  <span class=\"p\">};<\/span>\n  <span class=\"nl\">userProfile<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">key<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">value<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">id<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">name<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">email<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">bio<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">avatarUrl<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">joinDate<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">};<\/span>\n  <span class=\"p\">};<\/span>\n<span class=\"p\">}<\/span> \n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"%D8%B2%D9%85%DB%8C%D9%86%D9%87_%D9%BE%D8%A7%DB%8C%DA%AF%D8%A7%D9%87_%D8%AF%D8%A7%D8%AF%D9%87\"><\/span>\n<p>  \u0632\u0645\u06cc\u0646\u0647 \u067e\u0627\u06cc\u06af\u0627\u0647 \u062f\u0627\u062f\u0647<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0627\u06cc\u0646 \u0632\u0645\u06cc\u0646\u0647 \u0628\u0631\u0627\u06cc \u062a\u0639\u0627\u0645\u0644 \u0628\u0627 \u067e\u0627\u06cc\u06af\u0627\u0647 \u062f\u0627\u062f\u0647 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u0634\u0648\u062f.<br \/>\u0627\u0632 \u0622\u0646 \u0628\u0631\u0627\u06cc \u0628\u0647 \u062f\u0633\u062a \u0622\u0648\u0631\u062f\u0646 \u062f\u0627\u062f\u0647 \u0647\u0627\u06cc \u06a9\u0627\u0631\u0628\u0631 \u060c \u0639\u0627\u062f\u0627\u062a \u060c \u062a\u06a9\u0645\u06cc\u0644 \u060c \u067e\u0627\u062f\u0627\u0634 \u0648 \u063a\u06cc\u0631\u0647 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u0634\u0648\u062f.<\/p>\n<p>\u06cc\u06a9 \u0641\u0627\u06cc\u0644 \u062c\u062f\u06cc\u062f \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f <code>app\/contexts\/DatabaseContext.tsx<\/code>\u0628\u0634\u0631<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code>\n<span class=\"dl\">\"<\/span><span class=\"s2\">use client<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">import<\/span> <span class=\"nx\">React<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">createContext<\/span><span class=\"p\">,<\/span> <span class=\"nx\">useContext<\/span><span class=\"p\">,<\/span> <span class=\"nx\">useEffect<\/span><span class=\"p\">,<\/span> <span class=\"nx\">useState<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">react<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">IDBPDatabase<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">idb<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">WeiDB<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/types\/database<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">seedDatabase<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/utils\/seedData<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">initDB<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">@\/lib\/db<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n\n<span class=\"kr\">interface<\/span> <span class=\"nx\">DatabaseContextType<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">db<\/span><span class=\"p\">:<\/span> <span class=\"nx\">IDBPDatabase<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">WeiDB<\/span><span class=\"o\">&gt;<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">isLoading<\/span><span class=\"p\">:<\/span> <span class=\"nx\">boolean<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">error<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Error<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">userPoints<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">setUserPoints<\/span><span class=\"p\">:<\/span> <span class=\"p\">(<\/span><span class=\"nx\">points<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nb\">Promise<\/span><span class=\"o\">&lt;<\/span><span class=\"k\">void<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">addHabit<\/span><span class=\"p\">:<\/span> <span class=\"p\">(<\/span><span class=\"nx\">habit<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Omit<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">habits<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">],<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">id<\/span><span class=\"dl\">'<\/span> <span class=\"o\">|<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">createdAt<\/span><span class=\"dl\">'<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nb\">Promise<\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">string<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">getHabits<\/span><span class=\"p\">:<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nb\">Promise<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">habits<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">][]<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">completeHabit<\/span><span class=\"p\">:<\/span> <span class=\"p\">(<\/span><span class=\"nx\">habitId<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nb\">Promise<\/span><span class=\"o\">&lt;<\/span><span class=\"k\">void<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">getCompletions<\/span><span class=\"p\">:<\/span> <span class=\"p\">(<\/span><span class=\"nx\">habitId<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">,<\/span> <span class=\"nx\">date<\/span><span class=\"p\">?:<\/span> <span class=\"nb\">Date<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nb\">Promise<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">completions<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">][]<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">addReward<\/span><span class=\"p\">:<\/span> <span class=\"p\">(<\/span><span class=\"nx\">reward<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Omit<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">rewards<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">],<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">id<\/span><span class=\"dl\">'<\/span> <span class=\"o\">|<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">createdAt<\/span><span class=\"dl\">'<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nb\">Promise<\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">string<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">getRewards<\/span><span class=\"p\">:<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nb\">Promise<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">rewards<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">][]<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">redeemReward<\/span><span class=\"p\">:<\/span> <span class=\"p\">(<\/span><span class=\"nx\">rewardId<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nb\">Promise<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">boolean<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">getRewardRedemptions<\/span><span class=\"p\">:<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nb\">Promise<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">rewardRedemptions<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">][]<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">getUserData<\/span><span class=\"p\">:<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nb\">Promise<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">user<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">]<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">saveConversation<\/span><span class=\"p\">:<\/span> <span class=\"p\">(<\/span><span class=\"nx\">messages<\/span><span class=\"p\">:<\/span> <span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">conversations<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">messages<\/span><span class=\"dl\">'<\/span><span class=\"p\">],<\/span> <span class=\"nx\">conversationId<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nb\">Promise<\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">string<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">getConversations<\/span><span class=\"p\">:<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nb\">Promise<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">conversations<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">][]<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">saveUserProfile<\/span><span class=\"p\">:<\/span> <span class=\"p\">(<\/span><span class=\"nx\">profile<\/span><span class=\"p\">:<\/span> <span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">userProfile<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">])<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nb\">Promise<\/span><span class=\"o\">&lt;<\/span><span class=\"k\">void<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">getUserProfile<\/span><span class=\"p\">:<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nb\">Promise<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">userProfile<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">]<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"kd\">const<\/span> <span class=\"nx\">DatabaseContext<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">createContext<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">DatabaseContextType<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kd\">const<\/span> <span class=\"nx\">useDatabase<\/span> <span class=\"o\">=<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">context<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useContext<\/span><span class=\"p\">(<\/span><span class=\"nx\">DatabaseContext<\/span><span class=\"p\">);<\/span>\n  <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">context<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">throw<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">useDatabase must be used within a DatabaseProvider<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">}<\/span>\n  <span class=\"k\">return<\/span> <span class=\"nx\">context<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">};<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kd\">const<\/span> <span class=\"nx\">DatabaseProvider<\/span><span class=\"p\">:<\/span> <span class=\"nx\">React<\/span><span class=\"p\">.<\/span><span class=\"nx\">FC<\/span><span class=\"o\">&lt;<\/span><span class=\"p\">{<\/span> <span class=\"na\">children<\/span><span class=\"p\">:<\/span> <span class=\"nx\">React<\/span><span class=\"p\">.<\/span><span class=\"nx\">ReactNode<\/span> <span class=\"p\">}<\/span><span class=\"o\">&gt;<\/span> <span class=\"o\">=<\/span> <span class=\"p\">({<\/span> <span class=\"nx\">children<\/span> <span class=\"p\">})<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">db<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setDB<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">IDBPDatabase<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">WeiDB<\/span><span class=\"o\">&gt;<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">isLoading<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setIsLoading<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">boolean<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">true<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">error<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setError<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"nb\">Error<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">userPoints<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setUserPointsState<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">number<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">);<\/span>\n\n  <span class=\"nf\">useEffect<\/span><span class=\"p\">(()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">setupDB<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async <\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">database<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">initDB<\/span><span class=\"p\">();<\/span>\n        <span class=\"nf\">setDB<\/span><span class=\"p\">(<\/span><span class=\"nx\">database<\/span><span class=\"p\">);<\/span>\n\n        <span class=\"c1\">\/\/ Load initial user points<\/span>\n        <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n          <span class=\"kd\">const<\/span> <span class=\"nx\">userData<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">database<\/span><span class=\"p\">.<\/span><span class=\"nf\">get<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">user<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">default<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n          <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">userData<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n            <span class=\"nf\">setUserPointsState<\/span><span class=\"p\">(<\/span><span class=\"nx\">userData<\/span><span class=\"p\">.<\/span><span class=\"nx\">points<\/span><span class=\"p\">);<\/span>\n          <span class=\"p\">}<\/span>\n\n          <span class=\"c1\">\/\/ Seed database with sample data<\/span>\n          <span class=\"k\">await<\/span> <span class=\"nf\">seedDatabase<\/span><span class=\"p\">(<\/span><span class=\"nx\">database<\/span><span class=\"p\">);<\/span>\n        <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">dataError<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n          <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Error getting initial data from database:<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">dataError<\/span><span class=\"p\">);<\/span>\n          <span class=\"c1\">\/\/ Continue even with this error - we just might not have initial data<\/span>\n        <span class=\"p\">}<\/span>\n\n        <span class=\"nf\">setIsLoading<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">);<\/span>\n      <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">err<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Failed to init database:<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">err<\/span><span class=\"p\">);<\/span>\n        <span class=\"nf\">setError<\/span><span class=\"p\">(<\/span><span class=\"nx\">err<\/span> <span class=\"k\">instanceof<\/span> <span class=\"nb\">Error<\/span> <span class=\"p\">?<\/span> <span class=\"nx\">err<\/span> <span class=\"p\">:<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Unknown database error<\/span><span class=\"dl\">'<\/span><span class=\"p\">));<\/span>\n        <span class=\"nf\">setIsLoading<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">);<\/span>\n      <span class=\"p\">}<\/span>\n    <span class=\"p\">};<\/span>\n\n    <span class=\"nf\">setupDB<\/span><span class=\"p\">();<\/span>\n\n    <span class=\"c1\">\/\/ Do NOT close the connection when unmounting<\/span>\n    <span class=\"c1\">\/\/ The connection will be shared across providers<\/span>\n  <span class=\"p\">},<\/span> <span class=\"p\">[]);<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">setUserPoints<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async <\/span><span class=\"p\">(<\/span><span class=\"na\">points<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">db<\/span><span class=\"p\">)<\/span> <span class=\"k\">return<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">put<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">user<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">id<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">default<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">User<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n      <span class=\"nx\">points<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">streakDays<\/span><span class=\"p\">:<\/span> <span class=\"p\">(<\/span><span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">get<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">user<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">default<\/span><span class=\"dl\">'<\/span><span class=\"p\">))?.<\/span><span class=\"nx\">streakDays<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">0<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">lastActive<\/span><span class=\"p\">:<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">()<\/span>\n    <span class=\"p\">});<\/span>\n\n    <span class=\"nf\">setUserPointsState<\/span><span class=\"p\">(<\/span><span class=\"nx\">points<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">addHabit<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async <\/span><span class=\"p\">(<\/span><span class=\"na\">habit<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Omit<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">habits<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">],<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">id<\/span><span class=\"dl\">'<\/span> <span class=\"o\">|<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">createdAt<\/span><span class=\"dl\">'<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">db<\/span><span class=\"p\">)<\/span> <span class=\"k\">throw<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Database not initialized<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"kd\">const<\/span> <span class=\"nx\">id<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">`habit_<\/span><span class=\"p\">${<\/span><span class=\"nb\">Date<\/span><span class=\"p\">.<\/span><span class=\"nf\">now<\/span><span class=\"p\">()}<\/span><span class=\"s2\">_<\/span><span class=\"p\">${<\/span><span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">random<\/span><span class=\"p\">().<\/span><span class=\"nf\">toString<\/span><span class=\"p\">(<\/span><span class=\"mi\">36<\/span><span class=\"p\">).<\/span><span class=\"nf\">substr<\/span><span class=\"p\">(<\/span><span class=\"mi\">2<\/span><span class=\"p\">,<\/span> <span class=\"mi\">9<\/span><span class=\"p\">)}<\/span><span class=\"s2\">`<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">add<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">habits<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span>\n      <span class=\"p\">...<\/span><span class=\"nx\">habit<\/span><span class=\"p\">,<\/span>\n      <span class=\"nx\">id<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">createdAt<\/span><span class=\"p\">:<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">()<\/span>\n    <span class=\"p\">});<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"nx\">id<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">getHabits<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async <\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">db<\/span><span class=\"p\">)<\/span> <span class=\"k\">return<\/span> <span class=\"p\">[];<\/span>\n    <span class=\"k\">return<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">getAll<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">habits<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">completeHabit<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async <\/span><span class=\"p\">(<\/span><span class=\"na\">habitId<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">db<\/span><span class=\"p\">)<\/span> <span class=\"k\">return<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"kd\">const<\/span> <span class=\"nx\">habit<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">get<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">habits<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">habitId<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">habit<\/span><span class=\"p\">)<\/span> <span class=\"k\">return<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"kd\">const<\/span> <span class=\"nx\">completionId<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">`completion_<\/span><span class=\"p\">${<\/span><span class=\"nb\">Date<\/span><span class=\"p\">.<\/span><span class=\"nf\">now<\/span><span class=\"p\">()}<\/span><span class=\"s2\">_<\/span><span class=\"p\">${<\/span><span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">random<\/span><span class=\"p\">().<\/span><span class=\"nf\">toString<\/span><span class=\"p\">(<\/span><span class=\"mi\">36<\/span><span class=\"p\">).<\/span><span class=\"nf\">substr<\/span><span class=\"p\">(<\/span><span class=\"mi\">2<\/span><span class=\"p\">,<\/span> <span class=\"mi\">9<\/span><span class=\"p\">)}<\/span><span class=\"s2\">`<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">add<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">completions<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">id<\/span><span class=\"p\">:<\/span> <span class=\"nx\">completionId<\/span><span class=\"p\">,<\/span>\n      <span class=\"nx\">habitId<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">completedAt<\/span><span class=\"p\">:<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(),<\/span>\n      <span class=\"na\">points<\/span><span class=\"p\">:<\/span> <span class=\"nx\">habit<\/span><span class=\"p\">.<\/span><span class=\"nx\">points<\/span>\n    <span class=\"p\">});<\/span>\n\n    <span class=\"c1\">\/\/ Update user points<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">userData<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">get<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">user<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">default<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">userData<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">await<\/span> <span class=\"nf\">setUserPoints<\/span><span class=\"p\">(<\/span><span class=\"nx\">userData<\/span><span class=\"p\">.<\/span><span class=\"nx\">points<\/span> <span class=\"o\">+<\/span> <span class=\"nx\">habit<\/span><span class=\"p\">.<\/span><span class=\"nx\">points<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">getCompletions<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async <\/span><span class=\"p\">(<\/span><span class=\"nx\">habitId<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">,<\/span> <span class=\"nx\">date<\/span><span class=\"p\">?:<\/span> <span class=\"nb\">Date<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">db<\/span><span class=\"p\">)<\/span> <span class=\"k\">return<\/span> <span class=\"p\">[];<\/span>\n\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">habitId<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">return<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">getAllFromIndex<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">completions<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">by-habit<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">habitId<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">date<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">allCompletions<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">getAll<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">completions<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">startOfDay<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(<\/span><span class=\"nx\">date<\/span><span class=\"p\">);<\/span>\n      <span class=\"nx\">startOfDay<\/span><span class=\"p\">.<\/span><span class=\"nf\">setHours<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"mi\">0<\/span><span class=\"p\">);<\/span>\n\n      <span class=\"kd\">const<\/span> <span class=\"nx\">endOfDay<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(<\/span><span class=\"nx\">date<\/span><span class=\"p\">);<\/span>\n      <span class=\"nx\">endOfDay<\/span><span class=\"p\">.<\/span><span class=\"nf\">setHours<\/span><span class=\"p\">(<\/span><span class=\"mi\">23<\/span><span class=\"p\">,<\/span> <span class=\"mi\">59<\/span><span class=\"p\">,<\/span> <span class=\"mi\">59<\/span><span class=\"p\">,<\/span> <span class=\"mi\">999<\/span><span class=\"p\">);<\/span>\n\n      <span class=\"k\">return<\/span> <span class=\"nx\">allCompletions<\/span><span class=\"p\">.<\/span><span class=\"nf\">filter<\/span><span class=\"p\">(<\/span>\n        <span class=\"p\">(<\/span><span class=\"na\">completion<\/span><span class=\"p\">:<\/span> <span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">completions<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">])<\/span> <span class=\"o\">=&gt;<\/span> \n          <span class=\"nx\">completion<\/span><span class=\"p\">.<\/span><span class=\"nx\">completedAt<\/span> <span class=\"o\">&gt;=<\/span> <span class=\"nx\">startOfDay<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">completion<\/span><span class=\"p\">.<\/span><span class=\"nx\">completedAt<\/span> <span class=\"o\">&lt;=<\/span> <span class=\"nx\">endOfDay<\/span>\n      <span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">getAll<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">completions<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">addReward<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async <\/span><span class=\"p\">(<\/span><span class=\"na\">reward<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Omit<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">rewards<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">],<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">id<\/span><span class=\"dl\">'<\/span> <span class=\"o\">|<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">createdAt<\/span><span class=\"dl\">'<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">db<\/span><span class=\"p\">)<\/span> <span class=\"k\">throw<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Database not initialized<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"kd\">const<\/span> <span class=\"nx\">id<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">`reward_<\/span><span class=\"p\">${<\/span><span class=\"nb\">Date<\/span><span class=\"p\">.<\/span><span class=\"nf\">now<\/span><span class=\"p\">()}<\/span><span class=\"s2\">_<\/span><span class=\"p\">${<\/span><span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">random<\/span><span class=\"p\">().<\/span><span class=\"nf\">toString<\/span><span class=\"p\">(<\/span><span class=\"mi\">36<\/span><span class=\"p\">).<\/span><span class=\"nf\">substr<\/span><span class=\"p\">(<\/span><span class=\"mi\">2<\/span><span class=\"p\">,<\/span> <span class=\"mi\">9<\/span><span class=\"p\">)}<\/span><span class=\"s2\">`<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">add<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">rewards<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span>\n      <span class=\"p\">...<\/span><span class=\"nx\">reward<\/span><span class=\"p\">,<\/span>\n      <span class=\"nx\">id<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">createdAt<\/span><span class=\"p\">:<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">()<\/span>\n    <span class=\"p\">});<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"nx\">id<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">getRewards<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async <\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">db<\/span><span class=\"p\">)<\/span> <span class=\"k\">return<\/span> <span class=\"p\">[];<\/span>\n    <span class=\"k\">return<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">getAll<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">rewards<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">redeemReward<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async <\/span><span class=\"p\">(<\/span><span class=\"na\">rewardId<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">db<\/span><span class=\"p\">)<\/span> <span class=\"k\">return<\/span> <span class=\"kc\">false<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"kd\">const<\/span> <span class=\"nx\">reward<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">get<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">rewards<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">rewardId<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">reward<\/span><span class=\"p\">)<\/span> <span class=\"k\">return<\/span> <span class=\"kc\">false<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"kd\">const<\/span> <span class=\"nx\">userData<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">get<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">user<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">default<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">userData<\/span> <span class=\"o\">||<\/span> <span class=\"nx\">userData<\/span><span class=\"p\">.<\/span><span class=\"nx\">points<\/span> <span class=\"o\">&lt;<\/span> <span class=\"nx\">reward<\/span><span class=\"p\">.<\/span><span class=\"nx\">cost<\/span><span class=\"p\">)<\/span> <span class=\"k\">return<\/span> <span class=\"kc\">false<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"kd\">const<\/span> <span class=\"nx\">redemptionId<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">`redemption_<\/span><span class=\"p\">${<\/span><span class=\"nb\">Date<\/span><span class=\"p\">.<\/span><span class=\"nf\">now<\/span><span class=\"p\">()}<\/span><span class=\"s2\">_<\/span><span class=\"p\">${<\/span><span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">random<\/span><span class=\"p\">().<\/span><span class=\"nf\">toString<\/span><span class=\"p\">(<\/span><span class=\"mi\">36<\/span><span class=\"p\">).<\/span><span class=\"nf\">substr<\/span><span class=\"p\">(<\/span><span class=\"mi\">2<\/span><span class=\"p\">,<\/span> <span class=\"mi\">9<\/span><span class=\"p\">)}<\/span><span class=\"s2\">`<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">add<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">rewardRedemptions<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">id<\/span><span class=\"p\">:<\/span> <span class=\"nx\">redemptionId<\/span><span class=\"p\">,<\/span>\n      <span class=\"nx\">rewardId<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">redeemedAt<\/span><span class=\"p\">:<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(),<\/span>\n      <span class=\"na\">cost<\/span><span class=\"p\">:<\/span> <span class=\"nx\">reward<\/span><span class=\"p\">.<\/span><span class=\"nx\">cost<\/span>\n    <span class=\"p\">});<\/span>\n\n    <span class=\"c1\">\/\/ Update user points<\/span>\n    <span class=\"k\">await<\/span> <span class=\"nf\">setUserPoints<\/span><span class=\"p\">(<\/span><span class=\"nx\">userData<\/span><span class=\"p\">.<\/span><span class=\"nx\">points<\/span> <span class=\"o\">-<\/span> <span class=\"nx\">reward<\/span><span class=\"p\">.<\/span><span class=\"nx\">cost<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"kc\">true<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">getRewardRedemptions<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async <\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">db<\/span><span class=\"p\">)<\/span> <span class=\"k\">return<\/span> <span class=\"p\">[];<\/span>\n    <span class=\"k\">return<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">getAll<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">rewardRedemptions<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">getUserData<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async <\/span><span class=\"p\">():<\/span> <span class=\"nb\">Promise<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">user<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">]<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">db<\/span><span class=\"p\">)<\/span> <span class=\"k\">return<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">userData<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">get<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">user<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">default<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">return<\/span> <span class=\"nx\">userData<\/span> <span class=\"o\">||<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">saveConversation<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async <\/span><span class=\"p\">(<\/span><span class=\"na\">messages<\/span><span class=\"p\">:<\/span> <span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">conversations<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">messages<\/span><span class=\"dl\">'<\/span><span class=\"p\">],<\/span> <span class=\"nx\">conversationId<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">db<\/span><span class=\"p\">)<\/span> <span class=\"k\">throw<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Database not initialized<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">conversationId<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"c1\">\/\/ Update existing conversation<\/span>\n      <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">existingConversation<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">get<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">conversations<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">conversationId<\/span><span class=\"p\">);<\/span>\n        <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">existingConversation<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n          <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">put<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">conversations<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span>\n            <span class=\"p\">...<\/span><span class=\"nx\">existingConversation<\/span><span class=\"p\">,<\/span>\n            <span class=\"nx\">messages<\/span><span class=\"p\">,<\/span>\n            <span class=\"na\">updatedAt<\/span><span class=\"p\">:<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">()<\/span>\n          <span class=\"p\">});<\/span>\n          <span class=\"k\">return<\/span> <span class=\"nx\">conversationId<\/span><span class=\"p\">;<\/span>\n        <span class=\"p\">}<\/span>\n      <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Failed to update conversation:<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n        <span class=\"c1\">\/\/ If update fails, fall back to creating a new conversation<\/span>\n      <span class=\"p\">}<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c1\">\/\/ Create new conversation<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">id<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">conversationId<\/span> <span class=\"o\">||<\/span> <span class=\"s2\">`conversation_<\/span><span class=\"p\">${<\/span><span class=\"nb\">Date<\/span><span class=\"p\">.<\/span><span class=\"nf\">now<\/span><span class=\"p\">()}<\/span><span class=\"s2\">_<\/span><span class=\"p\">${<\/span><span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">random<\/span><span class=\"p\">().<\/span><span class=\"nf\">toString<\/span><span class=\"p\">(<\/span><span class=\"mi\">36<\/span><span class=\"p\">).<\/span><span class=\"nf\">substr<\/span><span class=\"p\">(<\/span><span class=\"mi\">2<\/span><span class=\"p\">,<\/span> <span class=\"mi\">9<\/span><span class=\"p\">)}<\/span><span class=\"s2\">`<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">add<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">conversations<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">id<\/span><span class=\"p\">,<\/span>\n        <span class=\"nx\">messages<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">createdAt<\/span><span class=\"p\">:<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">()<\/span>\n      <span class=\"p\">});<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"c1\">\/\/ Handle the case where the conversation already exists but we couldn't update it<\/span>\n      <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Failed to create conversation:<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n      <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">conversationId<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n          <span class=\"c1\">\/\/ Try to overwrite the existing conversation as a last resort<\/span>\n          <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">put<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">conversations<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span>\n            <span class=\"nx\">id<\/span><span class=\"p\">,<\/span>\n            <span class=\"nx\">messages<\/span><span class=\"p\">,<\/span>\n            <span class=\"na\">createdAt<\/span><span class=\"p\">:<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(),<\/span>\n            <span class=\"na\">updatedAt<\/span><span class=\"p\">:<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">()<\/span>\n          <span class=\"p\">});<\/span>\n        <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">putError<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n          <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Failed to overwrite conversation:<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">putError<\/span><span class=\"p\">);<\/span>\n        <span class=\"p\">}<\/span>\n      <span class=\"p\">}<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"nx\">id<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">getConversations<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async <\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">db<\/span><span class=\"p\">)<\/span> <span class=\"k\">return<\/span> <span class=\"p\">[];<\/span>\n    <span class=\"k\">return<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">getAll<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">conversations<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">saveUserProfile<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async <\/span><span class=\"p\">(<\/span><span class=\"na\">profile<\/span><span class=\"p\">:<\/span> <span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">userProfile<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">])<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">db<\/span><span class=\"p\">)<\/span> <span class=\"k\">throw<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Database not initialized<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">put<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">userProfile<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">profile<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">getUserProfile<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async <\/span><span class=\"p\">():<\/span> <span class=\"nb\">Promise<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">userProfile<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">]<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">db<\/span><span class=\"p\">)<\/span> <span class=\"k\">return<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">profile<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">get<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">userProfile<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">default<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n      <span class=\"k\">return<\/span> <span class=\"nx\">profile<\/span> <span class=\"o\">||<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Failed to get user profile:<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n      <span class=\"k\">return<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"na\">value<\/span><span class=\"p\">:<\/span> <span class=\"nx\">DatabaseContextType<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">db<\/span><span class=\"p\">,<\/span>\n    <span class=\"nx\">isLoading<\/span><span class=\"p\">,<\/span>\n    <span class=\"nx\">error<\/span><span class=\"p\">,<\/span>\n    <span class=\"nx\">userPoints<\/span><span class=\"p\">,<\/span>\n    <span class=\"nx\">setUserPoints<\/span><span class=\"p\">,<\/span>\n    <span class=\"nx\">addHabit<\/span><span class=\"p\">,<\/span>\n    <span class=\"nx\">getHabits<\/span><span class=\"p\">,<\/span>\n    <span class=\"nx\">completeHabit<\/span><span class=\"p\">,<\/span>\n    <span class=\"nx\">getCompletions<\/span><span class=\"p\">,<\/span>\n    <span class=\"nx\">addReward<\/span><span class=\"p\">,<\/span>\n    <span class=\"nx\">getRewards<\/span><span class=\"p\">,<\/span>\n    <span class=\"nx\">redeemReward<\/span><span class=\"p\">,<\/span>\n    <span class=\"nx\">getRewardRedemptions<\/span><span class=\"p\">,<\/span>\n    <span class=\"nx\">getUserData<\/span><span class=\"p\">,<\/span>\n    <span class=\"nx\">saveConversation<\/span><span class=\"p\">,<\/span>\n    <span class=\"nx\">getConversations<\/span><span class=\"p\">,<\/span>\n    <span class=\"nx\">saveUserProfile<\/span><span class=\"p\">,<\/span>\n    <span class=\"nx\">getUserProfile<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"k\">return <\/span><span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nc\">DatabaseContext<\/span><span class=\"p\">.<\/span><span class=\"nc\">Provider<\/span> <span class=\"na\">value<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">value<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"si\">{<\/span><span class=\"nx\">children<\/span><span class=\"si\">}<\/span>\n    <span class=\"p\"\/><span class=\"nc\">DatabaseContext<\/span><span class=\"p\">.<\/span><span class=\"nc\">Provider<\/span><span class=\"p\">&gt;<\/span>\n  <span class=\"p\">);<\/span>\n<span class=\"p\">};<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"%D8%A7%D8%B1%D8%A7%D8%A6%D9%87_%D8%AF%D9%87%D9%86%D8%AF%DA%AF%D8%A7%D9%86_%D8%B2%D9%85%DB%8C%D9%86%D9%87_%D8%A8%D8%A7%D9%86%DA%A9_%D8%A7%D8%B7%D9%84%D8%A7%D8%B9%D8%A7%D8%AA%DB%8C\"><\/span>\n<p>  \u0627\u0631\u0627\u0626\u0647 \u062f\u0647\u0646\u062f\u06af\u0627\u0646 (\u0632\u0645\u06cc\u0646\u0647 \u0628\u0627\u0646\u06a9 \u0627\u0637\u0644\u0627\u0639\u0627\u062a\u06cc)<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0628\u0631\u0646\u0627\u0645\u0647 \u0631\u0627 \u0628\u0627 <code>DatabaseProvider<\/code> \u0645\u0624\u0644\u0641\u0647<\/p>\n<p>\u067e\u0631\u0648\u0646\u062f\u0647 \u0628\u0627\u0632 <code>app\/providers.tsx<\/code>\u0628\u0634\u0631<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"dl\">\"<\/span><span class=\"s2\">use client<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">import<\/span> <span class=\"nx\">React<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">react<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">ThemeProvider<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">next-themes<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">DatabaseProvider<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/contexts\/DatabaseContext<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">UserCacheProvider<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/contexts\/UserCacheContext<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">ChatProvider<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/contexts\/ChatContext<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">RealTimeStreamingMode<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/RealTimeStreamingMode<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">usePathname<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">next\/navigation<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">Providers<\/span><span class=\"p\">({<\/span> <span class=\"nx\">children<\/span> <span class=\"p\">}:<\/span> <span class=\"p\">{<\/span> <span class=\"nl\">children<\/span><span class=\"p\">:<\/span> <span class=\"nx\">React<\/span><span class=\"p\">.<\/span><span class=\"nx\">ReactNode<\/span> <span class=\"p\">})<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">pathname<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">usePathname<\/span><span class=\"p\">();<\/span>\n  <span class=\"k\">return <\/span><span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nc\">ThemeProvider<\/span> <span class=\"na\">attribute<\/span><span class=\"p\">=<\/span><span class=\"s\">\"class\"<\/span> <span class=\"na\">defaultTheme<\/span><span class=\"p\">=<\/span><span class=\"s\">\"dark\"<\/span> <span class=\"na\">enableSystem<\/span> <span class=\"na\">forcedTheme<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">pathname<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">\/<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">?<\/span> <span class=\"kc\">undefined<\/span> <span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">dark<\/span><span class=\"dl\">\"<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nc\">DatabaseProvider<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nc\">UserCacheProvider<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nc\">ChatProvider<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"si\">{<\/span><span class=\"nx\">children<\/span><span class=\"si\">}<\/span>\n            <span class=\"si\">{<\/span><span class=\"nx\">pathname<\/span> <span class=\"o\">!==<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">\/<\/span><span class=\"dl\">\"<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"p\">&lt;<\/span><span class=\"nc\">RealTimeStreamingMode<\/span> <span class=\"p\">\/&gt;<\/span><span class=\"si\">}<\/span>\n          <span class=\"p\"\/><span class=\"nc\">ChatProvider<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\"\/><span class=\"nc\">UserCacheProvider<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\"\/><span class=\"nc\">DatabaseProvider<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\"\/><span class=\"nc\">ThemeProvider<\/span><span class=\"p\">&gt;<\/span>\n  <span class=\"p\">);<\/span>\n<span class=\"p\">}<\/span> \n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"%D8%B2%D9%85%DB%8C%D9%86%D9%87_%D8%AD%D8%A7%D9%81%D8%B8%D9%87_%D9%BE%D9%86%D9%87%D8%A7%D9%86_%DA%A9%D8%A7%D8%B1%D8%A8%D8%B1\"><\/span>\n<p>  \u0632\u0645\u06cc\u0646\u0647 \u062d\u0627\u0641\u0638\u0647 \u067e\u0646\u0647\u0627\u0646 \u06a9\u0627\u0631\u0628\u0631<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0627\u06cc\u0646 \u0632\u0645\u06cc\u0646\u0647 \u0628\u0631\u0627\u06cc \u0630\u062e\u06cc\u0631\u0647 \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u06a9\u0627\u0631\u0628\u0631 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u0634\u0648\u062f.<br \/>\u0627\u0632 \u0622\u0646 \u0628\u0631\u0627\u06cc \u062c\u0644\u0648\u06af\u06cc\u0631\u06cc \u0627\u0632 \u0648\u0627\u06a9\u0634\u06cc \u062f\u0627\u062f\u0647 \u0647\u0627\u06cc \u06a9\u0627\u0631\u0628\u0631 \u0627\u0632 \u067e\u0627\u06cc\u06af\u0627\u0647 \u062f\u0627\u062f\u0647 \u062f\u0631 \u0647\u0631 \u0635\u0641\u062d\u0647 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u0634\u0648\u062f.<\/p>\n<p>\u06cc\u06a9 \u0641\u0627\u06cc\u0644 \u062c\u062f\u06cc\u062f \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f <code>app\/contexts\/UserCacheContext.tsx<\/code>\u0628\u0634\u0631<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"dl\">\"<\/span><span class=\"s2\">use client<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">import<\/span> <span class=\"nx\">React<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">createContext<\/span><span class=\"p\">,<\/span> <span class=\"nx\">useContext<\/span><span class=\"p\">,<\/span> <span class=\"nx\">useEffect<\/span><span class=\"p\">,<\/span> <span class=\"nx\">useState<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">react<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">WeiDB<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/types\/database<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">useDatabase<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">.\/DatabaseContext<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kr\">interface<\/span> <span class=\"nx\">UserCache<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">profile<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">habits<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">[];<\/span>\n  <span class=\"nl\">completions<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">[];<\/span>\n  <span class=\"nl\">rewards<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">[];<\/span>\n  <span class=\"nl\">redemptions<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">[];<\/span>\n  <span class=\"nl\">points<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">streak<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">recentActivity<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">[];<\/span>\n  <span class=\"nl\">lastUpdated<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Date<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"kr\">interface<\/span> <span class=\"nx\">UserCacheContextType<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">cache<\/span><span class=\"p\">:<\/span> <span class=\"nx\">UserCache<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">isLoading<\/span><span class=\"p\">:<\/span> <span class=\"nx\">boolean<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">error<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Error<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">refreshCache<\/span><span class=\"p\">:<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nb\">Promise<\/span><span class=\"o\">&lt;<\/span><span class=\"k\">void<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"kd\">const<\/span> <span class=\"nx\">UserCacheContext<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">createContext<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">UserCacheContextType<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kd\">const<\/span> <span class=\"nx\">useUserCache<\/span> <span class=\"o\">=<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">context<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useContext<\/span><span class=\"p\">(<\/span><span class=\"nx\">UserCacheContext<\/span><span class=\"p\">);<\/span>\n  <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">context<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">throw<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">useUserCache must be used within a UserCacheProvider<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">}<\/span>\n  <span class=\"k\">return<\/span> <span class=\"nx\">context<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">};<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kd\">const<\/span> <span class=\"nx\">UserCacheProvider<\/span><span class=\"p\">:<\/span> <span class=\"nx\">React<\/span><span class=\"p\">.<\/span><span class=\"nx\">FC<\/span><span class=\"o\">&lt;<\/span><span class=\"p\">{<\/span> <span class=\"na\">children<\/span><span class=\"p\">:<\/span> <span class=\"nx\">React<\/span><span class=\"p\">.<\/span><span class=\"nx\">ReactNode<\/span> <span class=\"p\">}<\/span><span class=\"o\">&gt;<\/span> <span class=\"o\">=<\/span> <span class=\"p\">({<\/span> <span class=\"nx\">children<\/span> <span class=\"p\">})<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">db<\/span><span class=\"p\">,<\/span> <span class=\"na\">isLoading<\/span><span class=\"p\">:<\/span> <span class=\"nx\">dbLoading<\/span> <span class=\"p\">}<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useDatabase<\/span><span class=\"p\">();<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">cache<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setCache<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">UserCache<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">isLoading<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setIsLoading<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">boolean<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">true<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">error<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setError<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"nb\">Error<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">fetchUserData<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async <\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">db<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">warn<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">UserCacheProvider: Database not available yet<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n      <span class=\"k\">return<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"nf\">setIsLoading<\/span><span class=\"p\">(<\/span><span class=\"kc\">true<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n      <span class=\"c1\">\/\/ Get user profile<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">profile<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">get<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">userProfile<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">default<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n\n      <span class=\"c1\">\/\/ Get user stats<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">userData<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">get<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">user<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">default<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n\n      <span class=\"c1\">\/\/ Get habits<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">habits<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">getAll<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">habits<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n\n      <span class=\"c1\">\/\/ Get all completions<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">allCompletions<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">getAll<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">completions<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n\n      <span class=\"c1\">\/\/ Filter recent completions (last 30 days)<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">thirtyDaysAgo<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">();<\/span>\n      <span class=\"nx\">thirtyDaysAgo<\/span><span class=\"p\">.<\/span><span class=\"nf\">setDate<\/span><span class=\"p\">(<\/span><span class=\"nx\">thirtyDaysAgo<\/span><span class=\"p\">.<\/span><span class=\"nf\">getDate<\/span><span class=\"p\">()<\/span> <span class=\"o\">-<\/span> <span class=\"mi\">30<\/span><span class=\"p\">);<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">completions<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">allCompletions<\/span><span class=\"p\">.<\/span><span class=\"nf\">filter<\/span><span class=\"p\">(<\/span>\n        <span class=\"nx\">completion<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(<\/span><span class=\"nx\">completion<\/span><span class=\"p\">.<\/span><span class=\"nx\">completedAt<\/span><span class=\"p\">)<\/span> <span class=\"o\">&gt;=<\/span> <span class=\"nx\">thirtyDaysAgo<\/span>\n      <span class=\"p\">);<\/span>\n\n      <span class=\"c1\">\/\/ Get rewards<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">rewards<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">getAll<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">rewards<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n\n      <span class=\"c1\">\/\/ Get redemptions (last 30 days)<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">allRedemptions<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">getAll<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">rewardRedemptions<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">redemptions<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">allRedemptions<\/span><span class=\"p\">.<\/span><span class=\"nf\">filter<\/span><span class=\"p\">(<\/span>\n        <span class=\"nx\">redemption<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(<\/span><span class=\"nx\">redemption<\/span><span class=\"p\">.<\/span><span class=\"nx\">redeemedAt<\/span><span class=\"p\">)<\/span> <span class=\"o\">&gt;=<\/span> <span class=\"nx\">thirtyDaysAgo<\/span>\n      <span class=\"p\">);<\/span>\n\n      <span class=\"c1\">\/\/ Calculate streak<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">streakDays<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">userData<\/span><span class=\"p\">?.<\/span><span class=\"nx\">streakDays<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">0<\/span><span class=\"p\">;<\/span>\n\n      <span class=\"c1\">\/\/ Format recent activity<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">recentActivity<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">formatRecentActivity<\/span><span class=\"p\">(<\/span><span class=\"nx\">habits<\/span><span class=\"p\">,<\/span> <span class=\"nx\">completions<\/span><span class=\"p\">,<\/span> <span class=\"nx\">rewards<\/span><span class=\"p\">,<\/span> <span class=\"nx\">redemptions<\/span><span class=\"p\">);<\/span>\n\n      <span class=\"c1\">\/\/ Create the cache object<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"na\">newCache<\/span><span class=\"p\">:<\/span> <span class=\"nx\">UserCache<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">profile<\/span><span class=\"p\">:<\/span> <span class=\"nx\">profile<\/span> <span class=\"o\">||<\/span> <span class=\"p\">{},<\/span>\n        <span class=\"na\">habits<\/span><span class=\"p\">:<\/span> <span class=\"nx\">habits<\/span> <span class=\"o\">||<\/span> <span class=\"p\">[],<\/span>\n        <span class=\"na\">completions<\/span><span class=\"p\">:<\/span> <span class=\"nx\">completions<\/span> <span class=\"o\">||<\/span> <span class=\"p\">[],<\/span>\n        <span class=\"na\">rewards<\/span><span class=\"p\">:<\/span> <span class=\"nx\">rewards<\/span> <span class=\"o\">||<\/span> <span class=\"p\">[],<\/span>\n        <span class=\"na\">redemptions<\/span><span class=\"p\">:<\/span> <span class=\"nx\">redemptions<\/span> <span class=\"o\">||<\/span> <span class=\"p\">[],<\/span>\n        <span class=\"na\">points<\/span><span class=\"p\">:<\/span> <span class=\"nx\">userData<\/span><span class=\"p\">?.<\/span><span class=\"nx\">points<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">0<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">streak<\/span><span class=\"p\">:<\/span> <span class=\"nx\">streakDays<\/span><span class=\"p\">,<\/span>\n        <span class=\"nx\">recentActivity<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">lastUpdated<\/span><span class=\"p\">:<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">()<\/span>\n      <span class=\"p\">};<\/span>\n\n      <span class=\"nf\">setCache<\/span><span class=\"p\">(<\/span><span class=\"nx\">newCache<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">err<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Failed to fetch user data for cache:<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">err<\/span><span class=\"p\">);<\/span>\n      <span class=\"nf\">setError<\/span><span class=\"p\">(<\/span><span class=\"nx\">err<\/span> <span class=\"k\">instanceof<\/span> <span class=\"nb\">Error<\/span> <span class=\"p\">?<\/span> <span class=\"nx\">err<\/span> <span class=\"p\">:<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Unknown error fetching user data<\/span><span class=\"dl\">'<\/span><span class=\"p\">));<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">finally<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nf\">setIsLoading<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"c1\">\/\/ Define activity types for type safety<\/span>\n  <span class=\"kd\">type<\/span> <span class=\"nx\">CompletionActivity<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">completion<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">date<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Date<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">points<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">details<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">habitName<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">habitId<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">};<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">type<\/span> <span class=\"nx\">RedemptionActivity<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">redemption<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">date<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Date<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">points<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">details<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">rewardName<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">rewardId<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">};<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">type<\/span> <span class=\"nx\">Activity<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">CompletionActivity<\/span> <span class=\"o\">|<\/span> <span class=\"nx\">RedemptionActivity<\/span><span class=\"p\">;<\/span>\n\n  <span class=\"c1\">\/\/ Format recent activity for cache<\/span>\n  <span class=\"kd\">function<\/span> <span class=\"nf\">formatRecentActivity<\/span><span class=\"p\">(<\/span>\n    <span class=\"na\">habits<\/span><span class=\"p\">:<\/span> <span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">habits<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">][],<\/span> \n    <span class=\"na\">completions<\/span><span class=\"p\">:<\/span> <span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">completions<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">][],<\/span> \n    <span class=\"na\">rewards<\/span><span class=\"p\">:<\/span> <span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">rewards<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">][],<\/span> \n    <span class=\"na\">redemptions<\/span><span class=\"p\">:<\/span> <span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">rewardRedemptions<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">][]<\/span>\n  <span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"c1\">\/\/ Combine completions and redemptions<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"na\">allActivities<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Activity<\/span><span class=\"p\">[]<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span>\n      <span class=\"p\">...<\/span><span class=\"nx\">completions<\/span><span class=\"p\">.<\/span><span class=\"nf\">map<\/span><span class=\"p\">(<\/span><span class=\"nx\">completion<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">habit<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">habits<\/span><span class=\"p\">.<\/span><span class=\"nf\">find<\/span><span class=\"p\">(<\/span><span class=\"nx\">h<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">h<\/span><span class=\"p\">.<\/span><span class=\"nx\">id<\/span> <span class=\"o\">===<\/span> <span class=\"nx\">completion<\/span><span class=\"p\">.<\/span><span class=\"nx\">habitId<\/span><span class=\"p\">);<\/span>\n        <span class=\"k\">return<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">completion<\/span><span class=\"dl\">'<\/span> <span class=\"k\">as<\/span> <span class=\"kd\">const<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">date<\/span><span class=\"p\">:<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(<\/span><span class=\"nx\">completion<\/span><span class=\"p\">.<\/span><span class=\"nx\">completedAt<\/span><span class=\"p\">),<\/span>\n          <span class=\"na\">points<\/span><span class=\"p\">:<\/span> <span class=\"nx\">completion<\/span><span class=\"p\">.<\/span><span class=\"nx\">points<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">details<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n            <span class=\"na\">habitName<\/span><span class=\"p\">:<\/span> <span class=\"nx\">habit<\/span><span class=\"p\">?.<\/span><span class=\"nx\">name<\/span> <span class=\"o\">||<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">Unknown habit<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n            <span class=\"na\">habitId<\/span><span class=\"p\">:<\/span> <span class=\"nx\">completion<\/span><span class=\"p\">.<\/span><span class=\"nx\">habitId<\/span>\n          <span class=\"p\">}<\/span>\n        <span class=\"p\">};<\/span>\n      <span class=\"p\">}),<\/span>\n      <span class=\"p\">...<\/span><span class=\"nx\">redemptions<\/span><span class=\"p\">.<\/span><span class=\"nf\">map<\/span><span class=\"p\">(<\/span><span class=\"nx\">redemption<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">reward<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">rewards<\/span><span class=\"p\">.<\/span><span class=\"nf\">find<\/span><span class=\"p\">(<\/span><span class=\"nx\">r<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">r<\/span><span class=\"p\">.<\/span><span class=\"nx\">id<\/span> <span class=\"o\">===<\/span> <span class=\"nx\">redemption<\/span><span class=\"p\">.<\/span><span class=\"nx\">rewardId<\/span><span class=\"p\">);<\/span>\n        <span class=\"k\">return<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">redemption<\/span><span class=\"dl\">'<\/span> <span class=\"k\">as<\/span> <span class=\"kd\">const<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">date<\/span><span class=\"p\">:<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(<\/span><span class=\"nx\">redemption<\/span><span class=\"p\">.<\/span><span class=\"nx\">redeemedAt<\/span><span class=\"p\">),<\/span>\n          <span class=\"na\">points<\/span><span class=\"p\">:<\/span> <span class=\"o\">-<\/span><span class=\"nx\">redemption<\/span><span class=\"p\">.<\/span><span class=\"nx\">cost<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">details<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n            <span class=\"na\">rewardName<\/span><span class=\"p\">:<\/span> <span class=\"nx\">reward<\/span><span class=\"p\">?.<\/span><span class=\"nx\">name<\/span> <span class=\"o\">||<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">Unknown reward<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n            <span class=\"na\">rewardId<\/span><span class=\"p\">:<\/span> <span class=\"nx\">redemption<\/span><span class=\"p\">.<\/span><span class=\"nx\">rewardId<\/span>\n          <span class=\"p\">}<\/span>\n        <span class=\"p\">};<\/span>\n      <span class=\"p\">})<\/span>\n    <span class=\"p\">];<\/span>\n\n    <span class=\"c1\">\/\/ Sort by date (newest first)<\/span>\n    <span class=\"nx\">allActivities<\/span><span class=\"p\">.<\/span><span class=\"nf\">sort<\/span><span class=\"p\">((<\/span><span class=\"nx\">a<\/span><span class=\"p\">,<\/span> <span class=\"nx\">b<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">b<\/span><span class=\"p\">.<\/span><span class=\"nx\">date<\/span><span class=\"p\">.<\/span><span class=\"nf\">getTime<\/span><span class=\"p\">()<\/span> <span class=\"o\">-<\/span> <span class=\"nx\">a<\/span><span class=\"p\">.<\/span><span class=\"nx\">date<\/span><span class=\"p\">.<\/span><span class=\"nf\">getTime<\/span><span class=\"p\">());<\/span>\n\n    <span class=\"c1\">\/\/ Take the 5 most recent activities<\/span>\n    <span class=\"k\">return<\/span> <span class=\"nx\">allActivities<\/span><span class=\"p\">.<\/span><span class=\"nf\">slice<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"mi\">5<\/span><span class=\"p\">).<\/span><span class=\"nf\">map<\/span><span class=\"p\">(<\/span><span class=\"nx\">activity<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">formattedDate<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">activity<\/span><span class=\"p\">.<\/span><span class=\"nx\">date<\/span><span class=\"p\">.<\/span><span class=\"nf\">toLocaleDateString<\/span><span class=\"p\">();<\/span>\n\n      <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">activity<\/span><span class=\"p\">.<\/span><span class=\"kd\">type<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">completion<\/span><span class=\"dl\">'<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">return<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">action<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">Completed<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">target<\/span><span class=\"p\">:<\/span> <span class=\"nx\">activity<\/span><span class=\"p\">.<\/span><span class=\"nx\">details<\/span><span class=\"p\">.<\/span><span class=\"nx\">habitName<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">date<\/span><span class=\"p\">:<\/span> <span class=\"nx\">formattedDate<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">points<\/span><span class=\"p\">:<\/span> <span class=\"nx\">activity<\/span><span class=\"p\">.<\/span><span class=\"nx\">points<\/span>\n        <span class=\"p\">};<\/span>\n      <span class=\"p\">}<\/span> <span class=\"k\">else<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">return<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">action<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">Redeemed<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">target<\/span><span class=\"p\">:<\/span> <span class=\"nx\">activity<\/span><span class=\"p\">.<\/span><span class=\"nx\">details<\/span><span class=\"p\">.<\/span><span class=\"nx\">rewardName<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">date<\/span><span class=\"p\">:<\/span> <span class=\"nx\">formattedDate<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">points<\/span><span class=\"p\">:<\/span> <span class=\"nx\">activity<\/span><span class=\"p\">.<\/span><span class=\"nx\">points<\/span>\n        <span class=\"p\">};<\/span>\n      <span class=\"p\">}<\/span>\n    <span class=\"p\">});<\/span>\n  <span class=\"p\">}<\/span>\n\n  <span class=\"c1\">\/\/ Initialize cache when database is available<\/span>\n  <span class=\"nf\">useEffect<\/span><span class=\"p\">(()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">db<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"o\">!<\/span><span class=\"nx\">dbLoading<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nf\">fetchUserData<\/span><span class=\"p\">();<\/span>\n\n      <span class=\"c1\">\/\/ Refresh cache every 5 minutes<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">intervalId<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">setInterval<\/span><span class=\"p\">(<\/span><span class=\"nx\">fetchUserData<\/span><span class=\"p\">,<\/span> <span class=\"mi\">5<\/span> <span class=\"o\">*<\/span> <span class=\"mi\">60<\/span> <span class=\"o\">*<\/span> <span class=\"mi\">1000<\/span><span class=\"p\">);<\/span>\n\n      <span class=\"k\">return <\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nf\">clearInterval<\/span><span class=\"p\">(<\/span><span class=\"nx\">intervalId<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">},<\/span> <span class=\"p\">[<\/span><span class=\"nx\">db<\/span><span class=\"p\">,<\/span> <span class=\"nx\">dbLoading<\/span><span class=\"p\">]);<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">refreshCache<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async <\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">await<\/span> <span class=\"nf\">fetchUserData<\/span><span class=\"p\">();<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"k\">return <\/span><span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nc\">UserCacheContext<\/span><span class=\"p\">.<\/span><span class=\"nc\">Provider<\/span> <span class=\"na\">value<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"p\">{<\/span> <span class=\"nx\">cache<\/span><span class=\"p\">,<\/span> <span class=\"nx\">isLoading<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">,<\/span> <span class=\"nx\">refreshCache<\/span> <span class=\"p\">}<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"si\">{<\/span><span class=\"nx\">children<\/span><span class=\"si\">}<\/span>\n    <span class=\"p\"\/><span class=\"nc\">UserCacheContext<\/span><span class=\"p\">.<\/span><span class=\"nc\">Provider<\/span><span class=\"p\">&gt;<\/span>\n  <span class=\"p\">);<\/span>\n<span class=\"p\">};<\/span> \n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"%D8%A7%D8%B1%D8%A7%D8%A6%D9%87_%D8%AF%D9%87%D9%86%D8%AF%DA%AF%D8%A7%D9%86_%D8%B2%D9%85%DB%8C%D9%86%D9%87_%D8%AD%D8%A7%D9%81%D8%B8%D9%87_%D9%BE%D9%86%D9%87%D8%A7%D9%86_%DA%A9%D8%A7%D8%B1%D8%A8%D8%B1\"><\/span>\n<p>  \u0627\u0631\u0627\u0626\u0647 \u062f\u0647\u0646\u062f\u06af\u0627\u0646 (\u0632\u0645\u06cc\u0646\u0647 \u062d\u0627\u0641\u0638\u0647 \u067e\u0646\u0647\u0627\u0646 \u06a9\u0627\u0631\u0628\u0631)<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0628\u0631\u0646\u0627\u0645\u0647 \u0631\u0627 \u0628\u0627 <code>UserCacheProvider<\/code> \u0645\u0624\u0644\u0641\u0647<\/p>\n<p>\u067e\u0631\u0648\u0646\u062f\u0647 \u0628\u0627\u0632 <code>app\/providers.tsx<\/code>\u0628\u0634\u0631<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"dl\">\"<\/span><span class=\"s2\">use client<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">import<\/span> <span class=\"nx\">React<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">react<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">ThemeProvider<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">next-themes<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">DatabaseProvider<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/contexts\/DatabaseContext<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">UserCacheProvider<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/contexts\/UserCacheContext<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">ChatProvider<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/contexts\/ChatContext<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">RealTimeStreamingMode<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/RealTimeStreamingMode<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">usePathname<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">next\/navigation<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">Providers<\/span><span class=\"p\">({<\/span> <span class=\"nx\">children<\/span> <span class=\"p\">}:<\/span> <span class=\"p\">{<\/span> <span class=\"nl\">children<\/span><span class=\"p\">:<\/span> <span class=\"nx\">React<\/span><span class=\"p\">.<\/span><span class=\"nx\">ReactNode<\/span> <span class=\"p\">})<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">pathname<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">usePathname<\/span><span class=\"p\">();<\/span>\n  <span class=\"k\">return <\/span><span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nc\">ThemeProvider<\/span> <span class=\"na\">attribute<\/span><span class=\"p\">=<\/span><span class=\"s\">\"class\"<\/span> <span class=\"na\">defaultTheme<\/span><span class=\"p\">=<\/span><span class=\"s\">\"dark\"<\/span> <span class=\"na\">enableSystem<\/span> <span class=\"na\">forcedTheme<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">pathname<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">\/<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">?<\/span> <span class=\"kc\">undefined<\/span> <span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">dark<\/span><span class=\"dl\">\"<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nc\">DatabaseProvider<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nc\">UserCacheProvider<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nc\">ChatProvider<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"si\">{<\/span><span class=\"nx\">children<\/span><span class=\"si\">}<\/span>\n              <span class=\"si\">{<\/span><span class=\"nx\">pathname<\/span> <span class=\"o\">!==<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">\/<\/span><span class=\"dl\">\"<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"p\">&lt;<\/span><span class=\"nc\">RealTimeStreamingMode<\/span> <span class=\"p\">\/&gt;<\/span><span class=\"si\">}<\/span>\n          <span class=\"p\"\/><span class=\"nc\">ChatProvider<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\"\/><span class=\"nc\">UserCacheProvider<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\"\/><span class=\"nc\">DatabaseProvider<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\"\/><span class=\"nc\">ThemeProvider<\/span><span class=\"p\">&gt;<\/span>\n  <span class=\"p\">);<\/span>\n<span class=\"p\">}<\/span> \n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"%DA%AF%D9%BE_%D8%B5%D9%88%D8%AA%DB%8C\"><\/span>\n<p>  \u06af\u067e \u0635\u0648\u062a\u06cc<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p><img decoding=\"async\" src=\"https:\/\/media2.dev.to\/dynamic\/image\/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto\/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvb0szhim56z2h3viqg6f.png\" alt=\"\u0648\u06cc\u0698\u06af\u06cc \u0647\u0627\u06cc \u0648\u06cc\" loading=\"lazy\" width=\"800\" height=\"450\" title=\"\"><\/p>\n<h4><span class=\"ez-toc-section\" id=\"%D8%B1%D8%B3%DB%8C%D8%AF%DA%AF%DB%8C_%D8%A8%D9%87_%D8%B1%D9%88%DB%8C%D8%AF%D8%A7%D8%AF_%D8%B3%D8%B1%D9%88%D8%B1_%D9%87%D9%88%DA%A9\"><\/span>\n<p>  \u0631\u0633\u06cc\u062f\u06af\u06cc \u0628\u0647 \u0631\u0648\u06cc\u062f\u0627\u062f \u0633\u0631\u0648\u0631 (\u0647\u0648\u06a9)<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>\u0627\u06cc\u0646 \u0642\u0644\u0627\u0628 \u0628\u0631\u0627\u06cc \u0631\u0633\u06cc\u062f\u06af\u06cc \u0628\u0647 \u0631\u0648\u06cc\u062f\u0627\u062f\u0647\u0627\u06cc \u0633\u0631\u0648\u0631 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u0634\u0648\u062f.<br \/>\u0627\u0632 \u0622\u0646 \u0628\u0631\u0627\u06cc \u0648\u06cc\u0698\u06af\u06cc \u0686\u062a \u0635\u0648\u062a\u06cc \u0628\u0627 \u0639\u0648\u0627\u0645\u0644 AI \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u0634\u0648\u062f.<br \/>\u062a\u0648\u0627\u0628\u0639 \u0645\u062e\u062a\u0644\u0641 \u0627\u0632 \u062c\u0645\u0644\u0647: <\/p>\n<ul>\n<li>\u062c\u0644\u0633\u0647.<\/li>\n<li>COORLOY.ITEM.CREATED<\/li>\n<li>COORCOLY.ITEM.INPUT_AUDIO_Transcription.completed<\/li>\n<li>\u067e\u0627\u0633\u062e. saudio_transcript.delta<\/li>\n<li>\u067e\u0627\u0633\u062e<\/li>\n<\/ul>\n<p>\u0645\u0645\u06a9\u0646 \u0627\u0633\u062a \u062f\u0631 \u0627\u06cc\u0646\u062c\u0627 \u062f\u0631\u0628\u0627\u0631\u0647 API OpenAi Realtime \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u0628\u06cc\u0634\u062a\u0631\u06cc \u06a9\u0633\u0628 \u06a9\u0646\u06cc\u062f.<\/p>\n<p>\u06cc\u06a9 \u0641\u0627\u06cc\u0644 \u062c\u062f\u06cc\u062f \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f <code>app\/hooks\/useHandleServerEvent.ts<\/code>\u0628\u0634\u0631<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"dl\">\"<\/span><span class=\"s2\">use client<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">ServerEvent<\/span><span class=\"p\">,<\/span> <span class=\"nx\">SessionStatus<\/span><span class=\"p\">,<\/span> <span class=\"nx\">AgentConfig<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/app\/types<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">useTranscript<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/app\/contexts\/TranscriptContext<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">useEvent<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/app\/contexts\/EventContext<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">useRef<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">react<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kr\">interface<\/span> <span class=\"nx\">UseHandleServerEventParams<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">setSessionStatus<\/span><span class=\"p\">:<\/span> <span class=\"p\">(<\/span><span class=\"nx\">status<\/span><span class=\"p\">:<\/span> <span class=\"nx\">SessionStatus<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"k\">void<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">selectedAgentName<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">selectedAgentConfigSet<\/span><span class=\"p\">:<\/span> <span class=\"nx\">AgentConfig<\/span><span class=\"p\">[]<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">sendClientEvent<\/span><span class=\"p\">:<\/span> <span class=\"p\">(<\/span><span class=\"nx\">eventObj<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">,<\/span> <span class=\"nx\">eventNameSuffix<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"k\">void<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">setSelectedAgentName<\/span><span class=\"p\">:<\/span> <span class=\"p\">(<\/span><span class=\"nx\">name<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"k\">void<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">setIsAssistantSpeaking<\/span><span class=\"p\">?:<\/span> <span class=\"p\">(<\/span><span class=\"nx\">isSpeaking<\/span><span class=\"p\">:<\/span> <span class=\"nx\">boolean<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"k\">void<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">shouldForceResponse<\/span><span class=\"p\">?:<\/span> <span class=\"nx\">boolean<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">useHandleServerEvent<\/span><span class=\"p\">({<\/span>\n  <span class=\"nx\">setSessionStatus<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">selectedAgentName<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">selectedAgentConfigSet<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">sendClientEvent<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">setSelectedAgentName<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">setIsAssistantSpeaking<\/span><span class=\"p\">,<\/span>\n<span class=\"p\">}:<\/span> <span class=\"nx\">UseHandleServerEventParams<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">transcriptItems<\/span><span class=\"p\">,<\/span>\n    <span class=\"nx\">addTranscriptBreadcrumb<\/span><span class=\"p\">,<\/span>\n    <span class=\"nx\">addTranscriptMessage<\/span><span class=\"p\">,<\/span>\n    <span class=\"nx\">updateTranscriptMessage<\/span><span class=\"p\">,<\/span>\n    <span class=\"nx\">updateTranscriptItemStatus<\/span><span class=\"p\">,<\/span>\n  <span class=\"p\">}<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useTranscript<\/span><span class=\"p\">();<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">logServerEvent<\/span> <span class=\"p\">}<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useEvent<\/span><span class=\"p\">();<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">handleFunctionCall<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async <\/span><span class=\"p\">(<\/span><span class=\"nx\">functionCallParams<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nl\">name<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">call_id<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">arguments<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">})<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">args<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">parse<\/span><span class=\"p\">(<\/span><span class=\"nx\">functionCallParams<\/span><span class=\"p\">.<\/span><span class=\"nx\">arguments<\/span><span class=\"p\">);<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">currentAgent<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">selectedAgentConfigSet<\/span><span class=\"p\">?.<\/span><span class=\"nf\">find<\/span><span class=\"p\">(<\/span>\n      <span class=\"p\">(<\/span><span class=\"nx\">a<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">a<\/span><span class=\"p\">.<\/span><span class=\"nx\">name<\/span> <span class=\"o\">===<\/span> <span class=\"nx\">selectedAgentName<\/span>\n    <span class=\"p\">);<\/span>\n\n    <span class=\"nf\">addTranscriptBreadcrumb<\/span><span class=\"p\">(<\/span><span class=\"s2\">`function call: <\/span><span class=\"p\">${<\/span><span class=\"nx\">functionCallParams<\/span><span class=\"p\">.<\/span><span class=\"nx\">name<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span><span class=\"p\">,<\/span> <span class=\"nx\">args<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">currentAgent<\/span><span class=\"p\">?.<\/span><span class=\"nx\">toolLogic<\/span><span class=\"p\">?.[<\/span><span class=\"nx\">functionCallParams<\/span><span class=\"p\">.<\/span><span class=\"nx\">name<\/span><span class=\"p\">])<\/span> <span class=\"p\">{<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">fn<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">currentAgent<\/span><span class=\"p\">.<\/span><span class=\"nx\">toolLogic<\/span><span class=\"p\">[<\/span><span class=\"nx\">functionCallParams<\/span><span class=\"p\">.<\/span><span class=\"nx\">name<\/span><span class=\"p\">];<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">fnResult<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">fn<\/span><span class=\"p\">(<\/span><span class=\"nx\">args<\/span><span class=\"p\">,<\/span> <span class=\"nx\">transcriptItems<\/span><span class=\"p\">);<\/span>\n      <span class=\"nf\">addTranscriptBreadcrumb<\/span><span class=\"p\">(<\/span>\n        <span class=\"s2\">`function call result: <\/span><span class=\"p\">${<\/span><span class=\"nx\">functionCallParams<\/span><span class=\"p\">.<\/span><span class=\"nx\">name<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span><span class=\"p\">,<\/span>\n        <span class=\"nx\">fnResult<\/span>\n      <span class=\"p\">);<\/span>\n\n      <span class=\"nf\">sendClientEvent<\/span><span class=\"p\">({<\/span>\n        <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">conversation.item.create<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">item<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">function_call_output<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">call_id<\/span><span class=\"p\">:<\/span> <span class=\"nx\">functionCallParams<\/span><span class=\"p\">.<\/span><span class=\"nx\">call_id<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">output<\/span><span class=\"p\">:<\/span> <span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">stringify<\/span><span class=\"p\">(<\/span><span class=\"nx\">fnResult<\/span><span class=\"p\">),<\/span>\n        <span class=\"p\">},<\/span>\n      <span class=\"p\">});<\/span>\n      <span class=\"nf\">sendClientEvent<\/span><span class=\"p\">({<\/span> <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">response.create<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">});<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">else<\/span> <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">functionCallParams<\/span><span class=\"p\">.<\/span><span class=\"nx\">name<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">transferAgents<\/span><span class=\"dl\">\"<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">destinationAgent<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">args<\/span><span class=\"p\">.<\/span><span class=\"nx\">destination_agent<\/span><span class=\"p\">;<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">newAgentConfig<\/span> <span class=\"o\">=<\/span>\n        <span class=\"nx\">selectedAgentConfigSet<\/span><span class=\"p\">?.<\/span><span class=\"nf\">find<\/span><span class=\"p\">((<\/span><span class=\"nx\">a<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">a<\/span><span class=\"p\">.<\/span><span class=\"nx\">name<\/span> <span class=\"o\">===<\/span> <span class=\"nx\">destinationAgent<\/span><span class=\"p\">)<\/span> <span class=\"o\">||<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n      <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">newAgentConfig<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nf\">setSelectedAgentName<\/span><span class=\"p\">(<\/span><span class=\"nx\">destinationAgent<\/span><span class=\"p\">);<\/span>\n      <span class=\"p\">}<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">functionCallOutput<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">destination_agent<\/span><span class=\"p\">:<\/span> <span class=\"nx\">destinationAgent<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">did_transfer<\/span><span class=\"p\">:<\/span> <span class=\"o\">!!<\/span><span class=\"nx\">newAgentConfig<\/span><span class=\"p\">,<\/span>\n      <span class=\"p\">};<\/span>\n      <span class=\"nf\">sendClientEvent<\/span><span class=\"p\">({<\/span>\n        <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">conversation.item.create<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">item<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">function_call_output<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">call_id<\/span><span class=\"p\">:<\/span> <span class=\"nx\">functionCallParams<\/span><span class=\"p\">.<\/span><span class=\"nx\">call_id<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">output<\/span><span class=\"p\">:<\/span> <span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">stringify<\/span><span class=\"p\">(<\/span><span class=\"nx\">functionCallOutput<\/span><span class=\"p\">),<\/span>\n        <span class=\"p\">},<\/span>\n      <span class=\"p\">});<\/span>\n      <span class=\"nf\">addTranscriptBreadcrumb<\/span><span class=\"p\">(<\/span>\n        <span class=\"s2\">`function call: <\/span><span class=\"p\">${<\/span><span class=\"nx\">functionCallParams<\/span><span class=\"p\">.<\/span><span class=\"nx\">name<\/span><span class=\"p\">}<\/span><span class=\"s2\"> response`<\/span><span class=\"p\">,<\/span>\n        <span class=\"nx\">functionCallOutput<\/span>\n      <span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">else<\/span> <span class=\"p\">{<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">simulatedResult<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span> <span class=\"na\">result<\/span><span class=\"p\">:<\/span> <span class=\"kc\">true<\/span> <span class=\"p\">};<\/span>\n      <span class=\"nf\">addTranscriptBreadcrumb<\/span><span class=\"p\">(<\/span>\n        <span class=\"s2\">`function call fallback: <\/span><span class=\"p\">${<\/span><span class=\"nx\">functionCallParams<\/span><span class=\"p\">.<\/span><span class=\"nx\">name<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span><span class=\"p\">,<\/span>\n        <span class=\"nx\">simulatedResult<\/span>\n      <span class=\"p\">);<\/span>\n\n      <span class=\"nf\">sendClientEvent<\/span><span class=\"p\">({<\/span>\n        <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">conversation.item.create<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">item<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">function_call_output<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">call_id<\/span><span class=\"p\">:<\/span> <span class=\"nx\">functionCallParams<\/span><span class=\"p\">.<\/span><span class=\"nx\">call_id<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">output<\/span><span class=\"p\">:<\/span> <span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">stringify<\/span><span class=\"p\">(<\/span><span class=\"nx\">simulatedResult<\/span><span class=\"p\">),<\/span>\n        <span class=\"p\">},<\/span>\n      <span class=\"p\">});<\/span>\n      <span class=\"nf\">sendClientEvent<\/span><span class=\"p\">({<\/span> <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">response.create<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">});<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">handleServerEvent<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"nx\">serverEvent<\/span><span class=\"p\">:<\/span> <span class=\"nx\">ServerEvent<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nf\">logServerEvent<\/span><span class=\"p\">(<\/span><span class=\"nx\">serverEvent<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"k\">switch <\/span><span class=\"p\">(<\/span><span class=\"nx\">serverEvent<\/span><span class=\"p\">.<\/span><span class=\"kd\">type<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">case<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">session.created<\/span><span class=\"dl\">\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">serverEvent<\/span><span class=\"p\">.<\/span><span class=\"nx\">session<\/span><span class=\"p\">?.<\/span><span class=\"nx\">id<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n          <span class=\"nf\">setSessionStatus<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">CONNECTED<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n          <span class=\"nf\">addTranscriptBreadcrumb<\/span><span class=\"p\">(<\/span>\n            <span class=\"s2\">`session.id: <\/span><span class=\"p\">${<\/span>\n              <span class=\"nx\">serverEvent<\/span><span class=\"p\">.<\/span><span class=\"nx\">session<\/span><span class=\"p\">.<\/span><span class=\"nx\">id<\/span>\n            <span class=\"p\">}<\/span><span class=\"s2\">\\nStarted at: <\/span><span class=\"p\">${<\/span><span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">().<\/span><span class=\"nf\">toLocaleString<\/span><span class=\"p\">()}<\/span><span class=\"s2\">`<\/span>\n          <span class=\"p\">);<\/span>\n        <span class=\"p\">}<\/span>\n        <span class=\"k\">break<\/span><span class=\"p\">;<\/span>\n      <span class=\"p\">}<\/span>\n\n      <span class=\"k\">case<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">conversation.item.created<\/span><span class=\"dl\">\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"kd\">let<\/span> <span class=\"nx\">text<\/span> <span class=\"o\">=<\/span>\n          <span class=\"nx\">serverEvent<\/span><span class=\"p\">.<\/span><span class=\"nx\">item<\/span><span class=\"p\">?.<\/span><span class=\"nx\">content<\/span><span class=\"p\">?.[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]?.<\/span><span class=\"nx\">text<\/span> <span class=\"o\">||<\/span>\n          <span class=\"nx\">serverEvent<\/span><span class=\"p\">.<\/span><span class=\"nx\">item<\/span><span class=\"p\">?.<\/span><span class=\"nx\">content<\/span><span class=\"p\">?.[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]?.<\/span><span class=\"nx\">transcript<\/span> <span class=\"o\">||<\/span>\n          <span class=\"dl\">\"\"<\/span><span class=\"p\">;<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">role<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">serverEvent<\/span><span class=\"p\">.<\/span><span class=\"nx\">item<\/span><span class=\"p\">?.<\/span><span class=\"nx\">role<\/span> <span class=\"k\">as<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">user<\/span><span class=\"dl\">\"<\/span> <span class=\"o\">|<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">assistant<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">itemId<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">serverEvent<\/span><span class=\"p\">.<\/span><span class=\"nx\">item<\/span><span class=\"p\">?.<\/span><span class=\"nx\">id<\/span><span class=\"p\">;<\/span>\n\n        <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">itemId<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">transcriptItems<\/span><span class=\"p\">.<\/span><span class=\"nf\">some<\/span><span class=\"p\">((<\/span><span class=\"nx\">item<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">item<\/span><span class=\"p\">.<\/span><span class=\"nx\">itemId<\/span> <span class=\"o\">===<\/span> <span class=\"nx\">itemId<\/span><span class=\"p\">))<\/span> <span class=\"p\">{<\/span>\n          <span class=\"k\">break<\/span><span class=\"p\">;<\/span>\n        <span class=\"p\">}<\/span>\n\n        <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">itemId<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">role<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n          <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">role<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">user<\/span><span class=\"dl\">\"<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"o\">!<\/span><span class=\"nx\">text<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n            <span class=\"nx\">text<\/span> <span class=\"o\">=<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">[Transcribing...]<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n          <span class=\"p\">}<\/span>\n          <span class=\"nf\">addTranscriptMessage<\/span><span class=\"p\">(<\/span><span class=\"nx\">itemId<\/span><span class=\"p\">,<\/span> <span class=\"nx\">role<\/span><span class=\"p\">,<\/span> <span class=\"nx\">text<\/span><span class=\"p\">);<\/span>\n\n          <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">role<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">assistant<\/span><span class=\"dl\">\"<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">setIsAssistantSpeaking<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n            <span class=\"nf\">setIsAssistantSpeaking<\/span><span class=\"p\">(<\/span><span class=\"kc\">true<\/span><span class=\"p\">);<\/span>\n          <span class=\"p\">}<\/span>\n        <span class=\"p\">}<\/span>\n        <span class=\"k\">break<\/span><span class=\"p\">;<\/span>\n      <span class=\"p\">}<\/span>\n\n      <span class=\"k\">case<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">conversation.item.input_audio_transcription.completed<\/span><span class=\"dl\">\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">itemId<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">serverEvent<\/span><span class=\"p\">.<\/span><span class=\"nx\">item_id<\/span><span class=\"p\">;<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">finalTranscript<\/span> <span class=\"o\">=<\/span>\n          <span class=\"o\">!<\/span><span class=\"nx\">serverEvent<\/span><span class=\"p\">.<\/span><span class=\"nx\">transcript<\/span> <span class=\"o\">||<\/span> <span class=\"nx\">serverEvent<\/span><span class=\"p\">.<\/span><span class=\"nx\">transcript<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">\"<\/span><span class=\"se\">\\n<\/span><span class=\"dl\">\"<\/span>\n            <span class=\"p\">?<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">[inaudible]<\/span><span class=\"dl\">\"<\/span>\n            <span class=\"p\">:<\/span> <span class=\"nx\">serverEvent<\/span><span class=\"p\">.<\/span><span class=\"nx\">transcript<\/span><span class=\"p\">;<\/span>\n        <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">itemId<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n          <span class=\"nf\">updateTranscriptMessage<\/span><span class=\"p\">(<\/span><span class=\"nx\">itemId<\/span><span class=\"p\">,<\/span> <span class=\"nx\">finalTranscript<\/span><span class=\"p\">,<\/span> <span class=\"kc\">false<\/span><span class=\"p\">);<\/span>\n        <span class=\"p\">}<\/span>\n        <span class=\"k\">break<\/span><span class=\"p\">;<\/span>\n      <span class=\"p\">}<\/span>\n\n      <span class=\"k\">case<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">response.audio_transcript.delta<\/span><span class=\"dl\">\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">itemId<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">serverEvent<\/span><span class=\"p\">.<\/span><span class=\"nx\">item_id<\/span><span class=\"p\">;<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">deltaText<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">serverEvent<\/span><span class=\"p\">.<\/span><span class=\"nx\">delta<\/span> <span class=\"o\">||<\/span> <span class=\"dl\">\"\"<\/span><span class=\"p\">;<\/span>\n        <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">itemId<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n          <span class=\"nf\">updateTranscriptMessage<\/span><span class=\"p\">(<\/span><span class=\"nx\">itemId<\/span><span class=\"p\">,<\/span> <span class=\"nx\">deltaText<\/span><span class=\"p\">,<\/span> <span class=\"kc\">true<\/span><span class=\"p\">);<\/span>\n        <span class=\"p\">}<\/span>\n        <span class=\"k\">break<\/span><span class=\"p\">;<\/span>\n      <span class=\"p\">}<\/span>\n\n      <span class=\"k\">case<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">response.done<\/span><span class=\"dl\">\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">serverEvent<\/span><span class=\"p\">.<\/span><span class=\"nx\">response<\/span><span class=\"p\">?.<\/span><span class=\"nx\">output<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n          <span class=\"nx\">serverEvent<\/span><span class=\"p\">.<\/span><span class=\"nx\">response<\/span><span class=\"p\">.<\/span><span class=\"nx\">output<\/span><span class=\"p\">.<\/span><span class=\"nf\">forEach<\/span><span class=\"p\">((<\/span><span class=\"nx\">outputItem<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n            <span class=\"k\">if <\/span><span class=\"p\">(<\/span>\n              <span class=\"nx\">outputItem<\/span><span class=\"p\">.<\/span><span class=\"kd\">type<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">function_call<\/span><span class=\"dl\">\"<\/span> <span class=\"o\">&amp;&amp;<\/span>\n              <span class=\"nx\">outputItem<\/span><span class=\"p\">.<\/span><span class=\"nx\">name<\/span> <span class=\"o\">&amp;&amp;<\/span>\n              <span class=\"nx\">outputItem<\/span><span class=\"p\">.<\/span><span class=\"nx\">arguments<\/span>\n            <span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n              <span class=\"nf\">handleFunctionCall<\/span><span class=\"p\">({<\/span>\n                <span class=\"na\">name<\/span><span class=\"p\">:<\/span> <span class=\"nx\">outputItem<\/span><span class=\"p\">.<\/span><span class=\"nx\">name<\/span><span class=\"p\">,<\/span>\n                <span class=\"na\">call_id<\/span><span class=\"p\">:<\/span> <span class=\"nx\">outputItem<\/span><span class=\"p\">.<\/span><span class=\"nx\">call_id<\/span><span class=\"p\">,<\/span>\n                <span class=\"na\">arguments<\/span><span class=\"p\">:<\/span> <span class=\"nx\">outputItem<\/span><span class=\"p\">.<\/span><span class=\"nx\">arguments<\/span><span class=\"p\">,<\/span>\n              <span class=\"p\">});<\/span>\n            <span class=\"p\">}<\/span>\n          <span class=\"p\">});<\/span>\n        <span class=\"p\">}<\/span>\n        <span class=\"k\">break<\/span><span class=\"p\">;<\/span>\n      <span class=\"p\">}<\/span>\n\n      <span class=\"k\">case<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">response.output_item.done<\/span><span class=\"dl\">\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">itemId<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">serverEvent<\/span><span class=\"p\">.<\/span><span class=\"nx\">item<\/span><span class=\"p\">?.<\/span><span class=\"nx\">id<\/span><span class=\"p\">;<\/span>\n        <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">itemId<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n          <span class=\"nf\">updateTranscriptItemStatus<\/span><span class=\"p\">(<\/span><span class=\"nx\">itemId<\/span><span class=\"p\">,<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">DONE<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n\n          <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">setIsAssistantSpeaking<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n            <span class=\"nf\">setIsAssistantSpeaking<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">);<\/span>\n          <span class=\"p\">}<\/span>\n        <span class=\"p\">}<\/span>\n        <span class=\"k\">break<\/span><span class=\"p\">;<\/span>\n      <span class=\"p\">}<\/span>\n\n      <span class=\"nl\">default<\/span><span class=\"p\">:<\/span>\n        <span class=\"k\">break<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">handleServerEventRef<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useRef<\/span><span class=\"p\">(<\/span><span class=\"nx\">handleServerEvent<\/span><span class=\"p\">);<\/span>\n  <span class=\"nx\">handleServerEventRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">handleServerEvent<\/span><span class=\"p\">;<\/span>\n\n  <span class=\"k\">return<\/span> <span class=\"nx\">handleServerEventRef<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h4><span class=\"ez-toc-section\" id=\"%D8%AD%D8%A7%D9%84%D8%AA_%D8%AC%D8%B1%DB%8C%D8%A7%D9%86_%D9%88%D8%A7%D9%82%D8%B9%DB%8C\"><\/span>\n<p>  \u062d\u0627\u0644\u062a \u062c\u0631\u06cc\u0627\u0646 \u0648\u0627\u0642\u0639\u06cc<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>\u06cc\u06a9 \u0641\u0627\u06cc\u0644 \u062c\u062f\u06cc\u062f \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f <code>app\/RealTimeStreamingMode.tsx<\/code>\u0628\u0634\u0631<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"dl\">\"<\/span><span class=\"s2\">use client<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">import<\/span> <span class=\"nx\">React<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">useEffect<\/span><span class=\"p\">,<\/span> <span class=\"nx\">useRef<\/span><span class=\"p\">,<\/span> <span class=\"nx\">useState<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">react<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">usePathname<\/span><span class=\"p\">,<\/span> <span class=\"nx\">useSearchParams<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">next\/navigation<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">v4<\/span> <span class=\"k\">as<\/span> <span class=\"nx\">uuidv4<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">uuid<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"c1\">\/\/ UI components<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">VoiceTranscriptOverlay<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/components\/VoiceTranscriptOverlay<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">VoiceButton<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/components\/VoiceButton<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"c1\">\/\/ Types<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">AgentConfig<\/span><span class=\"p\">,<\/span> <span class=\"nx\">SessionStatus<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/app\/types<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"c1\">\/\/ Context providers &amp; hooks<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">useTranscript<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/app\/contexts\/TranscriptContext<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">useEvent<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/app\/contexts\/EventContext<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">useHandleServerEvent<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/hooks\/useHandleServerEvent<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"c1\">\/\/ Utilities<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">createRealtimeConnection<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/lib\/realtimeConnection<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"c1\">\/\/ Agent configs<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">allAgentSets<\/span><span class=\"p\">,<\/span> <span class=\"nx\">defaultAgentSetKey<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/app\/agentConfigs<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"kd\">function<\/span> <span class=\"nf\">RealTimeStreamingMode<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">searchParams<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useSearchParams<\/span><span class=\"p\">();<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">transcriptItems<\/span><span class=\"p\">,<\/span> <span class=\"nx\">addTranscriptMessage<\/span><span class=\"p\">,<\/span> <span class=\"nx\">addTranscriptBreadcrumb<\/span> <span class=\"p\">}<\/span> <span class=\"o\">=<\/span>\n    <span class=\"nf\">useTranscript<\/span><span class=\"p\">();<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">logClientEvent<\/span><span class=\"p\">,<\/span> <span class=\"nx\">logServerEvent<\/span> <span class=\"p\">}<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useEvent<\/span><span class=\"p\">();<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">selectedAgentName<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setSelectedAgentName<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">string<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"\"<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">selectedAgentConfigSet<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setSelectedAgentConfigSet<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span>\n    <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">AgentConfig<\/span><span class=\"p\">[]<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">dataChannel<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setDataChannel<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">RTCDataChannel<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">pcRef<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useRef<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">RTCPeerConnection<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">dcRef<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useRef<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">RTCDataChannel<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">audioElementRef<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useRef<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">HTMLAudioElement<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">sessionStatus<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setSessionStatus<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span>\n    <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">SessionStatus<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">DISCONNECTED<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">pathname<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">usePathname<\/span><span class=\"p\">();<\/span>\n\n  <span class=\"c1\">\/\/ Always keep logs hidden<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">isEventsPaneExpanded<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setIsEventsPaneExpanded<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">boolean<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">userText<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setUserText<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">string<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"\"<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">isPTTActive<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setIsPTTActive<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">boolean<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">true<\/span><span class=\"p\">);<\/span> <span class=\"c1\">\/\/ Default to PTT active<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">isPTTUserSpeaking<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setIsPTTUserSpeaking<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">boolean<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">isAudioPlaybackEnabled<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setIsAudioPlaybackEnabled<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">boolean<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">true<\/span><span class=\"p\">);<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">isVoiceModeActive<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setIsVoiceModeActive<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">boolean<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">isAssistantSpeaking<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setIsAssistantSpeaking<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">boolean<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">);<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">sendClientEvent<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"nx\">eventObj<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">,<\/span> <span class=\"nx\">eventNameSuffix<\/span> <span class=\"o\">=<\/span> <span class=\"dl\">\"\"<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">dcRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">dcRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span><span class=\"p\">.<\/span><span class=\"nx\">readyState<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">open<\/span><span class=\"dl\">\"<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nf\">logClientEvent<\/span><span class=\"p\">(<\/span><span class=\"nx\">eventObj<\/span><span class=\"p\">,<\/span> <span class=\"nx\">eventNameSuffix<\/span><span class=\"p\">);<\/span>\n      <span class=\"nx\">dcRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span><span class=\"p\">.<\/span><span class=\"nf\">send<\/span><span class=\"p\">(<\/span><span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">stringify<\/span><span class=\"p\">(<\/span><span class=\"nx\">eventObj<\/span><span class=\"p\">));<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">else<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nf\">logClientEvent<\/span><span class=\"p\">(<\/span>\n        <span class=\"p\">{<\/span> <span class=\"na\">attemptedEvent<\/span><span class=\"p\">:<\/span> <span class=\"nx\">eventObj<\/span><span class=\"p\">.<\/span><span class=\"kd\">type<\/span> <span class=\"p\">},<\/span>\n        <span class=\"dl\">\"<\/span><span class=\"s2\">error.data_channel_not_open<\/span><span class=\"dl\">\"<\/span>\n      <span class=\"p\">);<\/span>\n      <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span>\n        <span class=\"dl\">\"<\/span><span class=\"s2\">Failed to send message - no data channel available<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"nx\">eventObj<\/span>\n      <span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">handleServerEventRef<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useHandleServerEvent<\/span><span class=\"p\">({<\/span>\n    <span class=\"nx\">setSessionStatus<\/span><span class=\"p\">,<\/span>\n    <span class=\"nx\">selectedAgentName<\/span><span class=\"p\">,<\/span>\n    <span class=\"nx\">selectedAgentConfigSet<\/span><span class=\"p\">,<\/span>\n    <span class=\"nx\">sendClientEvent<\/span><span class=\"p\">,<\/span>\n    <span class=\"nx\">setSelectedAgentName<\/span><span class=\"p\">,<\/span>\n    <span class=\"nx\">setIsAssistantSpeaking<\/span><span class=\"p\">,<\/span>\n  <span class=\"p\">});<\/span>\n\n  <span class=\"nf\">useEffect<\/span><span class=\"p\">(()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">let<\/span> <span class=\"nx\">finalAgentConfig<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">searchParams<\/span><span class=\"p\">.<\/span><span class=\"nf\">get<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">agentConfig<\/span><span class=\"dl\">\"<\/span><span class=\"p\">)<\/span> <span class=\"o\">||<\/span> <span class=\"nx\">defaultAgentSetKey<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">allAgentSets<\/span><span class=\"p\">[<\/span><span class=\"nx\">finalAgentConfig<\/span><span class=\"p\">])<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">finalAgentConfig<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">defaultAgentSetKey<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"kd\">const<\/span> <span class=\"nx\">agents<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">allAgentSets<\/span><span class=\"p\">[<\/span><span class=\"nx\">finalAgentConfig<\/span><span class=\"p\">];<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">agentKeyToUse<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">agents<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]?.<\/span><span class=\"nx\">name<\/span> <span class=\"o\">||<\/span> <span class=\"dl\">\"\"<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"nf\">setSelectedAgentName<\/span><span class=\"p\">(<\/span><span class=\"nx\">agentKeyToUse<\/span><span class=\"p\">);<\/span>\n    <span class=\"nf\">setSelectedAgentConfigSet<\/span><span class=\"p\">(<\/span><span class=\"nx\">agents<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">},<\/span> <span class=\"p\">[<\/span><span class=\"nx\">searchParams<\/span><span class=\"p\">]);<\/span>\n\n  <span class=\"c1\">\/\/ Only connect when voice mode is activated, not on initial load<\/span>\n  <span class=\"nf\">useEffect<\/span><span class=\"p\">(()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">isVoiceModeActive<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">selectedAgentName<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">sessionStatus<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">DISCONNECTED<\/span><span class=\"dl\">\"<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nf\">connectToRealtime<\/span><span class=\"p\">();<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">else<\/span> <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">isVoiceModeActive<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">sessionStatus<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">CONNECTED<\/span><span class=\"dl\">\"<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nf\">disconnectFromRealtime<\/span><span class=\"p\">();<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">},<\/span> <span class=\"p\">[<\/span><span class=\"nx\">isVoiceModeActive<\/span><span class=\"p\">,<\/span> <span class=\"nx\">selectedAgentName<\/span><span class=\"p\">]);<\/span>\n\n  <span class=\"nf\">useEffect<\/span><span class=\"p\">(()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span>\n      <span class=\"nx\">sessionStatus<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">CONNECTED<\/span><span class=\"dl\">\"<\/span> <span class=\"o\">&amp;&amp;<\/span>\n      <span class=\"nx\">selectedAgentConfigSet<\/span> <span class=\"o\">&amp;&amp;<\/span>\n      <span class=\"nx\">selectedAgentName<\/span>\n    <span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">currentAgent<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">selectedAgentConfigSet<\/span><span class=\"p\">.<\/span><span class=\"nf\">find<\/span><span class=\"p\">(<\/span>\n        <span class=\"p\">(<\/span><span class=\"nx\">a<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">a<\/span><span class=\"p\">.<\/span><span class=\"nx\">name<\/span> <span class=\"o\">===<\/span> <span class=\"nx\">selectedAgentName<\/span>\n      <span class=\"p\">);<\/span>\n      <span class=\"nf\">addTranscriptBreadcrumb<\/span><span class=\"p\">(<\/span>\n        <span class=\"s2\">`Agent: <\/span><span class=\"p\">${<\/span><span class=\"nx\">selectedAgentName<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span><span class=\"p\">,<\/span>\n        <span class=\"nx\">currentAgent<\/span>\n      <span class=\"p\">);<\/span>\n      <span class=\"nf\">updateSession<\/span><span class=\"p\">(<\/span><span class=\"kc\">true<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">},<\/span> <span class=\"p\">[<\/span><span class=\"nx\">selectedAgentConfigSet<\/span><span class=\"p\">,<\/span> <span class=\"nx\">selectedAgentName<\/span><span class=\"p\">,<\/span> <span class=\"nx\">sessionStatus<\/span><span class=\"p\">]);<\/span>\n\n  <span class=\"nf\">useEffect<\/span><span class=\"p\">(()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">sessionStatus<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">CONNECTED<\/span><span class=\"dl\">\"<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">log<\/span><span class=\"p\">(<\/span>\n        <span class=\"s2\">`updatingSession, isPTTACtive=<\/span><span class=\"p\">${<\/span><span class=\"nx\">isPTTActive<\/span><span class=\"p\">}<\/span><span class=\"s2\"> sessionStatus=<\/span><span class=\"p\">${<\/span><span class=\"nx\">sessionStatus<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span>\n      <span class=\"p\">);<\/span>\n      <span class=\"nf\">updateSession<\/span><span class=\"p\">();<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">},<\/span> <span class=\"p\">[<\/span><span class=\"nx\">isPTTActive<\/span><span class=\"p\">]);<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">fetchEphemeralKey<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async <\/span><span class=\"p\">():<\/span> <span class=\"nb\">Promise<\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">string<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nf\">logClientEvent<\/span><span class=\"p\">({<\/span> <span class=\"na\">url<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">\/session<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">},<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">fetch_session_token_request<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">tokenResponse<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">fetch<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">\/api\/session<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">data<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">tokenResponse<\/span><span class=\"p\">.<\/span><span class=\"nf\">json<\/span><span class=\"p\">();<\/span>\n    <span class=\"nf\">logServerEvent<\/span><span class=\"p\">(<\/span><span class=\"nx\">data<\/span><span class=\"p\">,<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">fetch_session_token_response<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">data<\/span><span class=\"p\">.<\/span><span class=\"nx\">client_secret<\/span><span class=\"p\">?.<\/span><span class=\"nx\">value<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nf\">logClientEvent<\/span><span class=\"p\">(<\/span><span class=\"nx\">data<\/span><span class=\"p\">,<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">error.no_ephemeral_key<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n      <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">No ephemeral key provided by the server<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n      <span class=\"nf\">setSessionStatus<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">DISCONNECTED<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n      <span class=\"k\">return<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"nx\">data<\/span><span class=\"p\">.<\/span><span class=\"nx\">client_secret<\/span><span class=\"p\">.<\/span><span class=\"nx\">value<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">connectToRealtime<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async <\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">sessionStatus<\/span> <span class=\"o\">!==<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">DISCONNECTED<\/span><span class=\"dl\">\"<\/span><span class=\"p\">)<\/span> <span class=\"k\">return<\/span><span class=\"p\">;<\/span>\n    <span class=\"nf\">setSessionStatus<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">CONNECTING<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">EPHEMERAL_KEY<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">fetchEphemeralKey<\/span><span class=\"p\">();<\/span>\n      <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">EPHEMERAL_KEY<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">return<\/span><span class=\"p\">;<\/span>\n      <span class=\"p\">}<\/span>\n\n      <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">audioElementRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">audioElementRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">document<\/span><span class=\"p\">.<\/span><span class=\"nf\">createElement<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">audio<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n      <span class=\"p\">}<\/span>\n      <span class=\"nx\">audioElementRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span><span class=\"p\">.<\/span><span class=\"nx\">autoplay<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">isAudioPlaybackEnabled<\/span><span class=\"p\">;<\/span>\n\n      <span class=\"kd\">const<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">pc<\/span><span class=\"p\">,<\/span> <span class=\"nx\">dc<\/span> <span class=\"p\">}<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">createRealtimeConnection<\/span><span class=\"p\">(<\/span>\n        <span class=\"nx\">EPHEMERAL_KEY<\/span><span class=\"p\">,<\/span>\n        <span class=\"nx\">audioElementRef<\/span>\n      <span class=\"p\">);<\/span>\n      <span class=\"nx\">pcRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">pc<\/span><span class=\"p\">;<\/span>\n      <span class=\"nx\">dcRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">dc<\/span><span class=\"p\">;<\/span>\n\n      <span class=\"nx\">dc<\/span><span class=\"p\">.<\/span><span class=\"nf\">addEventListener<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">open<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nf\">logClientEvent<\/span><span class=\"p\">({},<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">data_channel.open<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n      <span class=\"p\">});<\/span>\n      <span class=\"nx\">dc<\/span><span class=\"p\">.<\/span><span class=\"nf\">addEventListener<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">close<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nf\">logClientEvent<\/span><span class=\"p\">({},<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">data_channel.close<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n      <span class=\"p\">});<\/span>\n      <span class=\"nx\">dc<\/span><span class=\"p\">.<\/span><span class=\"nf\">addEventListener<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">error<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"p\">(<\/span><span class=\"na\">err<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nf\">logClientEvent<\/span><span class=\"p\">({<\/span> <span class=\"na\">error<\/span><span class=\"p\">:<\/span> <span class=\"nx\">err<\/span> <span class=\"p\">},<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">data_channel.error<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n      <span class=\"p\">});<\/span>\n      <span class=\"nx\">dc<\/span><span class=\"p\">.<\/span><span class=\"nf\">addEventListener<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">message<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"p\">(<\/span><span class=\"na\">e<\/span><span class=\"p\">:<\/span> <span class=\"nx\">MessageEvent<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">handleServerEventRef<\/span><span class=\"p\">.<\/span><span class=\"nf\">current<\/span><span class=\"p\">(<\/span><span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">parse<\/span><span class=\"p\">(<\/span><span class=\"nx\">e<\/span><span class=\"p\">.<\/span><span class=\"nx\">data<\/span><span class=\"p\">));<\/span>\n      <span class=\"p\">});<\/span>\n\n      <span class=\"nf\">setDataChannel<\/span><span class=\"p\">(<\/span><span class=\"nx\">dc<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">err<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Error connecting to realtime:<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">err<\/span><span class=\"p\">);<\/span>\n      <span class=\"nf\">setSessionStatus<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">DISCONNECTED<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">disconnectFromRealtime<\/span> <span class=\"o\">=<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">pcRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">pcRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span><span class=\"p\">.<\/span><span class=\"nf\">getSenders<\/span><span class=\"p\">().<\/span><span class=\"nf\">forEach<\/span><span class=\"p\">((<\/span><span class=\"nx\">sender<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">sender<\/span><span class=\"p\">.<\/span><span class=\"nx\">track<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n          <span class=\"nx\">sender<\/span><span class=\"p\">.<\/span><span class=\"nx\">track<\/span><span class=\"p\">.<\/span><span class=\"nf\">stop<\/span><span class=\"p\">();<\/span>\n        <span class=\"p\">}<\/span>\n      <span class=\"p\">});<\/span>\n\n      <span class=\"nx\">pcRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span><span class=\"p\">.<\/span><span class=\"nf\">close<\/span><span class=\"p\">();<\/span>\n      <span class=\"nx\">pcRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n    <span class=\"nf\">setDataChannel<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n    <span class=\"nf\">setSessionStatus<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">DISCONNECTED<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n    <span class=\"nf\">setIsPTTUserSpeaking<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"nf\">logClientEvent<\/span><span class=\"p\">({},<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">disconnected<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">sendSimulatedUserMessage<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"nx\">text<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">id<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">uuidv4<\/span><span class=\"p\">().<\/span><span class=\"nf\">slice<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"mi\">32<\/span><span class=\"p\">);<\/span>\n    <span class=\"nf\">addTranscriptMessage<\/span><span class=\"p\">(<\/span><span class=\"nx\">id<\/span><span class=\"p\">,<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">user<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">text<\/span><span class=\"p\">,<\/span> <span class=\"kc\">true<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"nf\">sendClientEvent<\/span><span class=\"p\">(<\/span>\n      <span class=\"p\">{<\/span>\n        <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">conversation.item.create<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">item<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"nx\">id<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">message<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">role<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">user<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">content<\/span><span class=\"p\">:<\/span> <span class=\"p\">[{<\/span> <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">input_text<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">text<\/span> <span class=\"p\">}],<\/span>\n        <span class=\"p\">},<\/span>\n      <span class=\"p\">},<\/span>\n      <span class=\"dl\">\"<\/span><span class=\"s2\">(simulated user text message)<\/span><span class=\"dl\">\"<\/span>\n    <span class=\"p\">);<\/span>\n    <span class=\"nf\">sendClientEvent<\/span><span class=\"p\">(<\/span>\n      <span class=\"p\">{<\/span> <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">response.create<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">},<\/span>\n      <span class=\"dl\">\"<\/span><span class=\"s2\">(trigger response after simulated user text message)<\/span><span class=\"dl\">\"<\/span>\n    <span class=\"p\">);<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">updateSession<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"nx\">shouldTriggerResponse<\/span><span class=\"p\">:<\/span> <span class=\"nx\">boolean<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">false<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nf\">sendClientEvent<\/span><span class=\"p\">(<\/span>\n      <span class=\"p\">{<\/span> <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">input_audio_buffer.clear<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">},<\/span>\n      <span class=\"dl\">\"<\/span><span class=\"s2\">clear audio buffer on session update<\/span><span class=\"dl\">\"<\/span>\n    <span class=\"p\">);<\/span>\n\n    <span class=\"kd\">const<\/span> <span class=\"nx\">currentAgent<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">selectedAgentConfigSet<\/span><span class=\"p\">?.<\/span><span class=\"nf\">find<\/span><span class=\"p\">(<\/span>\n      <span class=\"p\">(<\/span><span class=\"nx\">a<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">a<\/span><span class=\"p\">.<\/span><span class=\"nx\">name<\/span> <span class=\"o\">===<\/span> <span class=\"nx\">selectedAgentName<\/span>\n    <span class=\"p\">);<\/span>\n\n    <span class=\"kd\">const<\/span> <span class=\"nx\">turnDetection<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">isPTTActive<\/span>\n      <span class=\"p\">?<\/span> <span class=\"kc\">null<\/span>\n      <span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">server_vad<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">threshold<\/span><span class=\"p\">:<\/span> <span class=\"mf\">0.5<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">prefix_padding_ms<\/span><span class=\"p\">:<\/span> <span class=\"mi\">300<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">silence_duration_ms<\/span><span class=\"p\">:<\/span> <span class=\"mi\">200<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">create_response<\/span><span class=\"p\">:<\/span> <span class=\"kc\">true<\/span><span class=\"p\">,<\/span>\n        <span class=\"p\">};<\/span>\n\n    <span class=\"kd\">const<\/span> <span class=\"nx\">instructions<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">currentAgent<\/span><span class=\"p\">?.<\/span><span class=\"nx\">instructions<\/span> <span class=\"o\">||<\/span> <span class=\"dl\">\"\"<\/span><span class=\"p\">;<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">tools<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">currentAgent<\/span><span class=\"p\">?.<\/span><span class=\"nx\">tools<\/span> <span class=\"o\">||<\/span> <span class=\"p\">[];<\/span>\n\n    <span class=\"kd\">const<\/span> <span class=\"nx\">sessionUpdateEvent<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">session.update<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">session<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">modalities<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">text<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">audio<\/span><span class=\"dl\">\"<\/span><span class=\"p\">],<\/span>\n        <span class=\"nx\">instructions<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">voice<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">coral<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">input_audio_format<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">pcm16<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">output_audio_format<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">pcm16<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">input_audio_transcription<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span> <span class=\"na\">model<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">whisper-1<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">},<\/span>\n        <span class=\"na\">turn_detection<\/span><span class=\"p\">:<\/span> <span class=\"nx\">turnDetection<\/span><span class=\"p\">,<\/span>\n        <span class=\"nx\">tools<\/span><span class=\"p\">,<\/span>\n      <span class=\"p\">},<\/span>\n    <span class=\"p\">};<\/span>\n\n    <span class=\"nf\">sendClientEvent<\/span><span class=\"p\">(<\/span><span class=\"nx\">sessionUpdateEvent<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">shouldTriggerResponse<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nf\">sendSimulatedUserMessage<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">hi<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">cancelAssistantSpeech<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async <\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">mostRecentAssistantMessage<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[...<\/span><span class=\"nx\">transcriptItems<\/span><span class=\"p\">]<\/span>\n      <span class=\"p\">.<\/span><span class=\"nf\">reverse<\/span><span class=\"p\">()<\/span>\n      <span class=\"p\">.<\/span><span class=\"nf\">find<\/span><span class=\"p\">((<\/span><span class=\"nx\">item<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">item<\/span><span class=\"p\">.<\/span><span class=\"nx\">role<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">assistant<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">mostRecentAssistantMessage<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">warn<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">can't cancel, no recent assistant message found<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n      <span class=\"k\">return<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">mostRecentAssistantMessage<\/span><span class=\"p\">.<\/span><span class=\"nx\">status<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">DONE<\/span><span class=\"dl\">\"<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">log<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">No truncation needed, message is DONE<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n      <span class=\"k\">return<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"nf\">sendClientEvent<\/span><span class=\"p\">({<\/span>\n      <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">conversation.item.truncate<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">item_id<\/span><span class=\"p\">:<\/span> <span class=\"nx\">mostRecentAssistantMessage<\/span><span class=\"p\">?.<\/span><span class=\"nx\">itemId<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">content_index<\/span><span class=\"p\">:<\/span> <span class=\"mi\">0<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">audio_end_ms<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Date<\/span><span class=\"p\">.<\/span><span class=\"nf\">now<\/span><span class=\"p\">()<\/span> <span class=\"o\">-<\/span> <span class=\"nx\">mostRecentAssistantMessage<\/span><span class=\"p\">.<\/span><span class=\"nx\">createdAtMs<\/span><span class=\"p\">,<\/span>\n    <span class=\"p\">});<\/span>\n    <span class=\"nf\">sendClientEvent<\/span><span class=\"p\">(<\/span>\n      <span class=\"p\">{<\/span> <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">response.cancel<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">},<\/span>\n      <span class=\"dl\">\"<\/span><span class=\"s2\">(cancel due to user interruption)<\/span><span class=\"dl\">\"<\/span>\n    <span class=\"p\">);<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">handleTalkButtonDown<\/span> <span class=\"o\">=<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">sessionStatus<\/span> <span class=\"o\">!==<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">CONNECTED<\/span><span class=\"dl\">\"<\/span> <span class=\"o\">||<\/span> <span class=\"nx\">dataChannel<\/span><span class=\"p\">?.<\/span><span class=\"nx\">readyState<\/span> <span class=\"o\">!==<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">open<\/span><span class=\"dl\">\"<\/span><span class=\"p\">)<\/span>\n      <span class=\"k\">return<\/span><span class=\"p\">;<\/span>\n    <span class=\"nf\">cancelAssistantSpeech<\/span><span class=\"p\">();<\/span>\n\n    <span class=\"nf\">setIsPTTUserSpeaking<\/span><span class=\"p\">(<\/span><span class=\"kc\">true<\/span><span class=\"p\">);<\/span>\n    <span class=\"nf\">sendClientEvent<\/span><span class=\"p\">({<\/span> <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">input_audio_buffer.clear<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">},<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">clear PTT buffer<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">handleTalkButtonUp<\/span> <span class=\"o\">=<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span>\n      <span class=\"nx\">sessionStatus<\/span> <span class=\"o\">!==<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">CONNECTED<\/span><span class=\"dl\">\"<\/span> <span class=\"o\">||<\/span>\n      <span class=\"nx\">dataChannel<\/span><span class=\"p\">?.<\/span><span class=\"nx\">readyState<\/span> <span class=\"o\">!==<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">open<\/span><span class=\"dl\">\"<\/span> <span class=\"o\">||<\/span>\n      <span class=\"o\">!<\/span><span class=\"nx\">isPTTUserSpeaking<\/span>\n    <span class=\"p\">)<\/span>\n      <span class=\"k\">return<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"nf\">setIsPTTUserSpeaking<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">);<\/span>\n    <span class=\"nf\">sendClientEvent<\/span><span class=\"p\">({<\/span> <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">input_audio_buffer.commit<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">},<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">commit PTT<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n    <span class=\"nf\">sendClientEvent<\/span><span class=\"p\">({<\/span> <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">response.create<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">},<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">trigger response PTT<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">handleVoiceModeToggle<\/span> <span class=\"o\">=<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">isVoiceModeActive<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"c1\">\/\/ Activate voice mode<\/span>\n      <span class=\"nf\">setIsVoiceModeActive<\/span><span class=\"p\">(<\/span><span class=\"kc\">true<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">else<\/span> <span class=\"p\">{<\/span>\n      <span class=\"c1\">\/\/ Deactivate voice mode<\/span>\n      <span class=\"nf\">setIsVoiceModeActive<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">);<\/span>\n      <span class=\"nf\">setIsPTTUserSpeaking<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"c1\">\/\/ Load saved preferences<\/span>\n  <span class=\"nf\">useEffect<\/span><span class=\"p\">(()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"c1\">\/\/ Default to audio playback enabled<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">storedAudioPlaybackEnabled<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">localStorage<\/span><span class=\"p\">.<\/span><span class=\"nf\">getItem<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">audioPlaybackEnabled<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">storedAudioPlaybackEnabled<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nf\">setIsAudioPlaybackEnabled<\/span><span class=\"p\">(<\/span><span class=\"nx\">storedAudioPlaybackEnabled<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">true<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">},<\/span> <span class=\"p\">[]);<\/span>\n\n  <span class=\"c1\">\/\/ Save preferences when they change<\/span>\n  <span class=\"nf\">useEffect<\/span><span class=\"p\">(()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">localStorage<\/span><span class=\"p\">.<\/span><span class=\"nf\">setItem<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">pushToTalkUI<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">true<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span> <span class=\"c1\">\/\/ Always use PTT<\/span>\n    <span class=\"nx\">localStorage<\/span><span class=\"p\">.<\/span><span class=\"nf\">setItem<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">logsExpanded<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">false<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span> <span class=\"c1\">\/\/ Always keep logs hidden<\/span>\n    <span class=\"nx\">localStorage<\/span><span class=\"p\">.<\/span><span class=\"nf\">setItem<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">audioPlaybackEnabled<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">isAudioPlaybackEnabled<\/span><span class=\"p\">.<\/span><span class=\"nf\">toString<\/span><span class=\"p\">());<\/span>\n  <span class=\"p\">},<\/span> <span class=\"p\">[<\/span><span class=\"nx\">isAudioPlaybackEnabled<\/span><span class=\"p\">]);<\/span>\n\n  <span class=\"c1\">\/\/ Handle audio playback changes<\/span>\n  <span class=\"nf\">useEffect<\/span><span class=\"p\">(()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">audioElementRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">isAudioPlaybackEnabled<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">audioElementRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span><span class=\"p\">.<\/span><span class=\"nf\">play<\/span><span class=\"p\">().<\/span><span class=\"k\">catch<\/span><span class=\"p\">((<\/span><span class=\"nx\">err<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n          <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">warn<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Autoplay may be blocked by browser:<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">err<\/span><span class=\"p\">);<\/span>\n        <span class=\"p\">});<\/span>\n      <span class=\"p\">}<\/span> <span class=\"k\">else<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">audioElementRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span><span class=\"p\">.<\/span><span class=\"nf\">pause<\/span><span class=\"p\">();<\/span>\n      <span class=\"p\">}<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">},<\/span> <span class=\"p\">[<\/span><span class=\"nx\">isAudioPlaybackEnabled<\/span><span class=\"p\">]);<\/span>\n\n  <span class=\"k\">return <\/span><span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;&gt;<\/span>\n      <span class=\"si\">{<\/span><span class=\"cm\">\/* Only render the voice button, nothing else in normal view *\/<\/span><span class=\"si\">}<\/span>\n\n      <span class=\"si\">{<\/span><span class=\"o\">!<\/span><span class=\"nx\">isVoiceModeActive<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">pathname<\/span> <span class=\"o\">!==<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">\/chat<\/span><span class=\"dl\">\"<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"p\">&lt;<\/span><span class=\"nc\">VoiceButton<\/span> \n        <span class=\"na\">onClose<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">handleVoiceModeToggle<\/span><span class=\"si\">}<\/span>\n        <span class=\"na\">isListening<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"kc\">false<\/span><span class=\"si\">}<\/span>\n        <span class=\"na\">isConnected<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"kc\">false<\/span><span class=\"si\">}<\/span>\n        <span class=\"na\">onStart<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{}<\/span><span class=\"si\">}<\/span>\n        <span class=\"na\">onStop<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{}<\/span><span class=\"si\">}<\/span>\n      <span class=\"p\">\/&gt;<\/span><span class=\"si\">}<\/span>\n\n      <span class=\"si\">{<\/span><span class=\"cm\">\/* Voice overlay appears only when activated *\/<\/span><span class=\"si\">}<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nc\">VoiceTranscriptOverlay<\/span> \n        <span class=\"na\">isVisible<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">isVoiceModeActive<\/span><span class=\"si\">}<\/span>\n        <span class=\"na\">transcriptItems<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">transcriptItems<\/span><span class=\"si\">}<\/span>\n        <span class=\"na\">isAssistantSpeaking<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">isAssistantSpeaking<\/span><span class=\"si\">}<\/span>\n        <span class=\"na\">isPTTUserSpeaking<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">isPTTUserSpeaking<\/span><span class=\"si\">}<\/span>\n        <span class=\"na\">handleTalkButtonDown<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">handleTalkButtonDown<\/span><span class=\"si\">}<\/span>\n        <span class=\"na\">handleTalkButtonUp<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">handleTalkButtonUp<\/span><span class=\"si\">}<\/span>\n        <span class=\"na\">connectionStatus<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">sessionStatus<\/span><span class=\"si\">}<\/span>\n        <span class=\"na\">onClose<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">handleVoiceModeToggle<\/span><span class=\"si\">}<\/span>\n      <span class=\"p\">\/&gt;<\/span>\n    <span class=\"p\">&gt;<\/span>\n  <span class=\"p\">);<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"nx\">RealTimeStreamingMode<\/span><span class=\"p\">;<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u062f\u0631 \u0627\u06cc\u0646\u062c\u0627 \u06cc\u06a9 \u0646\u0645\u0627\u06cc\u0634 \u0633\u0627\u062f\u0647 \u0627\u0632 \u0627\u0644\u06af\u0648\u0647\u0627\u06cc \u067e\u06cc\u0634\u0631\u0641\u062a\u0647 \u062a\u0631 \u0648 \u0639\u0627\u0645\u0644 \u0633\u0627\u062e\u062a\u0647 \u0634\u062f\u0647 \u062f\u0631 \u0628\u0627\u0644\u0627\u06cc API Realtime \u062a\u0648\u0633\u0637 <code>OpenAI<\/code>\u0628\u0634\u0631<br \/>\u0646\u0645\u0627\u06cc\u0646\u062f\u06af\u0627\u0646 Openai-Realtime<\/p>\n<h2><span class=\"ez-toc-section\" id=\"%D8%A7%D8%AF%D8%BA%D8%A7%D9%85_%D8%A8%D8%A7_AIML_API_%D9%88_Openai_Realtime_API\"><\/span>\n<p>  \u0627\u062f\u063a\u0627\u0645 \u0628\u0627 AI\/ML API \u0648 Openai Realtime API<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<h3><span class=\"ez-toc-section\" id=\"%D9%BE%DB%8C%DA%A9%D8%B1%D8%A8%D9%86%D8%AF%DB%8C_%D8%B9%D9%88%D8%A7%D9%85%D9%84_%D9%87%D9%88%D8%B4_%D9%85%D8%B5%D9%86%D9%88%D8%B9%DB%8C\"><\/span>\n<p>  \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc \u0639\u0648\u0627\u0645\u0644 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0639\u0648\u0627\u0645\u0644 \u067e\u0648\u06cc\u0627 \u0631\u0627 \u0628\u0627 \u0632\u0645\u06cc\u0646\u0647 \u06a9\u0627\u0631\u0628\u0631 \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u06a9\u0646\u06cc\u062f.<\/p>\n<p>\u06cc\u06a9 \u0641\u0627\u06cc\u0644 \u062c\u062f\u06cc\u062f \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f <code>app\/utils\/agentLoader.ts<\/code>\u0628\u0634\u0631<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight typescript\"><code><span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">UserCache<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">@\/app\/contexts\/UserCacheContext<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">injectUserContext<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">@\/app\/agentConfigs\/utils<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">AgentConfig<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">@\/app\/types<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n\n<span class=\"cm\">\/**\n * Load and enhance an agent with user context\n * @param agentName Name of the agent to load from the wellbeing directory\n * @param userCache The user cache context data\n * @returns Enhanced agent config with user context\n *\/<\/span>\n<span class=\"k\">export<\/span> <span class=\"k\">async<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">loadAgentWithUserContext<\/span><span class=\"p\">(<\/span>\n  <span class=\"nx\">agentName<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">userCache<\/span><span class=\"p\">:<\/span> <span class=\"nx\">UserCache<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span>\n<span class=\"p\">):<\/span> <span class=\"nb\">Promise<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">AgentConfig<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n    <span class=\"c1\">\/\/ Dynamically import the agent config<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">agentModule<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"k\">import<\/span><span class=\"p\">(<\/span><span class=\"s2\">`@\/app\/agentConfigs\/wellbeing\/<\/span><span class=\"p\">${<\/span><span class=\"nx\">agentName<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">agentModule<\/span><span class=\"p\">.<\/span><span class=\"k\">default<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"s2\">`Agent module <\/span><span class=\"p\">${<\/span><span class=\"nx\">agentName<\/span><span class=\"p\">}<\/span><span class=\"s2\"> has no default export`<\/span><span class=\"p\">);<\/span>\n      <span class=\"k\">return<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c1\">\/\/ If we have user cache data, enhance the agent with it<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">userCache<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">return<\/span> <span class=\"nf\">injectUserContext<\/span><span class=\"p\">(<\/span><span class=\"nx\">agentModule<\/span><span class=\"p\">.<\/span><span class=\"k\">default<\/span><span class=\"p\">,<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c1\">\/\/ Otherwise return the unmodified agent<\/span>\n    <span class=\"k\">return<\/span> <span class=\"nx\">agentModule<\/span><span class=\"p\">.<\/span><span class=\"k\">default<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"s2\">`Failed to load agent: <\/span><span class=\"p\">${<\/span><span class=\"nx\">agentName<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">return<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"cm\">\/**\n * Load multiple agents with user context\n * @param userCache The user cache context data\n * @returns Object containing all enhanced agents with user context\n *\/<\/span>\n<span class=\"k\">export<\/span> <span class=\"k\">async<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">loadAllAgentsWithUserContext<\/span><span class=\"p\">(<\/span>\n  <span class=\"nx\">userCache<\/span><span class=\"p\">:<\/span> <span class=\"nx\">UserCache<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span>\n<span class=\"p\">):<\/span> <span class=\"nb\">Promise<\/span><span class=\"o\">&lt;<\/span><span class=\"nb\">Record<\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">string<\/span><span class=\"p\">,<\/span> <span class=\"nx\">AgentConfig<\/span><span class=\"o\">&gt;&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n    <span class=\"c1\">\/\/ Import the agents index<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"p\">{<\/span> <span class=\"na\">default<\/span><span class=\"p\">:<\/span> <span class=\"nx\">agents<\/span> <span class=\"p\">}<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"k\">import<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">@\/app\/agentConfigs\/wellbeing\/index<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"c1\">\/\/ Create a result object<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"na\">enhancedAgents<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Record<\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">string<\/span><span class=\"p\">,<\/span> <span class=\"nx\">AgentConfig<\/span><span class=\"o\">&gt;<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{};<\/span>\n\n    <span class=\"c1\">\/\/ Enhance each agent with user context<\/span>\n    <span class=\"k\">for <\/span><span class=\"p\">(<\/span><span class=\"kd\">const<\/span> <span class=\"nx\">agent<\/span> <span class=\"k\">of<\/span> <span class=\"nx\">agents<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">userCache<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">enhancedAgents<\/span><span class=\"p\">[<\/span><span class=\"nx\">agent<\/span><span class=\"p\">.<\/span><span class=\"nx\">name<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">injectUserContext<\/span><span class=\"p\">(<\/span><span class=\"nx\">agent<\/span><span class=\"p\">,<\/span> <span class=\"nx\">userCache<\/span><span class=\"p\">);<\/span>\n      <span class=\"p\">}<\/span> <span class=\"k\">else<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">enhancedAgents<\/span><span class=\"p\">[<\/span><span class=\"nx\">agent<\/span><span class=\"p\">.<\/span><span class=\"nx\">name<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">agent<\/span><span class=\"p\">;<\/span>\n      <span class=\"p\">}<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"nx\">enhancedAgents<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Failed to load all agents<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">return<\/span> <span class=\"p\">{};<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span> \n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"%D8%A7%D8%A8%D8%B2%D8%A7%D8%B1%D9%87%D8%A7%DB%8C_%D9%BE%D8%A7%DB%8C%DA%AF%D8%A7%D9%87_%D8%AF%D8%A7%D8%AF%D9%87_%D8%B9%D8%A7%D9%85%D9%84\"><\/span>\n<p>  \u0627\u0628\u0632\u0627\u0631\u0647\u0627\u06cc \u067e\u0627\u06cc\u06af\u0627\u0647 \u062f\u0627\u062f\u0647 \u0639\u0627\u0645\u0644<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u062a\u0648\u0627\u0628\u0639 \u0627\u0628\u0632\u0627\u0631 \u0631\u0627 \u0628\u0631\u0627\u06cc \u062f\u0633\u062a\u0631\u0633\u06cc \u0628\u0647 \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u067e\u0627\u06cc\u06af\u0627\u0647 \u062f\u0627\u062f\u0647 \u0628\u0631\u0627\u06cc \u0639\u0648\u0627\u0645\u0644 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u0641\u0631\u0627\u0647\u0645 \u0645\u06cc \u06a9\u0646\u062f.<\/p>\n<p>\u06cc\u06a9 \u0641\u0627\u06cc\u0644 \u062c\u062f\u06cc\u062f \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f <code>app\/utils\/agentDatabaseTools.ts<\/code>\u0628\u0634\u0631<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight typescript\"><code><span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">IDBPDatabase<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">idb<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">WeiDB<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/types\/database<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">initDB<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">@\/lib\/db<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n\n<span class=\"cm\">\/**\n * Provides utility functions to access database information for AI agents\n *\/<\/span>\n\n<span class=\"c1\">\/\/ Database cache to avoid reopening connections<\/span>\n<span class=\"kd\">let<\/span> <span class=\"nx\">dbInstance<\/span><span class=\"p\">:<\/span> <span class=\"nx\">IDBPDatabase<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">WeiDB<\/span><span class=\"o\">&gt;<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n\n<span class=\"c1\">\/\/ Get the database (reuse the existing connection if possible)<\/span>\n<span class=\"k\">async<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">getDatabase<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">dbInstance<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">dbInstance<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">initDB<\/span><span class=\"p\">();<\/span>\n    <span class=\"p\">}<\/span>\n    <span class=\"k\">return<\/span> <span class=\"nx\">dbInstance<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Failed to open database for agent:<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">throw<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Database access failed<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"cm\">\/**\n * Get user profile information\n * @param fields Optional array of field names to retrieve\n * @returns User profile data object\n *\/<\/span>\n<span class=\"k\">export<\/span> <span class=\"k\">async<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">getUserProfile<\/span><span class=\"p\">(<\/span><span class=\"nx\">fields<\/span><span class=\"p\">?:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">[])<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">db<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">getDatabase<\/span><span class=\"p\">();<\/span>\n  <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">profile<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">get<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">userProfile<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">default<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">profile<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">return<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">fields<\/span> <span class=\"o\">||<\/span> <span class=\"nx\">fields<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">===<\/span> <span class=\"mi\">0<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">return<\/span> <span class=\"nx\">profile<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c1\">\/\/ Return only requested fields<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">filteredProfile<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{}<\/span> <span class=\"k\">as<\/span> <span class=\"nb\">Record<\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">string<\/span><span class=\"p\">,<\/span> <span class=\"kr\">any<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">;<\/span>\n    <span class=\"nx\">fields<\/span><span class=\"p\">.<\/span><span class=\"nf\">forEach<\/span><span class=\"p\">(<\/span><span class=\"nx\">field<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">field<\/span> <span class=\"k\">in<\/span> <span class=\"nx\">profile<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">filteredProfile<\/span><span class=\"p\">[<\/span><span class=\"nx\">field<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">profile<\/span><span class=\"p\">[<\/span><span class=\"nx\">field<\/span> <span class=\"k\">as<\/span> <span class=\"kr\">keyof<\/span> <span class=\"k\">typeof<\/span> <span class=\"nx\">profile<\/span><span class=\"p\">];<\/span>\n      <span class=\"p\">}<\/span>\n    <span class=\"p\">});<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"nx\">filteredProfile<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Failed to get user profile:<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">return<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"cm\">\/**\n * Get user's habits\n *\/<\/span>\n<span class=\"k\">export<\/span> <span class=\"k\">async<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">getUserHabits<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">db<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">getDatabase<\/span><span class=\"p\">();<\/span>\n  <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">habits<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">getAll<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">habits<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">return<\/span> <span class=\"nx\">habits<\/span> <span class=\"o\">||<\/span> <span class=\"p\">[];<\/span>\n  <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Failed to get user habits:<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">return<\/span> <span class=\"p\">[];<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"cm\">\/**\n * Get user's habit completions\n *\/<\/span>\n<span class=\"k\">export<\/span> <span class=\"k\">async<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">getHabitCompletions<\/span><span class=\"p\">(<\/span><span class=\"nx\">daysAgo<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">30<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">db<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">getDatabase<\/span><span class=\"p\">();<\/span>\n  <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">allCompletions<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">getAll<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">completions<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"c1\">\/\/ Filter completions by date<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">startDate<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">();<\/span>\n    <span class=\"nx\">startDate<\/span><span class=\"p\">.<\/span><span class=\"nf\">setDate<\/span><span class=\"p\">(<\/span><span class=\"nx\">startDate<\/span><span class=\"p\">.<\/span><span class=\"nf\">getDate<\/span><span class=\"p\">()<\/span> <span class=\"o\">-<\/span> <span class=\"nx\">daysAgo<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"nx\">allCompletions<\/span><span class=\"p\">.<\/span><span class=\"nf\">filter<\/span><span class=\"p\">(<\/span><span class=\"nx\">completion<\/span> <span class=\"o\">=&gt;<\/span> \n      <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(<\/span><span class=\"nx\">completion<\/span><span class=\"p\">.<\/span><span class=\"nx\">completedAt<\/span><span class=\"p\">)<\/span> <span class=\"o\">&gt;=<\/span> <span class=\"nx\">startDate<\/span>\n    <span class=\"p\">);<\/span>\n  <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Failed to get habit completions:<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">return<\/span> <span class=\"p\">[];<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"cm\">\/**\n * Get user's rewards\n *\/<\/span>\n<span class=\"k\">export<\/span> <span class=\"k\">async<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">getUserRewards<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">db<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">getDatabase<\/span><span class=\"p\">();<\/span>\n  <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">rewards<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">getAll<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">rewards<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">return<\/span> <span class=\"nx\">rewards<\/span> <span class=\"o\">||<\/span> <span class=\"p\">[];<\/span>\n  <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Failed to get user rewards:<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">return<\/span> <span class=\"p\">[];<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"cm\">\/**\n * Get user's reward redemptions\n *\/<\/span>\n<span class=\"k\">export<\/span> <span class=\"k\">async<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">getRewardRedemptions<\/span><span class=\"p\">(<\/span><span class=\"nx\">daysAgo<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">30<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">db<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">getDatabase<\/span><span class=\"p\">();<\/span>\n  <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">allRedemptions<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">getAll<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">rewardRedemptions<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"c1\">\/\/ Filter redemptions by date<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">startDate<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">();<\/span>\n    <span class=\"nx\">startDate<\/span><span class=\"p\">.<\/span><span class=\"nf\">setDate<\/span><span class=\"p\">(<\/span><span class=\"nx\">startDate<\/span><span class=\"p\">.<\/span><span class=\"nf\">getDate<\/span><span class=\"p\">()<\/span> <span class=\"o\">-<\/span> <span class=\"nx\">daysAgo<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"nx\">allRedemptions<\/span><span class=\"p\">.<\/span><span class=\"nf\">filter<\/span><span class=\"p\">(<\/span><span class=\"nx\">redemption<\/span> <span class=\"o\">=&gt;<\/span> \n      <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(<\/span><span class=\"nx\">redemption<\/span><span class=\"p\">.<\/span><span class=\"nx\">redeemedAt<\/span><span class=\"p\">)<\/span> <span class=\"o\">&gt;=<\/span> <span class=\"nx\">startDate<\/span>\n    <span class=\"p\">);<\/span>\n  <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Failed to get reward redemptions:<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">return<\/span> <span class=\"p\">[];<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"cm\">\/**\n * Get user's points and streak information\n *\/<\/span>\n<span class=\"k\">export<\/span> <span class=\"k\">async<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">getUserStats<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">db<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">getDatabase<\/span><span class=\"p\">();<\/span>\n  <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">userData<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">get<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">user<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">default<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">return<\/span> <span class=\"nx\">userData<\/span> <span class=\"o\">||<\/span> <span class=\"p\">{<\/span> <span class=\"na\">points<\/span><span class=\"p\">:<\/span> <span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"na\">streakDays<\/span><span class=\"p\">:<\/span> <span class=\"mi\">0<\/span> <span class=\"p\">};<\/span>\n  <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Failed to get user stats:<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> <span class=\"na\">points<\/span><span class=\"p\">:<\/span> <span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"na\">streakDays<\/span><span class=\"p\">:<\/span> <span class=\"mi\">0<\/span> <span class=\"p\">};<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"cm\">\/**\n * Complete a habit and update user points\n *\/<\/span>\n<span class=\"k\">export<\/span> <span class=\"k\">async<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">completeHabit<\/span><span class=\"p\">(<\/span><span class=\"nx\">habitId<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">db<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">getDatabase<\/span><span class=\"p\">();<\/span>\n  <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">habit<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">get<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">habits<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">habitId<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">habit<\/span><span class=\"p\">)<\/span> <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> <span class=\"na\">success<\/span><span class=\"p\">:<\/span> <span class=\"kc\">false<\/span><span class=\"p\">,<\/span> <span class=\"na\">message<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">Habit not found<\/span><span class=\"dl\">'<\/span> <span class=\"p\">};<\/span>\n\n    <span class=\"c1\">\/\/ Create completion record<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">completionId<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">`completion_<\/span><span class=\"p\">${<\/span><span class=\"nb\">Date<\/span><span class=\"p\">.<\/span><span class=\"nf\">now<\/span><span class=\"p\">()}<\/span><span class=\"s2\">_<\/span><span class=\"p\">${<\/span><span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">random<\/span><span class=\"p\">().<\/span><span class=\"nf\">toString<\/span><span class=\"p\">(<\/span><span class=\"mi\">36<\/span><span class=\"p\">).<\/span><span class=\"nf\">substr<\/span><span class=\"p\">(<\/span><span class=\"mi\">2<\/span><span class=\"p\">,<\/span> <span class=\"mi\">9<\/span><span class=\"p\">)}<\/span><span class=\"s2\">`<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">add<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">completions<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">id<\/span><span class=\"p\">:<\/span> <span class=\"nx\">completionId<\/span><span class=\"p\">,<\/span>\n      <span class=\"nx\">habitId<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">completedAt<\/span><span class=\"p\">:<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(),<\/span>\n      <span class=\"na\">points<\/span><span class=\"p\">:<\/span> <span class=\"nx\">habit<\/span><span class=\"p\">.<\/span><span class=\"nx\">points<\/span>\n    <span class=\"p\">});<\/span>\n\n    <span class=\"c1\">\/\/ Update user points<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">userData<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">get<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">user<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">default<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">userData<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">put<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">user<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span>\n        <span class=\"p\">...<\/span><span class=\"nx\">userData<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">points<\/span><span class=\"p\">:<\/span> <span class=\"nx\">userData<\/span><span class=\"p\">.<\/span><span class=\"nx\">points<\/span> <span class=\"o\">+<\/span> <span class=\"nx\">habit<\/span><span class=\"p\">.<\/span><span class=\"nx\">points<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">lastActive<\/span><span class=\"p\">:<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">()<\/span>\n      <span class=\"p\">});<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> \n      <span class=\"na\">success<\/span><span class=\"p\">:<\/span> <span class=\"kc\">true<\/span><span class=\"p\">,<\/span> \n      <span class=\"na\">message<\/span><span class=\"p\">:<\/span> <span class=\"s2\">`Habit completed. Earned <\/span><span class=\"p\">${<\/span><span class=\"nx\">habit<\/span><span class=\"p\">.<\/span><span class=\"nx\">points<\/span><span class=\"p\">}<\/span><span class=\"s2\"> points!`<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">newPoints<\/span><span class=\"p\">:<\/span> <span class=\"p\">(<\/span><span class=\"nx\">userData<\/span><span class=\"p\">?.<\/span><span class=\"nx\">points<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">0<\/span><span class=\"p\">)<\/span> <span class=\"o\">+<\/span> <span class=\"nx\">habit<\/span><span class=\"p\">.<\/span><span class=\"nx\">points<\/span>\n    <span class=\"p\">};<\/span>\n  <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Failed to complete habit:<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> <span class=\"na\">success<\/span><span class=\"p\">:<\/span> <span class=\"kc\">false<\/span><span class=\"p\">,<\/span> <span class=\"na\">message<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">Failed to complete habit<\/span><span class=\"dl\">'<\/span> <span class=\"p\">};<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"cm\">\/**\n * Get all user data combined for agent context\n *\/<\/span>\n<span class=\"k\">export<\/span> <span class=\"k\">async<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">getUserDataForAgent<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">db<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">getDatabase<\/span><span class=\"p\">();<\/span>\n\n    <span class=\"c1\">\/\/ Fetch user profile data<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">user<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">get<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">userProfile<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">default<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">user<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> <span class=\"na\">error<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">User profile not found<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">};<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c1\">\/\/ Fetch user's habits<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">habits<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">getAll<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">habits<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"c1\">\/\/ Fetch habit completions (last 30 days)<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">thirtyDaysAgo<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">();<\/span>\n    <span class=\"nx\">thirtyDaysAgo<\/span><span class=\"p\">.<\/span><span class=\"nf\">setDate<\/span><span class=\"p\">(<\/span><span class=\"nx\">thirtyDaysAgo<\/span><span class=\"p\">.<\/span><span class=\"nf\">getDate<\/span><span class=\"p\">()<\/span> <span class=\"o\">-<\/span> <span class=\"mi\">30<\/span><span class=\"p\">);<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">allCompletions<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">getAll<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">completions<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">completions<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">allCompletions<\/span><span class=\"p\">.<\/span><span class=\"nf\">filter<\/span><span class=\"p\">(<\/span><span class=\"nx\">completion<\/span> <span class=\"o\">=&gt;<\/span> \n      <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(<\/span><span class=\"nx\">completion<\/span><span class=\"p\">.<\/span><span class=\"nx\">completedAt<\/span><span class=\"p\">)<\/span> <span class=\"o\">&gt;=<\/span> <span class=\"nx\">thirtyDaysAgo<\/span>\n    <span class=\"p\">);<\/span>\n\n    <span class=\"c1\">\/\/ Fetch rewards<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">rewards<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">getAll<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">rewards<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"c1\">\/\/ Fetch redemptions<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">allRedemptions<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">getAll<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">rewardRedemptions<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">redemptions<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">allRedemptions<\/span><span class=\"p\">.<\/span><span class=\"nf\">filter<\/span><span class=\"p\">(<\/span><span class=\"nx\">redemption<\/span> <span class=\"o\">=&gt;<\/span> \n      <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(<\/span><span class=\"nx\">redemption<\/span><span class=\"p\">.<\/span><span class=\"nx\">redeemedAt<\/span><span class=\"p\">)<\/span> <span class=\"o\">&gt;=<\/span> <span class=\"nx\">thirtyDaysAgo<\/span>\n    <span class=\"p\">);<\/span>\n\n    <span class=\"c1\">\/\/ Get user data for points<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">userData<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">db<\/span><span class=\"p\">.<\/span><span class=\"nf\">get<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">user<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">default<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"c1\">\/\/ Calculate streak<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">streak<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">calculateStreak<\/span><span class=\"p\">(<\/span><span class=\"nx\">completions<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"c1\">\/\/ Format recent activities<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">recentActivity<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">formatRecentActivity<\/span><span class=\"p\">(<\/span><span class=\"nx\">habits<\/span><span class=\"p\">,<\/span> <span class=\"nx\">completions<\/span><span class=\"p\">,<\/span> <span class=\"nx\">rewards<\/span><span class=\"p\">,<\/span> <span class=\"nx\">redemptions<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">profile<\/span><span class=\"p\">:<\/span> <span class=\"nx\">user<\/span><span class=\"p\">,<\/span>\n      <span class=\"nx\">habits<\/span><span class=\"p\">,<\/span>\n      <span class=\"nx\">completions<\/span><span class=\"p\">,<\/span>\n      <span class=\"nx\">rewards<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">points<\/span><span class=\"p\">:<\/span> <span class=\"nx\">userData<\/span><span class=\"p\">?.<\/span><span class=\"nx\">points<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">0<\/span><span class=\"p\">,<\/span>\n      <span class=\"nx\">streak<\/span><span class=\"p\">,<\/span>\n      <span class=\"nx\">recentActivity<\/span>\n    <span class=\"p\">};<\/span>\n  <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Error getting user data from database:<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> <span class=\"na\">error<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Failed to retrieve user data from database<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">};<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"cm\">\/**\n * Format recent activity for agent context (last 5 activities)\n *\/<\/span>\n<span class=\"kd\">function<\/span> <span class=\"nf\">formatRecentActivity<\/span><span class=\"p\">(<\/span>\n  <span class=\"nx\">habits<\/span><span class=\"p\">:<\/span> <span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">habits<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">][],<\/span> \n  <span class=\"nx\">completions<\/span><span class=\"p\">:<\/span> <span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">completions<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">][],<\/span> \n  <span class=\"nx\">rewards<\/span><span class=\"p\">:<\/span> <span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">rewards<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">][],<\/span> \n  <span class=\"nx\">redemptions<\/span><span class=\"p\">:<\/span> <span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">rewardRedemptions<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">][]<\/span>\n<span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n  <span class=\"c1\">\/\/ Define activity types<\/span>\n  <span class=\"kd\">type<\/span> <span class=\"nx\">CompletionActivity<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">completion<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">date<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Date<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">points<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">details<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">habitName<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">habitId<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">};<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">type<\/span> <span class=\"nx\">RedemptionActivity<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">redemption<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">date<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Date<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">points<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">details<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">rewardName<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">rewardId<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">};<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"kd\">type<\/span> <span class=\"nx\">CombinedActivity<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">CompletionActivity<\/span> <span class=\"o\">|<\/span> <span class=\"nx\">RedemptionActivity<\/span><span class=\"p\">;<\/span>\n\n  <span class=\"c1\">\/\/ Combine completions and redemptions<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">allActivities<\/span><span class=\"p\">:<\/span> <span class=\"nx\">CombinedActivity<\/span><span class=\"p\">[]<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span>\n    <span class=\"p\">...<\/span><span class=\"nx\">completions<\/span><span class=\"p\">.<\/span><span class=\"nf\">map<\/span><span class=\"p\">(<\/span><span class=\"nx\">completion<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">habit<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">habits<\/span><span class=\"p\">.<\/span><span class=\"nf\">find<\/span><span class=\"p\">(<\/span><span class=\"nx\">h<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">h<\/span><span class=\"p\">.<\/span><span class=\"nx\">id<\/span> <span class=\"o\">===<\/span> <span class=\"nx\">completion<\/span><span class=\"p\">.<\/span><span class=\"nx\">habitId<\/span><span class=\"p\">);<\/span>\n      <span class=\"k\">return<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">completion<\/span><span class=\"dl\">'<\/span> <span class=\"k\">as<\/span> <span class=\"kd\">const<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">date<\/span><span class=\"p\">:<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(<\/span><span class=\"nx\">completion<\/span><span class=\"p\">.<\/span><span class=\"nx\">completedAt<\/span><span class=\"p\">),<\/span>\n        <span class=\"na\">points<\/span><span class=\"p\">:<\/span> <span class=\"nx\">completion<\/span><span class=\"p\">.<\/span><span class=\"nx\">points<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">details<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">habitName<\/span><span class=\"p\">:<\/span> <span class=\"nx\">habit<\/span><span class=\"p\">?.<\/span><span class=\"nx\">name<\/span> <span class=\"o\">||<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">Unknown habit<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">habitId<\/span><span class=\"p\">:<\/span> <span class=\"nx\">completion<\/span><span class=\"p\">.<\/span><span class=\"nx\">habitId<\/span>\n        <span class=\"p\">}<\/span>\n      <span class=\"p\">};<\/span>\n    <span class=\"p\">}),<\/span>\n    <span class=\"p\">...<\/span><span class=\"nx\">redemptions<\/span><span class=\"p\">.<\/span><span class=\"nf\">map<\/span><span class=\"p\">(<\/span><span class=\"nx\">redemption<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">reward<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">rewards<\/span><span class=\"p\">.<\/span><span class=\"nf\">find<\/span><span class=\"p\">(<\/span><span class=\"nx\">r<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">r<\/span><span class=\"p\">.<\/span><span class=\"nx\">id<\/span> <span class=\"o\">===<\/span> <span class=\"nx\">redemption<\/span><span class=\"p\">.<\/span><span class=\"nx\">rewardId<\/span><span class=\"p\">);<\/span>\n      <span class=\"k\">return<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">redemption<\/span><span class=\"dl\">'<\/span> <span class=\"k\">as<\/span> <span class=\"kd\">const<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">date<\/span><span class=\"p\">:<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(<\/span><span class=\"nx\">redemption<\/span><span class=\"p\">.<\/span><span class=\"nx\">redeemedAt<\/span><span class=\"p\">),<\/span>\n        <span class=\"na\">points<\/span><span class=\"p\">:<\/span> <span class=\"o\">-<\/span><span class=\"nx\">redemption<\/span><span class=\"p\">.<\/span><span class=\"nx\">cost<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">details<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">rewardName<\/span><span class=\"p\">:<\/span> <span class=\"nx\">reward<\/span><span class=\"p\">?.<\/span><span class=\"nx\">name<\/span> <span class=\"o\">||<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">Unknown reward<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">rewardId<\/span><span class=\"p\">:<\/span> <span class=\"nx\">redemption<\/span><span class=\"p\">.<\/span><span class=\"nx\">rewardId<\/span>\n        <span class=\"p\">}<\/span>\n      <span class=\"p\">};<\/span>\n    <span class=\"p\">})<\/span>\n  <span class=\"p\">];<\/span>\n\n  <span class=\"c1\">\/\/ Sort by date (newest first)<\/span>\n  <span class=\"nx\">allActivities<\/span><span class=\"p\">.<\/span><span class=\"nf\">sort<\/span><span class=\"p\">((<\/span><span class=\"nx\">a<\/span><span class=\"p\">,<\/span> <span class=\"nx\">b<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">b<\/span><span class=\"p\">.<\/span><span class=\"nx\">date<\/span><span class=\"p\">.<\/span><span class=\"nf\">getTime<\/span><span class=\"p\">()<\/span> <span class=\"o\">-<\/span> <span class=\"nx\">a<\/span><span class=\"p\">.<\/span><span class=\"nx\">date<\/span><span class=\"p\">.<\/span><span class=\"nf\">getTime<\/span><span class=\"p\">());<\/span>\n\n  <span class=\"c1\">\/\/ Take the 5 most recent activities<\/span>\n  <span class=\"k\">return<\/span> <span class=\"nx\">allActivities<\/span><span class=\"p\">.<\/span><span class=\"nf\">slice<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"mi\">5<\/span><span class=\"p\">).<\/span><span class=\"nf\">map<\/span><span class=\"p\">(<\/span><span class=\"nx\">activity<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">formattedDate<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">activity<\/span><span class=\"p\">.<\/span><span class=\"nx\">date<\/span><span class=\"p\">.<\/span><span class=\"nf\">toLocaleDateString<\/span><span class=\"p\">();<\/span>\n\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">activity<\/span><span class=\"p\">.<\/span><span class=\"kd\">type<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">completion<\/span><span class=\"dl\">'<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">return<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">action<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">Completed<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">target<\/span><span class=\"p\">:<\/span> <span class=\"nx\">activity<\/span><span class=\"p\">.<\/span><span class=\"nx\">details<\/span><span class=\"p\">.<\/span><span class=\"nx\">habitName<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">date<\/span><span class=\"p\">:<\/span> <span class=\"nx\">formattedDate<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">points<\/span><span class=\"p\">:<\/span> <span class=\"nx\">activity<\/span><span class=\"p\">.<\/span><span class=\"nx\">points<\/span>\n      <span class=\"p\">};<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">else<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">return<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">action<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">Redeemed<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">target<\/span><span class=\"p\">:<\/span> <span class=\"nx\">activity<\/span><span class=\"p\">.<\/span><span class=\"nx\">details<\/span><span class=\"p\">.<\/span><span class=\"nx\">rewardName<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">date<\/span><span class=\"p\">:<\/span> <span class=\"nx\">formattedDate<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">points<\/span><span class=\"p\">:<\/span> <span class=\"nx\">activity<\/span><span class=\"p\">.<\/span><span class=\"nx\">points<\/span>\n      <span class=\"p\">};<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">});<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"cm\">\/**\n * Calculates the user's current streak based on habit completions\n * @param completions Array of habit completions\n * @returns Number representing current streak\n *\/<\/span>\n<span class=\"kd\">function<\/span> <span class=\"nf\">calculateStreak<\/span><span class=\"p\">(<\/span><span class=\"nx\">completions<\/span><span class=\"p\">:<\/span> <span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">completions<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">][]):<\/span> <span class=\"kr\">number<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">completions<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span><span class=\"p\">)<\/span> <span class=\"k\">return<\/span> <span class=\"mi\">0<\/span><span class=\"p\">;<\/span>\n\n  <span class=\"c1\">\/\/ Sort completions by date (newest first)<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">sortedCompletions<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[...<\/span><span class=\"nx\">completions<\/span><span class=\"p\">].<\/span><span class=\"nf\">sort<\/span><span class=\"p\">((<\/span><span class=\"nx\">a<\/span><span class=\"p\">,<\/span> <span class=\"nx\">b<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> \n    <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(<\/span><span class=\"nx\">b<\/span><span class=\"p\">.<\/span><span class=\"nx\">completedAt<\/span><span class=\"p\">).<\/span><span class=\"nf\">getTime<\/span><span class=\"p\">()<\/span> <span class=\"o\">-<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(<\/span><span class=\"nx\">a<\/span><span class=\"p\">.<\/span><span class=\"nx\">completedAt<\/span><span class=\"p\">).<\/span><span class=\"nf\">getTime<\/span><span class=\"p\">()<\/span>\n  <span class=\"p\">);<\/span>\n\n  <span class=\"c1\">\/\/ Group completions by day<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">dailyCompletions<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"nb\">Map<\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">string<\/span><span class=\"p\">,<\/span> <span class=\"nx\">WeiDB<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">completions<\/span><span class=\"dl\">'<\/span><span class=\"p\">][<\/span><span class=\"dl\">'<\/span><span class=\"s1\">value<\/span><span class=\"dl\">'<\/span><span class=\"p\">][]<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">();<\/span>\n  <span class=\"nx\">sortedCompletions<\/span><span class=\"p\">.<\/span><span class=\"nf\">forEach<\/span><span class=\"p\">(<\/span><span class=\"nx\">completion<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">date<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(<\/span><span class=\"nx\">completion<\/span><span class=\"p\">.<\/span><span class=\"nx\">completedAt<\/span><span class=\"p\">);<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">dateString<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">date<\/span><span class=\"p\">.<\/span><span class=\"nf\">toISOString<\/span><span class=\"p\">().<\/span><span class=\"nf\">split<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">T<\/span><span class=\"dl\">'<\/span><span class=\"p\">)[<\/span><span class=\"mi\">0<\/span><span class=\"p\">];<\/span>\n\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">dailyCompletions<\/span><span class=\"p\">.<\/span><span class=\"nf\">has<\/span><span class=\"p\">(<\/span><span class=\"nx\">dateString<\/span><span class=\"p\">))<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">dailyCompletions<\/span><span class=\"p\">.<\/span><span class=\"nf\">set<\/span><span class=\"p\">(<\/span><span class=\"nx\">dateString<\/span><span class=\"p\">,<\/span> <span class=\"p\">[]);<\/span>\n    <span class=\"p\">}<\/span>\n    <span class=\"nx\">dailyCompletions<\/span><span class=\"p\">.<\/span><span class=\"nf\">get<\/span><span class=\"p\">(<\/span><span class=\"nx\">dateString<\/span><span class=\"p\">)<\/span><span class=\"o\">!<\/span><span class=\"p\">.<\/span><span class=\"nf\">push<\/span><span class=\"p\">(<\/span><span class=\"nx\">completion<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">});<\/span>\n\n  <span class=\"c1\">\/\/ Check if today has completions<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">today<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">().<\/span><span class=\"nf\">toISOString<\/span><span class=\"p\">().<\/span><span class=\"nf\">split<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">T<\/span><span class=\"dl\">'<\/span><span class=\"p\">)[<\/span><span class=\"mi\">0<\/span><span class=\"p\">];<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">hasCompletionToday<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">dailyCompletions<\/span><span class=\"p\">.<\/span><span class=\"nf\">has<\/span><span class=\"p\">(<\/span><span class=\"nx\">today<\/span><span class=\"p\">);<\/span>\n\n  <span class=\"c1\">\/\/ Calculate streak<\/span>\n  <span class=\"kd\">let<\/span> <span class=\"nx\">currentStreak<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">hasCompletionToday<\/span> <span class=\"p\">?<\/span> <span class=\"mi\">1<\/span> <span class=\"p\">:<\/span> <span class=\"mi\">0<\/span><span class=\"p\">;<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">dates<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">Array<\/span><span class=\"p\">.<\/span><span class=\"k\">from<\/span><span class=\"p\">(<\/span><span class=\"nx\">dailyCompletions<\/span><span class=\"p\">.<\/span><span class=\"nf\">keys<\/span><span class=\"p\">()).<\/span><span class=\"nf\">sort<\/span><span class=\"p\">().<\/span><span class=\"nf\">reverse<\/span><span class=\"p\">();<\/span>\n\n  <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">dates<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">&lt;=<\/span> <span class=\"mi\">1<\/span><span class=\"p\">)<\/span> <span class=\"k\">return<\/span> <span class=\"nx\">currentStreak<\/span><span class=\"p\">;<\/span>\n\n  <span class=\"c1\">\/\/ Start from yesterday if we have a completion today<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">startIndex<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">hasCompletionToday<\/span> <span class=\"p\">?<\/span> <span class=\"mi\">1<\/span> <span class=\"p\">:<\/span> <span class=\"mi\">0<\/span><span class=\"p\">;<\/span>\n\n  <span class=\"k\">for <\/span><span class=\"p\">(<\/span><span class=\"kd\">let<\/span> <span class=\"nx\">i<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">startIndex<\/span><span class=\"p\">;<\/span> <span class=\"nx\">i<\/span> <span class=\"o\">&lt;<\/span> <span class=\"nx\">dates<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span><span class=\"p\">;<\/span> <span class=\"nx\">i<\/span><span class=\"o\">++<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">currentDate<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(<\/span><span class=\"nx\">dates<\/span><span class=\"p\">[<\/span><span class=\"nx\">i<\/span><span class=\"p\">]);<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">previousDate<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(<\/span><span class=\"nx\">dates<\/span><span class=\"p\">[<\/span><span class=\"nx\">i<\/span><span class=\"o\">-<\/span><span class=\"mi\">1<\/span><span class=\"p\">]);<\/span>\n\n    <span class=\"c1\">\/\/ Calculate difference in days<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">diffTime<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">previousDate<\/span><span class=\"p\">.<\/span><span class=\"nf\">getTime<\/span><span class=\"p\">()<\/span> <span class=\"o\">-<\/span> <span class=\"nx\">currentDate<\/span><span class=\"p\">.<\/span><span class=\"nf\">getTime<\/span><span class=\"p\">();<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">diffDays<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">ceil<\/span><span class=\"p\">(<\/span><span class=\"nx\">diffTime<\/span> <span class=\"o\">\/<\/span> <span class=\"p\">(<\/span><span class=\"mi\">1000<\/span> <span class=\"o\">*<\/span> <span class=\"mi\">60<\/span> <span class=\"o\">*<\/span> <span class=\"mi\">60<\/span> <span class=\"o\">*<\/span> <span class=\"mi\">24<\/span><span class=\"p\">));<\/span>\n\n    <span class=\"c1\">\/\/ If the difference is exactly 1 day, continue the streak<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">diffDays<\/span> <span class=\"o\">===<\/span> <span class=\"mi\">1<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">currentStreak<\/span><span class=\"o\">++<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">else<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">break<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">}<\/span>\n\n  <span class=\"k\">return<\/span> <span class=\"nx\">currentStreak<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"%D8%A2%D8%AA%D8%B4_%D8%B3%D9%88%D8%B2%DB%8C_OpenTime_%D8%A8%D8%A7%D8%B2_%D8%A7%D8%B3%D8%AA\"><\/span>\n<p>  \u0622\u062a\u0634 \u0633\u0648\u0632\u06cc OpenTime \u0628\u0627\u0632 \u0627\u0633\u062a<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0628\u0631\u0627\u06cc \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 API OpenAi RealTime \u060c \u0628\u0627\u06cc\u062f \u06cc\u06a9 \u062c\u0644\u0633\u0647 \u062c\u062f\u06cc\u062f \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u0645. <br \/>\u0648 \u0647\u0631 \u0628\u0627\u0631 \u06a9\u0647 \u06a9\u0627\u0631\u0628\u0631 \u0628\u0647 \u06af\u0632\u06cc\u0646\u0647 \u0686\u062a \u0635\u0648\u062a\u06cc \u0628\u0631\u062e\u0648\u0631\u062f \u0645\u06cc \u06a9\u0646\u062f \u0628\u0627\u06cc\u062f \u0627\u062a\u0641\u0627\u0642 \u0628\u06cc\u0641\u062a\u062f.<br \/>\u06cc\u06a9 \u0641\u0627\u06cc\u0644 \u062c\u062f\u06cc\u062f \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f <code>app\/api\/session\/route.ts<\/code>\u0628\u0634\u0631<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight typescript\"><code><span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">NextResponse<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">next\/server<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">async<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">GET<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">response<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">fetch<\/span><span class=\"p\">(<\/span>\n      <span class=\"dl\">\"<\/span><span class=\"s2\">https:\/\/api.openai.com\/v1\/realtime\/sessions<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n      <span class=\"p\">{<\/span>\n        <span class=\"na\">method<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">POST<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">headers<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">Authorization<\/span><span class=\"p\">:<\/span> <span class=\"s2\">`Bearer <\/span><span class=\"p\">${<\/span><span class=\"nx\">process<\/span><span class=\"p\">.<\/span><span class=\"nx\">env<\/span><span class=\"p\">.<\/span><span class=\"nx\">OPENAI_API_KEY<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span><span class=\"p\">,<\/span>\n          <span class=\"dl\">\"<\/span><span class=\"s2\">Content-Type<\/span><span class=\"dl\">\"<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">application\/json<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"p\">},<\/span>\n        <span class=\"na\">body<\/span><span class=\"p\">:<\/span> <span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">stringify<\/span><span class=\"p\">({<\/span>\n          <span class=\"na\">model<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">gpt-4o-realtime-preview-2024-12-17<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n        <span class=\"p\">}),<\/span>\n      <span class=\"p\">}<\/span>\n    <span class=\"p\">);<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">data<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">response<\/span><span class=\"p\">.<\/span><span class=\"nf\">json<\/span><span class=\"p\">();<\/span>\n    <span class=\"k\">return<\/span> <span class=\"nx\">NextResponse<\/span><span class=\"p\">.<\/span><span class=\"nf\">json<\/span><span class=\"p\">(<\/span><span class=\"nx\">data<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">Error in \/session:<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">return<\/span> <span class=\"nx\">NextResponse<\/span><span class=\"p\">.<\/span><span class=\"nf\">json<\/span><span class=\"p\">(<\/span>\n      <span class=\"p\">{<\/span> <span class=\"na\">error<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Internal Server Error<\/span><span class=\"dl\">\"<\/span> <span class=\"p\">},<\/span>\n      <span class=\"p\">{<\/span> <span class=\"na\">status<\/span><span class=\"p\">:<\/span> <span class=\"mi\">500<\/span> <span class=\"p\">}<\/span>\n    <span class=\"p\">);<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"%D8%AA%D9%86%D8%B8%DB%8C%D9%85_env\"><\/span>\n<p>  \u062a\u0646\u0638\u06cc\u0645 .env<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u06cc\u06a9 \u0641\u0627\u06cc\u0644 \u062c\u062f\u06cc\u062f \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f <code>.env<\/code> \u0648 \u0645\u062a\u063a\u06cc\u0631\u0647\u0627\u06cc \u0632\u06cc\u0631 \u0631\u0627 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight plaintext\"><code>AIML_API_KEY=...\nGIPHY_API_KEY=... ( optional, it's for sending gifs )\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h2><span class=\"ez-toc-section\" id=\"%D8%A8%D8%A7%D8%B2%DA%AF%D8%B4%D8%AA_%D8%A8%D9%87_UI\"><\/span>\n<p>  \u0628\u0627\u0632\u06af\u0634\u062a \u0628\u0647 UI<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>quckly \u06cc\u06a9 \u0646\u0627\u0648\u0628\u0631\u06cc \u067e\u0627\u06cc\u06cc\u0646 \u0628\u0647 <code>Dashboard<\/code> \u0635\u0641\u062d\u0647<br \/>\u0627\u06cc\u0646 \u0627\u0645\u06a9\u0627\u0646 \u062f\u0633\u062a\u0631\u0633\u06cc \u0633\u0631\u06cc\u0639 \u0628\u0647 \u062e\u0627\u0646\u0647 \u060c \u0639\u0627\u062f\u0627\u062a \u060c \u067e\u0627\u062f\u0627\u0634 \u060c \u0686\u062a \u0648 \u0635\u0641\u062d\u0627\u062a \u067e\u0631\u0648\u0641\u0627\u06cc\u0644 \u0631\u0627 \u0641\u0631\u0627\u0647\u0645 \u0645\u06cc \u06a9\u0646\u062f.<br \/>\u0645\u0648\u0628\u0627\u06cc\u0644 \u062f\u0648\u0633\u062a\u0627\u0646\u0647 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0622\u0633\u0627\u0646<\/p>\n<p>\u06cc\u06a9 \u0641\u0627\u06cc\u0644 \u062c\u062f\u06cc\u062f \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f <code>app\/components\/dashboard\/BottomNavigation.tsx<\/code>\u0628\u0634\u0631<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"dl\">\"<\/span><span class=\"s2\">use client<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">import<\/span> <span class=\"nx\">Link<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">next\/link<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">usePathname<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">next\/navigation<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">House<\/span><span class=\"p\">,<\/span> <span class=\"nx\">ListChecks<\/span><span class=\"p\">,<\/span> <span class=\"nx\">Gift<\/span><span class=\"p\">,<\/span> <span class=\"nx\">ChatCenteredText<\/span><span class=\"p\">,<\/span> <span class=\"nx\">User<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@phosphor-icons\/react\/dist\/ssr<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">cn<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/lib\/utils<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"kd\">const<\/span> <span class=\"nx\">items<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span>\n  <span class=\"p\">{<\/span>\n    <span class=\"na\">label<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Home<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">icon<\/span><span class=\"p\">:<\/span> <span class=\"nx\">House<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">href<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">\/dashboard<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n  <span class=\"p\">},<\/span>\n  <span class=\"p\">{<\/span>\n    <span class=\"na\">label<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Habits<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">icon<\/span><span class=\"p\">:<\/span> <span class=\"nx\">ListChecks<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">href<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">\/habits<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n  <span class=\"p\">},<\/span>\n  <span class=\"p\">{<\/span>\n    <span class=\"na\">label<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Rewards<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">icon<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Gift<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">href<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">\/rewards<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n  <span class=\"p\">},<\/span>\n  <span class=\"p\">{<\/span>\n    <span class=\"na\">label<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Chat<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">icon<\/span><span class=\"p\">:<\/span> <span class=\"nx\">ChatCenteredText<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">href<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">\/chat<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n  <span class=\"p\">},<\/span>\n  <span class=\"p\">{<\/span>\n    <span class=\"na\">label<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">Profile<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">icon<\/span><span class=\"p\">:<\/span> <span class=\"nx\">User<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">href<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">\/profile<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n  <span class=\"p\">},<\/span>\n<span class=\"p\">];<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">BottomNavigation<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">pathname<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">usePathname<\/span><span class=\"p\">();<\/span>\n\n  <span class=\"k\">return <\/span><span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"fixed bottom-0 left-0 right-0 z-10 md:hidden\"<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"bg-background\/80 backdrop-blur-md border-t\"<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">nav<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"flex justify-around\"<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"si\">{<\/span><span class=\"nx\">items<\/span><span class=\"p\">.<\/span><span class=\"nf\">map<\/span><span class=\"p\">((<\/span><span class=\"nx\">item<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n            <span class=\"kd\">const<\/span> <span class=\"nx\">isActive<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">pathname<\/span> <span class=\"o\">===<\/span> <span class=\"nx\">item<\/span><span class=\"p\">.<\/span><span class=\"nx\">href<\/span> <span class=\"o\">||<\/span> \n              <span class=\"p\">(<\/span><span class=\"nx\">item<\/span><span class=\"p\">.<\/span><span class=\"nx\">href<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">\/dashboard<\/span><span class=\"dl\">'<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">pathname<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">\/<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n\n            <span class=\"k\">return <\/span><span class=\"p\">(<\/span>\n              <span class=\"p\">&lt;<\/span><span class=\"nc\">Link<\/span>\n                <span class=\"na\">key<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">item<\/span><span class=\"p\">.<\/span><span class=\"nx\">label<\/span><span class=\"si\">}<\/span>\n                <span class=\"na\">href<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">item<\/span><span class=\"p\">.<\/span><span class=\"nx\">href<\/span><span class=\"si\">}<\/span>\n                <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nf\">cn<\/span><span class=\"p\">(<\/span>\n                  <span class=\"dl\">\"<\/span><span class=\"s2\">flex flex-col items-center py-2 px-3<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n                  <span class=\"nx\">isActive<\/span> \n                    <span class=\"p\">?<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">text-primary<\/span><span class=\"dl\">\"<\/span> \n                    <span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">text-muted-foreground hover:text-foreground<\/span><span class=\"dl\">\"<\/span>\n                <span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n              <span class=\"p\">&gt;<\/span>\n                <span class=\"p\">&lt;<\/span><span class=\"nt\">item<\/span><span class=\"p\">.<\/span><span class=\"nt\">icon<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"h-5 w-5\"<\/span> <span class=\"p\">\/&gt;<\/span>\n                <span class=\"p\">&lt;<\/span><span class=\"nt\">span<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"text-xs mt-1\"<\/span><span class=\"p\">&gt;<\/span><span class=\"si\">{<\/span><span class=\"nx\">item<\/span><span class=\"p\">.<\/span><span class=\"nx\">label<\/span><span class=\"si\">}<\/span><span class=\"p\"\/><span class=\"nt\">span<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"p\"\/><span class=\"nc\">Link<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">);<\/span>\n          <span class=\"p\">})<\/span><span class=\"si\">}<\/span>\n        <span class=\"p\"\/><span class=\"nt\">nav<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\"\/><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\"\/><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n  <span class=\"p\">);<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0627\u0636\u0627\u0641\u0647 \u06a9\u0631\u062f\u0646 <code>BottomNavigation<\/code> \u062c\u0632\u0621 <code>Dashboard<\/code> \u0635\u0641\u062d\u0647<\/p>\n<p>\u0633\u067e\u0633 \u067e\u0648\u0634\u0647 \u0647\u0627\u06cc \u0645\u062e\u062a\u0644\u0641 \u0631\u0627 \u0628\u0631\u0627\u06cc \u0635\u0641\u062d\u0627\u062a \u062f\u06cc\u06af\u0631 \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f. <br \/>\u0628\u06cc\u0627\u06cc\u06cc\u062f <code>chat<\/code> \u0635\u0641\u062d\u0647<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight plaintext\"><code>app\n  chat\n    page.tsx\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0641\u0631\u0627\u062e\u0648\u0627\u0646\u06cc <code>ChatInterface<\/code> \u0645\u0624\u0644\u0641\u0647 \u062f\u0631 <code>chat<\/code> \u0635\u0641\u062d\u0647<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"dl\">\"<\/span><span class=\"s2\">use client<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">useDatabase<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/app\/contexts\/DatabaseContext<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">DatabaseError<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/app\/components\/errors\/DatabaseError<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">ChatInterface<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">@\/app\/components\/chat\/ChatInterface<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">DefaultLoading<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">..\/components\/default-loading<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">ChatPage<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">error<\/span><span class=\"p\">,<\/span> <span class=\"nx\">isLoading<\/span> <span class=\"p\">}<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useDatabase<\/span><span class=\"p\">();<\/span>\n\n  <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">return<\/span> <span class=\"p\">&lt;<\/span><span class=\"nc\">DatabaseError<\/span> <span class=\"na\">error<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">error<\/span><span class=\"si\">}<\/span> <span class=\"na\">onRetry<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nb\">window<\/span><span class=\"p\">.<\/span><span class=\"nx\">location<\/span><span class=\"p\">.<\/span><span class=\"nf\">reload<\/span><span class=\"p\">()<\/span><span class=\"si\">}<\/span> <span class=\"p\">\/&gt;;<\/span>\n  <span class=\"p\">}<\/span>\n\n  <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">isLoading<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">return <\/span><span class=\"p\">(<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nc\">DefaultLoading<\/span> <span class=\"na\">text<\/span><span class=\"p\">=<\/span><span class=\"s\">\"loading...\"<\/span> <span class=\"p\">\/&gt;<\/span>\n    <span class=\"p\">);<\/span>\n  <span class=\"p\">}<\/span>\n\n  <span class=\"k\">return <\/span><span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"@container\/main relative flex h-full w-full flex-col items-center justify-end\"<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nc\">ChatInterface<\/span> <span class=\"p\">\/&gt;<\/span>\n      <span class=\"p\"\/><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&gt;<\/span>\n  <span class=\"p\">);<\/span>\n<span class=\"p\">}<\/span> \n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0647\u0645\u06cc\u0646 \u0645\u0648\u0631\u062f \u0631\u0627 \u0628\u0631\u0627\u06cc \u0633\u0627\u06cc\u0631 \u0635\u0641\u062d\u0627\u062a \u062a\u06a9\u0631\u0627\u0631 \u06a9\u0646\u06cc\u062f.<\/p>\n<p>UI\/UX \u0646\u0647\u0627\u06cc\u06cc \u0628\u0631\u0646\u0627\u0645\u0647. \u0628\u0627\u06cc\u062f \u0634\u0628\u06cc\u0647 \u0627\u06cc\u0646 \u0628\u0627\u0634\u062f<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/media2.dev.to\/dynamic\/image\/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto\/.%2Fpublic%2Fassets%2Fwei-uiux.png\" alt=\"\u0648\u06cc\u0698\u06af\u06cc \u0647\u0627\u06cc \u0648\u06cc\" loading=\"lazy\" width=\"800\" height=\"400\" title=\"\"><\/p>\n<h2><span class=\"ez-toc-section\" id=\"%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87_%D8%B1%D8%A7_%D8%A7%D8%AC%D8%B1%D8%A7_%DA%A9%D9%86%DB%8C%D8%AF\"><\/span>\n<p>  \u0628\u0631\u0646\u0627\u0645\u0647 \u0631\u0627 \u0627\u062c\u0631\u0627 \u06a9\u0646\u06cc\u062f<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0628\u0631\u0627\u06cc \u0627\u062c\u0631\u0627\u06cc \u0628\u0631\u0646\u0627\u0645\u0647 \u060c \u0627\u0632 \u062f\u0633\u062a\u0648\u0631 \u0632\u06cc\u0631 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u06a9\u0646\u06cc\u062f:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight plaintext\"><code>npm run dev\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0631\u0641\u062a\u0646 \u0628\u0647 <code>http:\/\/localhost:3000<\/code> \u0648 \u0634\u0645\u0627 \u0628\u0627\u06cc\u062f \u0628\u0631\u0646\u0627\u0645\u0647 \u0631\u0627 \u062f\u0631 \u062d\u0627\u0644 \u0627\u062c\u0631\u0627 \u0628\u0628\u06cc\u0646\u06cc\u062f.<\/p>\n<p>\u0633\u067e\u0633 \u062a\u063a\u06cc\u06cc\u0631\u0627\u062a \u0631\u0627 \u0628\u0647 <code>main<\/code> \u0634\u0627\u062e\u0647<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight plaintext\"><code>git add .\ngit commit -m \"wei ai voice agent\"\ngit push\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0628\u0647 Vercel.com \u0628\u0631\u0648\u06cc\u062f \u0648 \u0645\u062e\u0632\u0646 GitHub \u062e\u0648\u062f \u0631\u0627 \u0648\u0635\u0644 \u06a9\u0646\u06cc\u062f. \u0648\u0627\u0631\u062f \u06a9\u0631\u062f\u0646 \u067e\u0631\u0648\u0698\u0647 \u0648 \u0627\u0633\u062a\u0642\u0631\u0627\u0631.<\/p>\n<p>\u067e\u0633 \u0627\u0632 \u0627\u062a\u0645\u0627\u0645 \u060c \u0628\u0627\u06cc\u062f \u067e\u06cc\u0648\u0646\u062f\u06cc \u0628\u0647 \u0628\u0631\u0646\u0627\u0645\u0647 \u062f\u0631\u06cc\u0627\u0641\u062a \u06a9\u0646\u06cc\u062f \u06a9\u0647 \u0628\u0647 \u067e\u0627\u06cc\u0627\u0646 \u0628\u0631\u0633\u062f <code>.vercel.app<\/code>\u0628\u0634\u0631<br \/>\u0627\u06cc\u0646\u062c\u0627 \u0645\u0627\u0644 \u0645\u0646 \u0627\u0633\u062a <code>https:\/\/trywei.vercel.app\/<\/code>\u0628\u0634\u0631<\/p>\n<h2><span class=\"ez-toc-section\" id=\"%D9%85%D8%B1%D8%A7%D8%AD%D9%84_%D8%A8%D8%B9%D8%AF%DB%8C\"><\/span>\n<p>  \u0645\u0631\u0627\u062d\u0644 \u0628\u0639\u062f\u06cc<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<ul>\n<li>\u0646\u0627\u0645 \u062f\u0627\u0645\u0646\u0647 \u0631\u0627 \u0628\u062e\u0631\u06cc\u062f \u0648 \u0622\u0646 \u0631\u0627 \u0628\u0647 \u0628\u0631\u0646\u0627\u0645\u0647 Vercel \u0627\u0634\u0627\u0631\u0647 \u06a9\u0646\u06cc\u062f (\u0645\u062b\u0627\u0644: https:\/\/wei.yaps.gg)<\/li>\n<li>\u067e\u062e\u0634 \u0648\u06cc\u062f\u06cc\u0648\u06cc Realtime \u0631\u0627 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f<\/li>\n<li>\u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u0645\u062b\u0627\u0644 supabase \u067e\u0627\u06cc\u06af\u0627\u0647 \u062f\u0627\u062f\u0647 \u0627\u0632 \u0631\u0627\u0647 \u062f\u0648\u0631 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f<\/li>\n<li>Auth \u0631\u0627 \u0628\u0627 Google OAuth 2.0 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f<\/li>\n<li>\u0648 \u0633\u0627\u06cc\u0631 \u0648\u06cc\u0698\u06af\u06cc \u0647\u0627\u06cc \u062c\u0627\u0644\u0628 &#8230;.<\/li>\n<\/ul>\n<p>\u0627\u06af\u0631 \u0633\u0648\u0627\u0644\u06cc \u062f\u0627\u0631\u06cc\u062f \u060c \u0627\u062d\u0633\u0627\u0633 \u0631\u0627\u062d\u062a\u06cc \u06a9\u0646\u06cc\u062f \u0627\u0632 \u0645\u0646 \u0628\u067e\u0631\u0633\u06cc\u062f.<\/p>\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>\ud83c\udf31 \u0648\u06cc: \u0639\u0648\u0627\u0645\u0644 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u0628\u0631\u0627\u06cc \u0631\u0634\u062f \u0634\u062e\u0635\u06cc \u0627\u062e\u06cc\u0631\u0627\u064b \u062f\u0631 \u06cc\u06a9 Hackathon Localdown \u0634\u0631\u06a9\u062a \u06a9\u0631\u062f\u0645. \u0645\u0646 \u0648\u06cc \u0631\u0627 \u0633\u0627\u062e\u062a\u0645 \u060c \u06cc\u06a9 \u0639\u0627\u0645\u0644 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u06a9\u0647 \u0628\u0647 \u0634\u0645\u0627 \u062f\u0631 \u0627\u06cc\u062c\u0627\u062f \u0639\u0627\u062f\u062a \u0647\u0627\u06cc \u062e\u0648\u0628 \u06a9\u0645\u06a9 \u0645\u06cc \u06a9\u0646\u062f. TLDR: \ud83c\udf31 WEI \u0639\u0627\u0645\u0644 AI \u0645\u06a9\u0627\u0644\u0645\u0647 \u0634\u0645\u0627 \u0627\u0633\u062a \u06a9\u0647 \u0627\u0632 \u0637\u0631\u06cc\u0642 \u06af\u0641\u062a\u06af\u0648\u06cc \u0637\u0628\u06cc\u0639\u06cc \u060c \u0639\u0627\u062f\u062a \u0631\u0627 \u0628\u06cc \u062f\u0631\u062f\u0633\u0631 \u0645\u06cc \u06a9\u0646\u062f. &hellip;<\/p>\n","protected":false},"author":2,"featured_media":108853,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"https:\/\/media2.dev.to\/dynamic\/image\/width=1000,height=500,fit=cover,gravity=auto,format=auto\/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ylskkgs2aykpsxke4jp.png","fifu_image_alt":"","footnotes":""},"categories":[339],"tags":[],"class_list":["post-108851","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dev"],"_links":{"self":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/posts\/108851","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/comments?post=108851"}],"version-history":[{"count":0,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/posts\/108851\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/media\/108853"}],"wp:attachment":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/media?parent=108851"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/categories?post=108851"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/tags?post=108851"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}