{"id":25615,"date":"2026-06-20T12:07:00","date_gmt":"2026-06-20T12:07:00","guid":{"rendered":"https:\/\/umang.pk\/2026\/06\/20\/%d8%a7%db%92-%d8%a2%d8%a6%db%8c-%d8%b3%db%92-%da%86%d9%84%d9%86%db%92-%d9%88%d8%a7%d9%84%db%8c-%d9%84%d9%88%da%a9%d9%84-%d9%81%d8%b1%d8%b3%d9%b9-%da%a9%d8%b1%d9%88%d9%85-%d8%a7%db%8c%da%a9%d8%b3%d9%b9\/"},"modified":"2026-06-20T12:07:06","modified_gmt":"2026-06-20T12:07:06","slug":"%d8%a7%db%92-%d8%a2%d8%a6%db%8c-%d8%b3%db%92-%da%86%d9%84%d9%86%db%92-%d9%88%d8%a7%d9%84%db%8c-%d9%84%d9%88%da%a9%d9%84-%d9%81%d8%b1%d8%b3%d9%b9-%da%a9%d8%b1%d9%88%d9%85-%d8%a7%db%8c%da%a9%d8%b3%d9%b9","status":"publish","type":"post","link":"https:\/\/umang.pk\/ur\/2026\/06\/20\/%d8%a7%db%92-%d8%a2%d8%a6%db%8c-%d8%b3%db%92-%da%86%d9%84%d9%86%db%92-%d9%88%d8%a7%d9%84%db%8c-%d9%84%d9%88%da%a9%d9%84-%d9%81%d8%b1%d8%b3%d9%b9-%da%a9%d8%b1%d9%88%d9%85-%d8%a7%db%8c%da%a9%d8%b3%d9%b9\/","title":{"rendered":"\u0627\u06d2 \u0622\u0626\u06cc \u0633\u06d2 \u0686\u0644\u0646\u06d2 \u0648\u0627\u0644\u06cc \u0644\u0648\u06a9\u0644 \u0641\u0631\u0633\u0679 \u06a9\u0631\u0648\u0645 \u0627\u06cc\u06a9\u0633\u0679\u06cc\u0646\u0634\u0646 \u06a9\u0648 \u06a9\u06cc\u0633\u06d2 \u0628\u0646\u0627\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u062c\u0648 \u0622\u067e \u06a9\u06cc \u0628\u0631\u0627\u0624\u0632\u0646\u06af \u06c1\u0633\u0679\u0631\u06cc \u06a9\u0648 \u0627\u0631\u0627\u062f\u06d2 \u06a9\u06d2 \u0646\u0642\u0634\u06d2 \u0645\u06cc\u06ba \u0628\u062f\u0644 \u062f\u06d2"},"content":{"rendered":"\n<div id=\"\">\n<p>\u0622\u067e \u06a9\u0627 \u0628\u0631\u0627\u0624\u0632\u0631 \u06c1\u0631 \u0648\u06c1 \u0635\u0641\u062d\u06c1 \u06cc\u0627\u062f \u0631\u06a9\u06be\u062a\u0627 \u06c1\u06d2 \u062c\u0633\u06d2 \u0622\u067e \u0646\u06d2 \u06a9\u0628\u06be\u06cc \u06a9\u06be\u0648\u0644\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u0627\u0633\u06d2 \u06a9\u0686\u06be \u0645\u0639\u0644\u0648\u0645 \u0646\u06c1\u06cc\u06ba \u06a9\u06c1 \u0622\u067e \u0646\u06d2 \u0627\u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0648\u06ba \u06a9\u06be\u0648\u0644\u0627\u06d4<\/p>\n<p>\u0627\u06af\u0631 \u0622\u067e \u062a\u06cc\u0646 \u062f\u0646 \u062a\u06a9 \u062f\u0631\u062c\u0646 \u0628\u06be\u0631 \u0679\u06cc\u0628\u0632 \u067e\u0631 \u0645\u0648\u062c\u0648\u062f \u0646\u0648\u0679 \u0628\u06a9 \u06a9\u0627 \u0645\u0648\u0627\u0632\u0646\u06c1 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0645\u0634\u063a\u0648\u0644 \u06c1\u0648 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u06c1\u0641\u062a\u06d2 \u0628\u0639\u062f \u0648\u0627\u067e\u0633 \u0622\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0622\u067e \u06a9\u06cc \u062a\u0627\u0631\u06cc\u062e \u0635\u0631\u0641 \u0679\u0627\u0626\u0645 \u0627\u0633\u0679\u06cc\u0645\u067e \u0627\u0648\u0631 \u0639\u0646\u0648\u0627\u0646\u0627\u062a \u06a9\u06cc \u0627\u06cc\u06a9 \u0633\u0627\u062f\u06c1 \u0641\u06c1\u0631\u0633\u062a \u062f\u06a9\u06be\u0627 \u0633\u06a9\u062a\u06cc \u06c1\u06d2\u060c \u0627\u0633 \u0628\u0627\u062a \u06a9\u0627 \u06a9\u0648\u0626\u06cc \u0627\u0634\u0627\u0631\u06c1 \u0646\u06c1\u06cc\u06ba \u06a9\u06c1 \u0648\u06c1 \u0648\u0632\u0679 \u0627\u06cc\u06a9 \u0686\u06cc\u0632 \u062a\u06be\u06cc \u2014 \u0627\u06cc\u06a9 \u0641\u06cc\u0635\u0644\u06c1 \u062c\u0648 \u0622\u067e \u0646\u06d2 \u0634\u0631\u0648\u0639 \u06a9\u06cc\u0627 \u0644\u06cc\u06a9\u0646 \u06a9\u0628\u06be\u06cc \u062e\u062a\u0645 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u0627\u06d4<\/p>\n<p>\u0627\u0633 \u0679\u06cc\u0648\u0679\u0648\u0631\u06cc\u0644 \u0645\u06cc\u06ba \u0622\u067e \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba: <strong>\u06a9\u06be\u0644\u06cc \u0644\u0648\u067e<\/strong>\u0627\u06cc\u06a9 \u0627\u0648\u067e\u0646 \u0633\u0648\u0631\u0633\u060c \u0644\u0648\u06a9\u0644 \u0641\u0631\u0633\u0679 \u06a9\u0631\u0648\u0645 \u0627\u06cc\u06a9\u0633\u0679\u06cc\u0646\u0634\u0646 \u06c1\u06d2 \u062c\u0648 \u0622\u067e \u06a9\u06cc \u0628\u0631\u0627\u0624\u0632\u0646\u06af \u06c1\u0633\u0679\u0631\u06cc \u06a9\u0648 \u0627\u0633\u06a9\u06cc\u0646 \u06a9\u0631\u06a9\u06d2\u060c \u0627\u0646\u06c1\u06cc\u06ba &quot;\u0627\u0646\u0679\u0679 \u062a\u06be\u0631\u06cc\u0688\u0632&#8221; (\u0641\u06cc\u0635\u0644\u06d2\u060c \u062a\u062d\u0642\u06cc\u0642\u0627\u062a\u060c \u0627\u0648\u0631 \u06a9\u06be\u0644\u06d2 \u0633\u0648\u0627\u0644\u0627\u062a \u062c\u0646 \u067e\u0631 \u0622\u067e \u0648\u0627\u067e\u0633 \u0622\u062a\u06d2 \u0631\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba) \u0645\u06cc\u06ba \u06af\u0631\u0648\u067e \u0628\u0646\u062f\u06cc \u06a9\u0631\u06a9\u06d2 \u0627\u0648\u0631 \u067e\u06be\u0631 \u06c1\u0631 \u0622\u0626\u0679\u0645 \u06a9\u0648 \u0627\u0633\u06a9\u0648\u0631 \u06a9\u0631\u06a9\u06d2 \u0627\u0633 \u0645\u0633\u0626\u0644\u06d2 \u06a9\u0648 \u062d\u0644 \u06a9\u0631\u062a\u06cc \u06c1\u06d2 \u06a9\u06c1 \u06cc\u06c1 \u0627\u0628 \u0628\u06be\u06cc \u06a9\u062a\u0646\u0627 \u0632\u0646\u062f\u06c1 \u06c1\u06d2\u06d4 \u0627\u062e\u062a\u06cc\u0627\u0631\u06cc \u0637\u0648\u0631 \u067e\u0631\u060c \u0627\u06cc\u06a9 \u0686\u06cc\u0679 \u0627\u0633\u0633\u0679\u0646\u0679 \u06a9\u0648 \u0633\u067e\u0648\u0631\u0679 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 Claude \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba \u062c\u0648 \u0627\u0646 \u062a\u06be\u0631\u06cc\u0688\u0632 \u06a9\u0648 \u0633\u0627\u062f\u06c1 \u0632\u0628\u0627\u0646 \u0645\u06cc\u06ba \u0644\u06cc\u0628\u0644 \u06a9\u0631 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u060c \u0645\u062e\u0635\u0648\u0635 \u0627\u06af\u0644\u06d2 \u0627\u0642\u062f\u0627\u0645\u0627\u062a \u062a\u062c\u0648\u06cc\u0632 \u06a9\u0631 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u067e\u0648\u0686\u06be\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 &quot;\u0645\u062c\u06be\u06d2 \u0627\u0633 \u06c1\u0641\u062a\u06d2 \u06a9\u06cc\u0627 \u0628\u0646\u062f \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u061f&#8221;<\/p>\n<p>\u0622\u062e\u0631 \u0645\u06cc\u06ba\u060c \u0622\u067e \u0645\u0646\u062f\u0631\u062c\u06c1 \u0630\u06cc\u0644 \u0628\u0646\u0627\u0626\u06cc\u06ba \u06af\u06d2:<\/p>\n<ul>\n<li>\n<p>\u0645\u06cc\u0646\u06cc \u0641\u06cc\u0633\u0679 V3 \u06a9\u0631\u0648\u0645 \u0627\u06cc\u06a9\u0633\u0679\u06cc\u0646\u0634\u0646 \u0633\u0631\u0648\u0633 \u0648\u0631\u06a9\u0631 \u0627\u0648\u0631 \u0645\u06a9\u0645\u0644 \u0679\u06cc\u0628 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u06a9\u06d2 \u0633\u0627\u062a\u06be<\/p>\n<\/li>\n<li>\n<p>\u0627\u06cc\u06a9 \u0645\u0642\u0627\u0645\u06cc \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u062c\u0648 IndexedDB \u0645\u06cc\u06ba \u0646\u06cc\u0648\u06cc\u06af\u06cc\u0634\u0646 \u06c1\u0633\u0679\u0631\u06cc \u06a9\u0648 \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u06a9\u06cc\u067e\u0686\u0631 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u060c \u0635\u0627\u0641 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u060c \u067e\u0627\u0631\u0679\u06cc\u0634\u0646\u0632 \u0627\u0648\u0631 \u06a9\u0644\u0633\u0679\u0631\u0632 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u0635\u0644\u06cc (\u067e\u06cc\u0686\u06cc\u062f\u06c1) \u062a\u0644\u0627\u0634 \u06a9\u06d2 \u0688\u06cc\u0679\u0627 \u067e\u0631 \u06a9\u0644\u0633\u0679\u0631\u0646\u06af \u0627\u0644\u06af\u0648\u0631\u062a\u06be\u0645 \u0679\u06cc\u0648\u0646 \u0627\u0648\u0631 \u0688\u06cc\u0628\u06af \u06a9\u06cc\u0627 \u06af\u06cc\u0627\u06d4<\/p>\n<\/li>\n<li>\n<p>\u06a9\u0644\u0627\u0688 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 AI \u0644\u06cc\u0628\u0644\u0646\u06af \u067e\u0631\u062a\u060c context.dev \u0633\u06d2 \u0628\u0631\u0627\u0646\u0688 \u0688\u06cc\u0679\u0627 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0627\u06cc\u06a9 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0642\u062f\u0645 \u06a9\u06d2 \u0633\u0627\u062a\u06be<\/p>\n<\/li>\n<li>\n<p>\u0627\u06cc\u06a9 \u0686\u06cc\u0679 \u0627\u0633\u0633\u0679\u0646\u0679 \u062c\u0648 \u067e\u0648\u0631\u06d2 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u0627 \u0627\u0646\u062f\u0627\u0632\u06c1 \u0644\u06af\u0627\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0622\u067e \u06a9\u0648 \u0628\u062a\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0622\u06af\u06d2 \u06a9\u06cc\u0627 \u06a9\u0631\u0646\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0622\u0646 \u0628\u0648\u0631\u0688\u0646\u06af\u060c \u0688\u06cc\u0632\u0627\u0626\u0646 \u0633\u0633\u0679\u0645\u060c \u0627\u0648\u0631 \u0648\u0631\u06a9\u0646\u06af \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0627\u0633\u0679\u06cc\u0679\u0633 \u0633\u0633\u0679\u0645 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0686\u06cc\u06a9\u0646\u0627 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688<\/p>\n<\/li>\n<\/ul>\n<p>\u06c1\u0631 \u0686\u06cc\u0632 \u0688\u06cc\u0648\u0627\u0626\u0633 \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u0686\u0644\u062a\u06cc \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0635\u0631\u0641 \u0646\u06cc\u0679 \u0648\u0631\u06a9 \u06a9\u0627\u0644\u0632 \u0627\u062e\u062a\u06cc\u0627\u0631\u06cc \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0622\u067e \u06a9\u06cc \u0627\u067e\u0646\u06cc API \u06a9\u06cc\u0632 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u06a9\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<h2 id=\"heading-table-of-contents\">\u0627\u0646\u0688\u06cc\u06a9\u0633<\/h2>\n<h2 id=\"heading-what-youll-build\">\u06a9\u06cc\u0627 \u062a\u0639\u0645\u06cc\u0631 \u06a9\u0631\u0646\u0627 \u06c1\u06d2<\/h2>\n<p>\u067e\u06c1\u0644\u06cc \u0628\u0627\u0631\u060c \u0627\u0648\u067e\u0646 \u0644\u0648\u067e\u0633 \u0622\u067e \u06a9\u0648 \u0627\u06cc\u06a9 \u0645\u0631\u06a9\u0632\u06cc \u0648\u06cc\u0644\u06a9\u0645 \u0627\u0633\u06a9\u0631\u06cc\u0646 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062e\u0648\u0634 \u0622\u0645\u062f\u06cc\u062f \u06a9\u06c1\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u06d2 \u062a\u06cc\u0646 \u0645\u0631\u0627\u062d\u0644 \u0645\u06cc\u06ba \u0622\u067e \u06a9\u06cc \u0631\u06c1\u0646\u0645\u0627\u0626\u06cc \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u062a\u0627\u0631\u06cc\u062e \u06a9\u0648 \u0627\u0633\u06a9\u06cc\u0646 \u06a9\u0631\u0646\u06d2\u060c \u0633\u06cc\u0634\u0646 \u0628\u0646\u0627\u0646\u06d2\u060c \u0627\u0648\u0631 \u0627\u0631\u0627\u062f\u06d2 \u06a9\u0627 \u0646\u0642\u0634\u06c1 \u0628\u0646\u0627\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f\u060c \u0646\u06cc\u0648\u06cc\u06af\u06cc\u0634\u0646 \u06a9\u0648 \u0631\u06cc\u0627\u0633\u062a\u06cc \u06af\u0631\u0648\u067e \u062a\u06be\u0631\u06cc\u0688\u0632 (\u0641\u0639\u0627\u0644\u060c \u0631\u0648\u06a9\u0627\u060c \u0627\u0648\u0631 \u0646\u06cc\u0646\u062f) \u0645\u06cc\u06ba \u062f\u0648\u0628\u0627\u0631\u06c1 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u06c1\u0631 \u0622\u0626\u0679\u0645 \u0645\u06cc\u06ba \u0627\u0639\u062a\u0645\u0627\u062f \u06a9\u0627 \u0633\u06a9\u0648\u0631\u060c \u0633\u0627\u062f\u06c1 \u0632\u0628\u0627\u0646 \u06a9\u0627 \u062e\u0644\u0627\u0635\u06c1\u060c \u0645\u062e\u0635\u0648\u0635 \u0627\u06af\u0644\u06d2 \u0627\u0642\u062f\u0627\u0645\u0627\u062a\u060c \u0627\u0648\u0631 \u0634\u0627\u0645\u0644 \u06c1\u06cc\u06ba\u06d4 <strong>\u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06a9\u0631\u06cc\u06ba<\/strong> \u06cc\u06c1 \u0628\u0679\u0646 \u0648\u06c1\u06cc \u0635\u0641\u062d\u06c1 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u06be\u0648\u0644\u062a\u0627 \u06c1\u06d2 \u062c\u0633\u06d2 \u0622\u067e \u0646\u06d2 \u0686\u06be\u0648\u0691\u0627 \u062a\u06be\u0627\u06d4 \u062f\u0627\u0626\u06cc\u06ba \u06a9\u0627\u0644\u0645 \u0645\u06cc\u06ba \u0622\u067e \u06a9\u06d2 \u0627\u067e\u0646\u06d2 \u062a\u06be\u0631\u06cc\u0688 \u067e\u0631 \u0645\u0628\u0646\u06cc \u0686\u06cc\u0679 \u0627\u0633\u0633\u0679\u0646\u0679\u0633 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/umang.pk\/wp-content\/uploads\/2026\/06\/1781957220_833_\u0627\u06d2-\u0622\u0626\u06cc-\u0633\u06d2-\u0686\u0644\u0646\u06d2-\u0648\u0627\u0644\u06cc-\u0644\u0648\u06a9\u0644-\u0641\u0631\u0633\u0679-\u06a9\u0631\u0648\u0645-\u0627\u06cc\u06a9\u0633\u0679\u06cc\u0646\u0634\u0646-\u06a9\u0648.png\" alt=\"\u0627\u0648\u067e\u0646 \u0644\u0648\u067e\u0633 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u0628\u0627\u0626\u06cc\u06ba \u0637\u0631\u0641 \u0627\u0633\u0679\u06cc\u0679\u0633 \u06af\u0631\u0648\u067e \u0627\u0646\u0679\u06cc\u0646\u0679 \u062a\u06be\u0631\u06cc\u0688\u0632 \u062f\u06a9\u06be\u0627 \u0631\u06c1\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u062f\u0627\u0626\u06cc\u06ba \u0637\u0631\u0641 AI \u06a9\u06cc \u0645\u062f\u062f \u0633\u06d2 \u0686\u06cc\u0679 \u0627\u0633 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u0627\u0633\u062a\u062f\u0644\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u06c1 \u0627\u0633 \u06c1\u0641\u062a\u06d2 \u06a9\u0648\u0646 \u0633\u06d2 \u0622\u0626\u0679\u0645\u0632 \u0648\u0627\u062c\u0628 \u0627\u0644\u0627\u062f\u0627 \u06c1\u06cc\u06ba\u06d4\" style=\"display:block;margin:0 auto\" width=\"3456\" height=\"2164\" loading=\"lazy\" title=\"\"><\/p>\n<p>\u0648\u06c1 \u0645\u0639\u0627\u0648\u0646 \u062c\u0648\u0627\u0628\u0627\u062a \u0635\u0627\u0631\u0641 \u06a9\u06d2 \u062d\u0642\u06cc\u0642\u06cc \u062f\u06be\u0627\u06af\u0648\u06ba \u0645\u06cc\u06ba \u0627\u06cc\u06a9\u0633\u0679\u0631\u0627\u067e\u0648\u0644\u06cc\u0679 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0646 \u06a9\u06cc \u062f\u0631\u062c\u06c1 \u0628\u0646\u062f\u06cc \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u0686\u06be\u0648\u0691\u0646\u0627 \u06a9\u062a\u0646\u0627 \u0622\u0633\u0627\u0646 \u06c1\u06d2 \u0628\u0645\u0642\u0627\u0628\u0644\u06c1 \u0627\u0635\u0644 \u0641\u06cc\u0635\u0644\u0648\u06ba \u06a9\u06cc \u06a9\u062a\u0646\u06cc \u0645\u0642\u062f\u0627\u0631 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0627\u0633 \u0628\u0627\u062a \u06a9\u06cc \u0628\u06be\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u06cc\u06c1 \u0627\u0633 \u062a\u0639\u0645\u06cc\u0631 \u06a9\u0627 \u0633\u0628 \u0633\u06d2 \u0646\u06cc\u0627 \u062d\u0635\u06c1 \u06a9\u06cc\u0648\u06ba \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0633 \u06a9\u0627 \u0627\u0646\u062d\u0635\u0627\u0631 context.dev \u06a9\u06d2 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0627\u0642\u062f\u0627\u0645\u0627\u062a \u067e\u0631 \u06c1\u06d2 \u062c\u0646\u06c1\u06cc\u06ba \u06c1\u0645 \u0628\u0639\u062f \u0645\u06cc\u06ba \u0627\u0633 \u0679\u06cc\u0648\u0679\u0648\u0631\u06cc\u0644 \u0645\u06cc\u06ba \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba \u06af\u06d2\u06d4<\/p>\n<h2 id=\"heading-prerequisites\">\u0634\u0631\u0637\u06cc\u06ba<\/h2>\n<p>\u067e\u06cc\u0631\u0648\u06cc \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0622\u067e \u06a9\u0648 \u0636\u0631\u0648\u0631\u062a \u06c1\u0648 \u06af\u06cc:<\/p>\n<ul>\n<li>\n<p><strong>\u0646\u0648\u0688 18+<\/strong> \u06a9\u0631\u0648\u0645\u06cc\u0645 \u067e\u0631 \u0645\u0628\u0646\u06cc \u0628\u0631\u0627\u0624\u0632\u0631\u0632 (\u06a9\u0631\u0648\u0645\u060c \u0628\u06c1\u0627\u062f\u0631\u060c \u0627\u06cc\u062c\u060c \u0648\u063a\u06cc\u0631\u06c1)\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0622\u0631\u0627\u0645 <strong>\u0679\u0627\u0626\u067e \u0627\u0633\u06a9\u0631\u067e\u0679<\/strong> \u0627\u0648\u0631 <strong>\u0631\u062f \u0639\u0645\u0644<\/strong>. \u0622\u067e \u06a9\u0648 \u0645\u0627\u06c1\u0631 \u0628\u0646\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u0622\u067e \u06a9\u0648 Hooks \u0627\u0648\u0631 async\/await \u067e\u0691\u06be\u0646\u06d2 \u0645\u06cc\u06ba \u0645\u06c1\u0627\u0631\u062a \u062d\u0627\u0635\u0644 \u06a9\u0631\u0646\u06cc \u0686\u0627\u06c1\u06cc\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0628\u0646\u06cc\u0627\u062f\u06cc \u0639\u0644\u0645 <strong>\u0627\u0646\u0688\u06cc\u06a9\u0633\u0688 \u0688\u06cc \u0628\u06cc<\/strong> \u06cc\u06c1 \u0645\u062f\u062f\u06af\u0627\u0631 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u0636\u0631\u0648\u0631\u06cc \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u062c\u0628 \u0622\u067e \u0622\u06af\u06d2 \u0628\u0691\u06be\u062a\u06d2 \u06c1\u06cc\u06ba \u062a\u0648 \u0622\u067e \u0633\u06cc\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u0622\u067e \u06a9\u0648 \u06a9\u06cc\u0627 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<p>\u0627\u0633 \u062a\u0639\u0645\u06cc\u0631 \u06a9\u06d2 \u062f\u0648\u0646\u0648\u06ba \u062d\u0635\u06d2 \u0627\u062e\u062a\u06cc\u0627\u0631\u06cc \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u06c1\u0631 \u0627\u06cc\u06a9 \u06a9\u0648 \u0645\u0641\u062a \u062f\u0631\u062c\u06d2 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u067e\u0646\u06cc API \u06a9\u0644\u06cc\u062f \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<ul>\n<li>\n<p>\u0646\u06c1\u06cc\u06ba <strong>\u06c1\u06cc\u0648\u0645\u06cc\u0646\u0679\u06cc API \u06a9\u0644\u06cc\u062f<\/strong> (platform.claude.com \u067e\u0631) AI \u0644\u06cc\u0628\u0644\u0646\u06af \u0627\u0648\u0631 \u0686\u06cc\u0679 \u0627\u0633\u0633\u0679\u0646\u0679\u0633 \u06a9\u06d2 \u0644\u06cc\u06d2<\/p>\n<\/li>\n<li>\n<p>\u06a9\u0648\u0626\u06cc \u0631\u0627\u0633\u062a\u06c1 \u0646\u06c1\u06cc\u06ba <strong>context.dev API \u06a9\u0644\u06cc\u062f<\/strong> (context.dev \u0633\u06d2) \u0628\u0631\u0627\u0646\u0688 \u0641\u0627\u0624\u0646\u0688\u06cc\u0634\u0646 \u0628\u0646\u0627\u0646\u06d2 \u06a9\u06d2 \u0627\u0642\u062f\u0627\u0645\u0627\u062a<\/p>\n<\/li>\n<\/ul>\n<p>\u0686\u0648\u0646\u06a9\u06c1 \u062f\u0648\u0646\u0648\u06ba \u06a9\u06cc\u0632 \u0627\u0646 \u06a9\u06d2 \u0627\u0648\u067e\u0631 \u0627\u06cc\u06a9 \u0627\u0636\u0627\u0641\u06cc \u067e\u0631\u062a \u06c1\u06cc\u06ba\u060c \u0622\u067e \u0627\u0646 \u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u067e\u0648\u0631\u06cc \u0628\u0646\u06cc\u0627\u062f\u06cc \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646\u060c \u06a9\u06cc\u067e\u0686\u0631\u060c \u06a9\u0644\u0633\u0679\u0631\u0646\u06af \u0627\u0648\u0631 \u0627\u0633\u06a9\u0648\u0631\u0646\u06af \u0628\u0646\u0627 \u0627\u0648\u0631 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h2 id=\"heading-how-openloops-is-structured\">\u0627\u0648\u067e\u0646 \u0644\u0648\u067e\u0633 \u06a9\u06cc \u0633\u0627\u062e\u062a<\/h2>\n<p>\u06a9\u0648\u0688 \u0644\u06a9\u06be\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0645\u062c\u0645\u0648\u0639\u06cc \u0634\u06a9\u0644 \u06a9\u0648 \u062f\u06cc\u06a9\u06be\u0646\u0627 \u0645\u0641\u06cc\u062f \u06c1\u06d2\u06d4 \u0627\u0648\u067e\u0646 \u0644\u0648\u067e\u0633 \u0645\u06cc\u06ba \u06c1\u0631 \u0642\u062f\u0645 \u0627\u06cc\u06a9 IndexedDB \u0627\u0633\u0679\u0648\u0631 \u0633\u06d2 \u067e\u0691\u06be\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u06af\u0644\u06d2 \u06a9\u0648 \u0644\u06a9\u06be\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-plaintext\">chrome.history (backfill) \u2500\u2500\u2510\nchrome.tabs.onUpdated (live)\u2500\u2534\u2500\u2192 raw_events\n                                     \u2502  noise filter\n                                     \u25bc\n                                  sessions\n                                     \u2502  ambient detection + clustering + scoring\n                                     \u25bc\n                               intent_threads\n                                     \u2502\n                                     \u25bc\n                              React dashboard\n                                     \u2502  optional, opt-in\n                                     \u251c\u2500\u2500\u2192 brand enrichment   (context.dev)\n                                     \u2514\u2500\u2500\u2192 AI labeling + next step (Claude)\n                                              \u2502\n                                              \u25bc  optional, opt-in\n                                        AI assistant chat (Claude)\n<\/code><\/pre>\n<p>\u06c1\u0631 \u0642\u062f\u0645 \u0630\u06cc\u0644 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0627\u0644\u06af \u0645\u0627\u0688\u06cc\u0648\u0644 \u06c1\u06d2\u06d4 <code>src\/pipeline\/<\/code>\u06c1\u0631 \u0627\u06cc\u06a9 \u06a9\u0648 \u0622\u0632\u0627\u062f\u0627\u0646\u06c1 \u0637\u0648\u0631 \u067e\u0631 \u062c\u0627\u0646\u0686\u0627 \u062c\u0627 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 Chrome DevTools \u06a9\u06be\u0648\u0644\u06cc\u06ba \u0627\u0648\u0631 \u062f\u0631\u062c \u0630\u06cc\u0644 \u06a9\u0648 \u062f\u06cc\u06a9\u06be\u06cc\u06ba: <code>raw_events<\/code>, <code>sessions<\/code>\u06cc\u0627 <code>intent_threads<\/code> \u0622\u067e \u0627\u06cc\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646 \u0679\u06cc\u0628 \u0633\u06d2 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u06a9\u0633\u06cc \u062f\u0648\u0633\u0631\u06d2 \u0642\u062f\u0645 \u06a9\u0648 \u0686\u06be\u0648\u0626\u06d2 \u0628\u063a\u06cc\u0631 \u0627\u06cc\u06a9 \u0642\u062f\u0645 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0628\u0646\u0627 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-the-shared-types\">\u0634\u06cc\u0626\u0631 \u06a9\u06cc \u0642\u0633\u0645<\/h3>\n<p>\u062a\u0645\u0627\u0645 \u0645\u0631\u0627\u062d\u0644 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u06c1\u06cc \u0628\u0627\u0631 \u0628\u06cc\u0627\u0646 \u06a9\u0631\u062f\u06c1 TypeScript \u0627\u0646\u0679\u0631\u0641\u06cc\u0633 \u06a9\u06cc \u0627\u06cc\u06a9 \u06c1\u06cc \u0686\u06be\u0648\u0679\u06cc \u062a\u0639\u062f\u0627\u062f \u062a\u06cc\u0627\u0631 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>src\/types.ts<\/code>:<\/p>\n<pre><code class=\"language-typescript\">\/\/ Shared TypeScript interfaces for the openloops pipeline.\n\/\/ Each stage of the pipeline consumes and produces these types.\n\nexport interface RawEvent {\n  id: string;\n  url: string;\n  domain: string;\n  title: string;\n  visitedAt: number;         \/\/ epoch ms\n  source: \"backfill\" | \"live\";\n}\n\nexport interface Session {\n  id: string;\n  events: RawEvent[];\n  startedAt: number;\n  endedAt: number;\n  domains: string[];\n  keywords: string[];\n}\n\nexport interface IntentThread {\n  id: string;\n  title: string;\n  summary?: string;\n  nextStep?: string;   \/\/ one concrete action to move the thread forward\n  sessions: Session[];\n  type: \"buying\" | \"research\" | \"planning\" | \"learning\" | \"unclassified\";\n  confidence: number;        \/\/ 0-1\n  status: \"active\" | \"stalled\" | \"dormant\";\n  firstSeen: number;\n  lastSeen: number;\n  distinctDays: number;\n  signals: string[];\n}\n\nexport interface Brand {\n  domain: string;\n  name: string;\n  description: string;\n  industry: string;\n  logoUrl: string;\n  brandColor: string;\n}\n<\/code><\/pre>\n<p>\u0632\u06cc\u0627\u062f\u06c1 \u062a\u0631 \u0641\u06cc\u0644\u0688\u0632 <code>IntentThread<\/code>, <code>confidence<\/code>, <code>status<\/code>, <code>signals<\/code>\u0627\u0648\u0631 <code>distinctDays<\/code> \u06c1\u0645 \u0628\u0639\u062f \u0645\u06cc\u06ba \u0627\u0633 \u06af\u0627\u0626\u06cc\u0688 \u0645\u06cc\u06ba \u062f\u06be\u0627\u06af\u0648\u06ba \u06a9\u0648 \u06a9\u0644\u0633\u0679\u0631\u0646\u06af \u0627\u0648\u0631 \u0627\u0633\u06a9\u0648\u0631 \u06a9\u0631\u062a\u06d2 \u0648\u0642\u062a \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u0645\u0642\u0627\u0645\u06cc \u06c1\u06cc\u0648\u0631\u0633\u0679\u06a9\u0633 \u06a9\u0648 \u0628\u06be\u0631\u06cc\u06ba \u06af\u06d2\u06d4 <code>summary<\/code> \u0627\u0648\u0631 <code>nextStep<\/code> \u0631\u06c1\u0646\u0627 <code>undefined<\/code> \u062c\u0628 \u062a\u06a9 \u06a9\u06c1 \u0622\u067e \u0627\u0633\u06d2 \u0628\u0639\u062f \u0645\u06cc\u06ba \u0634\u0627\u0645\u0644 \u0627\u062e\u062a\u06cc\u0627\u0631\u06cc AI \u0644\u06cc\u0628\u0644\u0646\u06af \u0645\u0631\u062d\u0644\u06d2 \u0645\u06cc\u06ba \u0622\u0628\u0627\u062f \u0646\u06c1 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<p>\u06cc\u06c1 \u0648\u06c1 \u0646\u0645\u0648\u0646\u06c1 \u06c1\u06d2 \u062c\u0648 \u067e\u0648\u0631\u06d2 \u067e\u0631\u0648\u062c\u06cc\u06a9\u0679 \u06a9\u0648 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0688\u06cc\u0679\u0627 \u0645\u0627\u0688\u0644 \u0627\u067e\u0646\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 AI \u0627\u0633\u06d2 \u0627\u0641\u0632\u0648\u062f\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-the-manifest\">\u0638\u0627\u06c1\u0631<\/h3>\n<p>\u0627\u0648\u067e\u0646 \u0644\u0648\u067e\u0633 \u0627\u06cc\u06a9 \u0645\u06cc\u0646\u06cc \u0641\u06cc\u0633\u0679 V3 \u0627\u06cc\u06a9\u0633\u0679\u06cc\u0646\u0634\u0646 \u06c1\u06d2 \u062c\u0633 \u0645\u06cc\u06ba \u062a\u06cc\u0646 \u0627\u062c\u0627\u0632\u062a\u06cc\u06ba \u0627\u0648\u0631 \u062a\u06cc\u0646 \u0645\u06cc\u0632\u0628\u0627\u0646 \u0627\u062c\u0627\u0632\u062a\u06cc\u06ba \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-json\">{\n  \"manifest_version\": 3,\n  \"name\": \"openloops\",\n  \"version\": \"0.0.1\",\n  \"description\": \"Reconstruct your browsing history into an AI-labeled map of intent threads: active decisions, stalled research, open questions. Fully local.\",\n\n  \"permissions\": [\"history\", \"tabs\", \"storage\"],\n  \"host_permissions\": [\n    \"https:\/\/api.anthropic.com\/*\",\n    \"https:\/\/api.context.dev\/*\",\n    \"https:\/\/logos.context.dev\/*\"\n  ],\n\n  \"background\": {\n    \"service_worker\": \"src\/background.ts\",\n    \"type\": \"module\"\n  },\n\n  \"options_page\": \"src\/dashboard\/index.html\",\n\n  \"icons\": {\n    \"16\": \"icons\/icon16.png\",\n    \"32\": \"icons\/icon32.png\",\n    \"48\": \"icons\/icon48.png\",\n    \"128\": \"icons\/icon128.png\"\n  },\n\n  \"action\": {\n    \"default_title\": \"openloops\",\n    \"default_icon\": {\n      \"16\": \"icons\/icon16.png\",\n      \"32\": \"icons\/icon32.png\"\n    }\n  }\n}\n<\/code><\/pre>\n<p>\u0627\u062c\u0627\u0632\u062a\u06cc\u06ba\u060c \u0645\u06cc\u0632\u0628\u0627\u0646\u06cc \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a\u060c \u0627\u0648\u0631 <code>options_page<\/code> \u06c1\u0631 \u0634\u06d2 \u06a9\u0627 \u0627\u06cc\u06a9 \u062e\u0627\u0635 \u0648\u0632\u0646 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<ul>\n<li>\n<p><code>permissions: [\"history\", \"tabs\", \"storage\"]<\/code>    \u0635\u0631\u0641 \u0627\u062e\u062a\u06cc\u0627\u0631 \u06c1\u06d2\u06d4 <em>\u0628\u0646\u06cc\u0627\u062f\u06cc \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646<\/em> \u0622\u067e \u06a9\u0648 \u0627\u0633 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4 <code>history<\/code> \u0628\u06cc\u06a9 \u0627\u067e \u0627\u0634\u062a\u06c1\u0627\u0631\u0627\u062a \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u067e\u0646\u06cc \u0628\u0631\u0627\u0624\u0632\u0646\u06af \u06c1\u0633\u0679\u0631\u06cc \u067e\u0691\u06be\u06cc\u06ba\u060c <code>tabs<\/code> \u0633\u0631\u0648\u0633 \u0648\u0631\u06a9\u0631 \u06a9\u0648 \u0635\u0641\u062d\u06c1 \u06a9\u06d2 \u0646\u0626\u06d2 \u0628\u0648\u062c\u06be \u06a9\u0627 \u0645\u0634\u0627\u06c1\u062f\u06c1 \u06a9\u0631\u0646\u06d2 \u0627\u0648\u0631 &#8216;\u0631\u06cc\u0632\u06cc\u0648\u0645\u06d2&#8217; \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0679\u06cc\u0628\u0632 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u06be\u0648\u0644\u0646\u06d2 \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 <code>storage<\/code> \u06cc\u06c1 \u0648\u06c1 \u062c\u06af\u06c1 \u06c1\u06d2 \u062c\u06c1\u0627\u06ba \u0622\u067e \u06a9\u06cc API \u06a9\u06cc\u0632 \u0627\u0648\u0631 \u062a\u0631\u062c\u06cc\u062d\u0627\u062a \u0648\u0627\u0642\u0639 \u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p><code>host_permissions<\/code>    \u0627\u06af\u0631 \u0622\u067e \u0627\u062e\u062a\u06cc\u0627\u0631\u06cc AI \u062e\u0635\u0648\u0635\u06cc\u0627\u062a \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u062a\u0648 \u06cc\u06c1 \u0627\u0644\u06af \u0627\u0648\u0631 \u0635\u0631\u0641 \u0627\u06c1\u0645 \u06c1\u06d2\u06d4 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u06a9\u06cc\u0627 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>fetch()<\/code> CORS \u06a9\u06cc \u063a\u0644\u0637\u06cc\u0648\u06ba \u06a9\u06d2 \u0628\u063a\u06cc\u0631 Anthropic \u0627\u0648\u0631 context.dev \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p><code>options_page<\/code>    \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u06a9\u0648 \u067e\u0648\u0627\u0626\u0646\u0679\u0633 \u062f\u06cc\u06d2 \u06af\u0626\u06d2\u06d4 \u0627\u0633 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2\u060c \u0627\u0633\u06d2 \u0627\u0633 \u0637\u0631\u062d \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u06ba: <code>default_popup<\/code>\u0627\u0633 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2 \u06a9\u06c1 \u0679\u0648\u0644 \u0628\u0627\u0631 \u06a9\u06d2 \u0622\u0626\u06cc\u06a9\u0648\u0646 \u067e\u0631 \u06a9\u0644\u06a9 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u0627\u06cc\u06a9 \u0686\u06be\u0648\u0679\u06d2 \u067e\u0627\u067e \u0627\u067e \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0645\u06a9\u0645\u0644 \u0628\u0631\u0627\u0624\u0632\u0631 \u0679\u06cc\u0628 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u06a9\u06be\u0644 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4 \u0627\u0633\u0679\u06cc\u0679\u0633 \u06af\u0631\u0648\u067e \u06a9\u0627\u0631\u0688\u0632 \u0627\u0648\u0631 \u0686\u06cc\u0679 \u067e\u06cc\u0646\u0644\u0632 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0645\u0644\u0679\u06cc \u06a9\u0627\u0644\u0645 \u0644\u06d2 \u0622\u0624\u0679 \u06a9\u0648 \u062f\u06cc\u06a9\u06be\u062a\u06d2 \u0648\u0642\u062a \u06cc\u06c1 \u0627\u06c1\u0645 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<h2 id=\"heading-how-to-scaffold-the-extension\">\u0627\u06cc\u06a9\u0633\u0679\u06cc\u0646\u0634\u0646 \u06a9\u0648 \u0633\u06a9\u06cc\u0641\u0648\u0644\u0688 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0637\u0631\u06cc\u0642\u06c1<\/h2>\n<p>\u0648\u0627\u0626\u0679 \u0627\u0648\u0631 CRXJS \u067e\u0644\u06af \u0627\u0646 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0634\u0631\u0648\u0639 \u06a9\u0631\u06cc\u06ba \u062c\u0648 \u06c1\u0627\u0679 \u0645\u0627\u0688\u06cc\u0648\u0644 \u0631\u06cc \u0644\u0648\u0688\u0646\u06af \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0645\u06cc\u0646\u06cc \u0641\u06cc\u0633\u0679 V3 \u0627\u06cc\u06a9\u0633\u0679\u06cc\u0646\u0634\u0646 \u06a9\u0648 \u0645\u0631\u062a\u0628 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-bash\">npm create vite@latest openloops -- --template react-ts\ncd openloops\nnpm install @crxjs\/vite-plugin idb react-markdown\n<\/code><\/pre>\n<p>\u0622\u067e \u06a9\u0627 <code>vite.config.ts<\/code> CRXJS \u0622\u067e \u06a9\u0627 <code>manifest.json<\/code>\u0627\u0648\u0631 \u0648\u06c1\u0627\u06ba \u0633\u06d2\u060c \u0648\u0627\u0626\u0679 \u062a\u0627\u0644\u06cc\u0641 \u06a9\u0648 \u0633\u0646\u0628\u06be\u0627\u0644\u062a\u0627 \u06c1\u06d2\u06d4 <code>src\/background.ts<\/code> \u0648\u0627\u0642\u0639\u06cc <code>.js<\/code> \u0648\u06c1 \u0641\u0627\u0626\u0644\u06cc\u06ba \u062c\u0646\u06c1\u06cc\u06ba \u06a9\u0631\u0648\u0645 \u0644\u0648\u0688 \u06a9\u0631 \u0633\u06a9\u062a\u0627 \u06c1\u06d2 (\u06a9\u0686\u06cc \u0641\u0627\u0626\u0644\u06cc\u06ba) <code>.ts<\/code> \u0645\u06cc\u0646\u06cc \u0641\u06cc\u0633\u0679 \u0645\u06cc\u06ba \u0633\u0631\u0648\u0633 \u0648\u0631\u06a9\u0631 \u0631\u0648\u0679 \u0631\u062c\u0633\u0679\u0631\u06cc\u0634\u0646 \u06a9\u06cc \u062e\u0631\u0627\u0628\u06cc \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u06c1\u0645 \u0627\u0633\u06d2 \u0627\u06af\u0644\u06d2 \u062d\u0635\u06d2 \u0645\u06cc\u06ba \u0688\u06cc\u0628\u06af \u06a9\u0631\u06cc\u06ba \u06af\u06d2\u06d4<\/p>\n<p>\u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u06a9\u0627 \u0627\u0646\u0679\u0631\u06cc \u067e\u0648\u0627\u0626\u0646\u0679 \u0627\u06cc\u06a9 \u0645\u0639\u06cc\u0627\u0631\u06cc React 18 \u0631\u0648\u0679 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-html\">\n\n  \n    <meta charset=\"UTF-8\"\/>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\/>\n    <title>openloops<\/title>\n  \n  \n    \n    <script type=\"module\" src=\"https:\/\/www.freecodecamp.org\/news\/how-to-build-an-ai-powered-local-first-chrome-extension\/.\/main.tsx\"\/>\n  \n\n<\/code><\/pre>\n<pre><code class=\"language-typescriptreact\">import { StrictMode } from \"react\";\nimport { createRoot } from \"react-dom\/client\";\nimport \".\/app.css\";\nimport App from \".\/App\";\n\ncreateRoot(document.getElementById(\"root\")!).render(\n  <strictmode>\n    <app\/>\n  <\/strictmode>\n);\n<\/code><\/pre>\n<p>\u0627\u0633\u06d2 \u0628\u0646\u0627\u0626\u06cc\u06ba \u0627\u0648\u0631 \u067e\u06be\u0631 \u0627\u0633\u06d2 \u0628\u063a\u06cc\u0631 \u0632\u067e \u0634\u062f\u06c1 \u0627\u06cc\u06a9\u0633\u0679\u06cc\u0646\u0634\u0646 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0644\u0648\u0688 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-bash\">npm run build\n<\/code><\/pre>\n<p>\u06a9\u0631\u0648\u0645 \u0645\u06cc\u06ba\u060c \u0627\u0633 \u067e\u0631 \u062c\u0627\u0626\u06cc\u06ba: <code>chrome:\/\/extensions<\/code>\u0641\u0639\u0627\u0644 \u06a9\u0631\u06cc\u06ba <strong>\u0688\u0648\u06cc\u0644\u067e\u0631 \u0645\u0648\u0688<\/strong>\u06a9\u0644\u06a9 \u06a9\u0631\u06cc\u06ba <strong>\u067e\u06cc\u06a9 \u06a9\u06be\u0648\u0644 \u062f\u06cc\u0627 \u0633\u0627\u0645\u0627\u0646<\/strong>\u0645\u0646\u062a\u062e\u0628 \u06a9\u0631\u06cc\u06ba <code>dist\/<\/code> \u0641\u0648\u0644\u0688\u0631 \u0627\u06af\u0631 \u0627\u0628\u06be\u06cc \u062a\u06a9 \u06a9\u0686\u06be \u0628\u06be\u06cc \u0646\u06c1\u06cc\u06ba \u0628\u0646\u0627\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0679\u0648\u0644 \u0628\u0627\u0631 \u06a9\u06d2 \u0622\u0626\u06cc\u06a9\u0648\u0646 \u067e\u0631 \u06a9\u0644\u06a9 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u0627\u06cc\u06a9 \u062e\u0627\u0644\u06cc \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u0679\u06cc\u0628 \u06a9\u06be\u0644 \u062c\u0627\u0626\u06d2 \u06af\u0627 \u0627\u0648\u0631 \u0633\u0631\u0648\u0633 \u0648\u0631\u06a9\u0631 (\u0627\u06cc\u06a9\u0633\u0679\u06cc\u0646\u0634\u0646 \u06a9\u0627\u0631\u0688 \u067e\u0631 \"\u0633\u0631\u0648\u0633 \u0648\u0631\u06a9\u0631\" \u06a9\u06d2 \u0644\u0646\u06a9 \u0645\u06cc\u06ba \u0646\u0638\u0631 \u0622\u062a\u0627 \u06c1\u06d2) \u0644\u0627\u06af \u0627\u0646 \u06c1\u0648\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u06d4 <code>[openloops] Extension installed.<\/code> \u0627\u0646\u0633\u0679\u0627\u0644 \u06a9\u0631\u0646\u0627\u06d4<\/p>\n<p>\u0627\u06cc\u06a9 \u0628\u0627\u0631 \u062c\u0628 \u0622\u067e \u06a9\u06d2 \u067e\u0627\u0633 \u0641\u0627\u0624\u0646\u0688\u06cc\u0634\u0646 \u06c1\u06d2\u060c \u06cc\u06c1 \u0628\u06be\u0631\u0646\u0627 \u0634\u0631\u0648\u0639 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0648\u0642\u062a \u06c1\u06d2. <code>raw_events<\/code> \u0622\u067e \u06a9\u06cc \u0627\u0635\u0644 \u0628\u0631\u0627\u0624\u0632\u0646\u06af \u06c1\u0633\u0679\u0631\u06cc \u06a9\u06d2 \u0633\u0627\u062a\u06be\u06d4<\/p>\n<h2 id=\"heading-how-to-capture-your-browsing-history\">\u0628\u0631\u0627\u0624\u0632\u0646\u06af \u06c1\u0633\u0679\u0631\u06cc \u06a9\u0648 \u06a9\u06cc\u0633\u06d2 \u06a9\u06cc\u067e\u0686\u0631 \u06a9\u0631\u06cc\u06ba\u06d4<\/h2>\n<p>\u0627\u0648\u067e\u0646 \u0644\u0648\u067e\u0633 \u0645\u06cc\u06ba \u06c1\u0631 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u0627\u0633 \u0637\u0631\u062d \u0634\u0631\u0648\u0639 \u06c1\u0648\u062a\u0627 \u06c1\u06d2: <code>RawEvent<\/code>\u0648\u06c1 \u0627\u0642\u0633\u0627\u0645 \u062c\u0648 \u06c1\u0645 \u0646\u06d2 \u067e\u06c1\u0644\u06d2 \u062f\u06cc\u06a9\u06be\u06cc \u062a\u06be\u06cc\u06ba: URL\u060c \u0688\u0648\u0645\u06cc\u0646\u060c \u0679\u0627\u0626\u0679\u0644\u060c \u0679\u0627\u0626\u0645 \u0627\u0633\u0679\u06cc\u0645\u067e\u060c \u0627\u0648\u0631 <code>source<\/code> \u06cc\u0627 \u062a\u0648 \u0627\u06cc\u06a9 <code>\"backfill\"<\/code> \u06cc\u0627 <code>\"live\"<\/code>.<\/p>\n<p>\u062f\u0648 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646\u06cc\u06ba \u0627\u0633\u06d2 \u0628\u06be\u0631\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<ul>\n<li>\n<p>\u06a9\u0648\u0626\u06cc \u0631\u0627\u0633\u062a\u06c1 \u0646\u06c1\u06cc\u06ba <strong>\u0627\u06cc\u06a9 \u0628\u0627\u0631 \u0628\u06cc\u06a9 \u0641\u0644<\/strong> \u067e\u0686\u06be\u0644\u06d2 14 \u062f\u0646 \u067e\u0691\u06be\u06cc\u06ba <code>chrome.history<\/code> \u0645\u0637\u0627\u0644\u0628\u06c1 \u067e\u0631<\/p>\n<\/li>\n<li>\n<p><strong>\u0632\u0646\u062f\u06c1 \u06af\u0631\u0641\u062a\u0627\u0631\u06cc<\/strong>\u0627\u0633 \u0645\u0642\u0627\u0645 \u0633\u06d2\u060c \u0635\u0641\u062d\u06c1 \u06a9\u06d2 \u0646\u0626\u06d2 \u0628\u0648\u062c\u06be \u0645\u0648\u0635\u0648\u0644 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<\/ul>\n<p>\u062f\u0648\u0646\u0648\u06ba \u0631\u0627\u0633\u062a\u06d2 \u0686\u0646\u062f \u0686\u06be\u0648\u0679\u06d2 \u0645\u062f\u062f\u06af\u0627\u0631\u0648\u06ba \u06a9\u0627 \u0627\u0634\u062a\u0631\u0627\u06a9 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u06c1\u06cc IndexedDB \u067e\u0631\u062a \u067e\u0631 \u0644\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0644\u06c1\u0630\u0627 \u06cc\u06c1 \u067e\u06c1\u0644\u06d2 \u0627\u0646 \u06a9\u06cc \u062a\u0639\u0645\u06cc\u0631 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-a-few-shared-helpers\">\u0686\u0646\u062f \u0634\u06cc\u0626\u0631\u0646\u06af \u0645\u062f\u062f\u06af\u0627\u0631<\/h3>\n<p>\u0628\u0646\u0627\u0646\u0627 <code>src\/lib\/util.ts<\/code>:<\/p>\n<pre><code class=\"language-typescript\">export function isHttpUrl(url: string): boolean {\n  return url.startsWith(\"http:\/\/\") || url.startsWith(\"https:\/\/\");\n}\n\nexport function extractDomain(url: string): string {\n  try {\n    const { hostname } = new URL(url);\n    return hostname.replace(\/^www.\/, \"\");\n  } catch {\n    return url;\n  }\n}\n\nexport function isLocalHost(domain: string): boolean {\n  if (domain === \"localhost\" || domain === \"127.0.0.1\") return true;\n  if (domain.endsWith(\".local\")) return true;\n\n  const octets = domain.split(\".\");\n  if (octets.length === 4 && octets.every((o) => \/^d{1,3}$\/.test(o))) {\n    const [a, b] = octets.map(Number);\n    if (a === 10) return true;\n    if (a === 172 && b >= 16 && b <= 31) return true;\n    if (a === 192 &#038;&#038; b === 168) return true;\n  }\n\n  return false;\n}\n\nexport function hashId(url: string, visitedAt: number): string {\n  const str = `({url}|){visitedAt}`;\n  let hash = 5381;\n  for (let i = 0; i < str.length; i++) {\n    hash = ((hash << 5) + hash) ^ str.charCodeAt(i);\n    hash |= 0;\n  }\n  return (hash >>> 0).toString(36);\n}\n<\/code><\/pre>\n<p>\u0627\u0646 \u0686\u0627\u0631 \u062e\u0635\u0648\u0635\u06cc\u0627\u062a \u0645\u06cc\u06ba \u0633\u06d2 \u06c1\u0631 \u0627\u06cc\u06a9 \u0627\u06cc\u0633\u06d2 \u0645\u0633\u0627\u0626\u0644 \u06a9\u0648 \u062d\u0644 \u06a9\u0631\u062a\u06cc \u06c1\u06d2 \u062c\u0648 \u0634\u0627\u06cc\u062f \u0628\u0639\u062f \u0645\u06cc\u06ba \u062a\u0639\u0645\u06cc\u0631 \u0645\u06cc\u06ba \u0645\u0639\u0644\u0648\u0645 \u0646\u06c1 \u06c1\u0648\u06ba\u06d4<\/p>\n<ul>\n<li>\n<p><code>isHttpUrl<\/code>    \u0644\u0627\u0626\u06cc\u0648 \u06a9\u06cc\u067e\u0686\u0631 \u0627\u0648\u0631 \u0628\u06cc\u06a9 \u0641\u0644 \u062f\u0648\u0646\u0648\u06ba \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06c1\u0648\u0646\u06d2 \u0648\u0627\u0644\u0627 \u0645\u0634\u062a\u0631\u06a9\u06c1 \u0627\u0633\u06a9\u06cc\u0645 \u06af\u0627\u0631\u0688\u060c \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u06af\u06cc\u0679 \u062c\u0648 \u0627\u0633\u06d2 \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u0631\u06a9\u06be\u062a\u0627 \u06c1\u06d2\u06d4 <code>chrome:\/\/<\/code>, <code>chrome-extension:\/\/<\/code>, <code>about:<\/code>\u0627\u0648\u0631 <code>file:\/\/<\/code> \u0622\u067e \u06a9\u06d2 \u0688\u06cc\u0679\u0627 \u0633\u06d2 URL \u06a9\u0648 \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u062d\u0630\u0641 \u06a9\u0631 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 \u062f\u0648\u0646\u0648\u06ba \u06a9\u06cc\u067e\u0686\u0631 \u0631\u0627\u0633\u062a\u06d2 \u0627\u0633\u06d2 \u062f\u0648\u0633\u0631\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u06a9\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p><code>extractDomain<\/code>    \u0646\u06cc\u06a9\u06cc\u0648\u06ba \u06a9\u0648 \u062f\u0648\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>www.<\/code> \u0622\u0633\u0627\u0646 \u0645\u06cc\u0632\u0628\u0627\u0646 \u0646\u0627\u0645 \u0644\u0648\u0679\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>bbc.co.uk<\/code> \u0627\u0648\u0631 <code>news.bbc.co.uk<\/code> \u0627\u0635\u0644 \u0631\u062c\u0633\u0679\u0631\u0688 \u0688\u0648\u0645\u06cc\u0646 \u0646\u06a9\u0627\u0644\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0639\u0648\u0627\u0645\u06cc \u0644\u0627\u062d\u0642\u0648\u06ba \u06a9\u06cc \u0641\u06c1\u0631\u0633\u062a \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u0648\u06c1 \u0627\u0633 \u0645\u0646\u0637\u0642 \u06a9\u06d2 \u0645\u0637\u0627\u0628\u0642 \u0627\u06cc\u06a9 \u062c\u06cc\u0633\u06d2 \u0688\u0648\u0645\u06cc\u0646\u0632 \u067e\u0631 \u0646\u06c1\u06cc\u06ba \u0679\u0648\u0679\u062a\u06d2\u06d4 \u0627\u06af\u0631 URL \u062e\u0631\u0627\u0628 \u06c1\u06d2\u060c \u062a\u0648 \u06cc\u06c1 \u0627\u0646 \u067e\u0679 \u067e\u06be\u06cc\u0646\u06a9\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0627\u0633\u06d2 \u0628\u063a\u06cc\u0631 \u062a\u0628\u062f\u06cc\u0644\u06cc \u06a9\u06d2 \u0644\u0648\u0679\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p><code>isLocalHost<\/code>    \u06cc\u06c1 \u0627\u06cc\u06a9 \u0648\u062c\u06c1 \u0633\u06d2 \u0645\u0648\u062c\u0648\u062f \u06c1\u06d2\u06d4 \u062c\u0628 \u0622\u067e \u0628\u0639\u062f \u0645\u06cc\u06ba \u0627\u0633 \u06af\u0627\u0626\u06cc\u0688 \u0645\u06cc\u06ba \u0628\u0631\u0627\u0646\u0688 \u0645\u06cc\u06ba \u0627\u0636\u0627\u0641\u06c1 \u06a9\u0631\u06cc\u06ba \u06af\u06d2\u060c \u062a\u0648 \u0622\u067e \u0627\u067e\u0646\u06d2 \u0688\u0648\u0645\u06cc\u0646 \u06a9\u0627 \u0646\u0627\u0645 \u0627\u06cc\u06a9 \u0628\u06cc\u0631\u0648\u0646\u06cc API \u06a9\u0648 \u0628\u06be\u06cc\u062c\u06cc\u06ba \u06af\u06d2\u06d4 <code>localhost:5173<\/code> \u06cc\u0627 <code>192.168.1.50<\/code> \u06cc\u06c1 \u0627\u0633 API \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u0639\u0646\u06cc \u062e\u06cc\u0632 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 \u0627\u0648\u0631 \u06cc\u06c1 \u0635\u0631\u0641 \u0627\u06cc\u06a9 \u0636\u0627\u0626\u0639 \u0634\u062f\u06c1 \u062a\u0644\u0627\u0634 \u06c1\u0648\u06af\u06cc\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u0645\u06cc\u06ba \u0627\u0633\u06d2 \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u06cc\u06c1\u0627\u06ba \u0645\u0627\u062e\u0630 \u0645\u06cc\u06ba \u0641\u0644\u0679\u0631 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u062a\u062c\u0648\u06cc\u0632 \u06a9\u0631\u062a\u0627 \u06c1\u0648\u06ba\u06d4 \u06cc\u06c1 \u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1: <code>localhost<\/code>, <code>127.0.0.1<\/code>, <code>.local<\/code> \u0645\u06cc\u0632\u0628\u0627\u0646 \u0646\u0627\u0645 \u0627\u0648\u0631 \u0645\u0639\u06cc\u0627\u0631\u06cc \u0646\u062c\u06cc IPv4 \u0631\u06cc\u0646\u062c (<code>10.x.x.x<\/code>, <code>172.16.x.x<\/code>-<code>172.31.x.x<\/code>, <code>192.168.x.x<\/code>)\u06d4<\/p>\n<\/li>\n<li>\n<p><code>hashId<\/code>    \u06cc\u06c1 URL \u0627\u0648\u0631 \u0679\u0627\u0626\u0645 \u0627\u0633\u0679\u06cc\u0645\u067e \u06a9\u0648 \u0627\u06cc\u06a9 \u0645\u062e\u062a\u0635\u0631\u060c \u062a\u0639\u06cc\u06cc\u0646\u0627\u062a\u06cc \u0633\u0679\u0631\u0646\u06af \u0645\u06cc\u06ba \u062c\u0648\u0691\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0633\u0627\u062f\u06c1 \u06c1\u06cc\u0634\u0646\u06af \u0627\u0644\u06af\u0648\u0631\u062a\u06be\u0645 (djb2) \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>(url, visitedAt)<\/code> \u062c\u0648\u0691\u0627 \u06c1\u0645\u06cc\u0634\u06c1 \u0627\u06cc\u06a9 \u06c1\u06cc ID \u062a\u06cc\u0627\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0644\u06a9\u06be\u0646\u06d2 \u0648\u0627\u0644\u0648\u06ba \u06a9\u0648 \u06a9\u0645\u0632\u0648\u0631 \u0628\u0646\u0627 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u0639\u0646\u06cc\u060c \u0627\u06af\u0631 \u0622\u067e \u0628\u06cc\u06a9 \u0641\u0644 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0686\u0644\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c <em>\u0627\u06cc\u06a9 \u06c1\u06cc<\/em> ID <em>\u0627\u06cc\u06a9 \u06c1\u06cc<\/em> \u0686\u0648\u0646\u06a9\u06c1 \u0622\u067e IndexedDB \u0648\u0632\u0679 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>put<\/code> \"\u0645\u06cc\u0631\u06cc \u0633\u0631\u06af\u0632\u0634\u062a \u062a\u0644\u0627\u0634 \u06a9\u0631\u06cc\u06ba\" \u067e\u0631 \u0627\u06cc\u06a9 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0628\u0627\u0631 \u06a9\u0644\u06a9 \u06a9\u0631\u0646\u0627 \u0645\u062d\u0641\u0648\u0638 \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u06cc\u06c1 \u0646\u0642\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0635\u0627\u0641 \u0637\u0648\u0631 \u067e\u0631 \u0627\u0648\u0648\u0631 \u0631\u0627\u0626\u0679 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<h3 id=\"heading-the-database-layer-so-far\">\u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u067e\u0631\u062a (\u0627\u0628 \u062a\u06a9)<\/h3>\n<p>\u0627\u0648\u067e\u0646 \u0644\u0648\u067e\u0633 \u06c1\u0631 \u0686\u06cc\u0632 \u06a9\u0648 IndexedDB \u0645\u06cc\u06ba \u0627\u0633\u0679\u0648\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0628\u0630\u0631\u06cc\u0639\u06c1: <code>idb<\/code> \u0627\u06cc\u06a9 \u0631\u06cc\u067e\u0631 \u062c\u0648 \u062e\u0627\u0645 IndexedDB \u06a9\u0627\u0644\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u0679\u0627\u0626\u067e \u0634\u062f\u06c1 \u0648\u0639\u062f\u06d2 \u067e\u0631 \u0645\u0628\u0646\u06cc API \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0628\u0646\u0627\u0646\u0627 <code>src\/db\/index.ts<\/code>:<\/p>\n<pre><code class=\"language-typescript\">import { openDB, type DBSchema, type IDBPDatabase } from \"idb\";\nimport type { RawEvent } from \"..\/types\";\n\ninterface OpenloopsDB extends DBSchema {\n  raw_events: {\n    key: string;\n    value: RawEvent;\n    indexes: { by_visitedAt: number };\n  };\n}\n\nconst DB_NAME = \"openloops\";\nconst DB_VERSION = 1;\n\nlet _db: Promise<idbpdatabase>> | null = null;\n\nexport function getDB(): Promise<idbpdatabase>> {\n  if (!_db) {\n    _db = openDB<openloopsdb>(DB_NAME, DB_VERSION, {\n      upgrade(db) {\n        if (!db.objectStoreNames.contains(\"raw_events\")) {\n          const s = db.createObjectStore(\"raw_events\", { keyPath: \"id\" });\n          s.createIndex(\"by_visitedAt\", \"visitedAt\");\n        }\n      },\n    });\n  }\n  return _db;\n}\n\nexport async function clearEvents(): Promise<void> {\n  const db = await getDB();\n  return db.clear(\"raw_events\");\n}\n\nexport async function putEvents(events: RawEvent[]): Promise<void> {\n  if (events.length === 0) return;\n  const db = await getDB();\n  const tx = db.transaction(\"raw_events\", \"readwrite\");\n  await Promise.all([...events.map((e) => tx.store.put(e)), tx.done]);\n}\n\nexport async function getAllEvents(): Promise<rawevent> {\n  const db = await getDB();\n  return db.getAllFromIndex(\"raw_events\", \"by_visitedAt\");\n}\n\nexport async function getEventCount(): Promise<number> {\n  const db = await getDB();\n  return db.count(\"raw_events\");\n}\n<\/number><\/rawevent><\/void><\/void><\/openloopsdb><\/idbpdatabase><\/idbpdatabase><\/code><\/pre>\n<p>\u0686\u0627\u0631 \u0686\u06be\u0648\u0679\u06cc \u062e\u0635\u0648\u0635\u06cc\u0627\u062a \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u067e\u0631\u062a \u06a9\u06d2 \u067e\u06c1\u0644\u06d2 \u0648\u0631\u0698\u0646 \u06a9\u0648 \u0645\u06a9\u0645\u0644 \u06a9\u0631\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 <code>clearEvents<\/code> \u0628\u06cc\u06a9 \u0641\u0644 \u0627\u0633 \u0633\u0679\u0648\u0631\u06cc\u062c \u06a9\u0648 \u0635\u0627\u0641 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0633\u06d2 \u0648\u06c1 \u067e\u06c1\u0644\u06d2 \u06a9\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062a\u0627\u06a9\u06c1 \u062a\u0645\u0627\u0645 \u0627\u0633\u06a9\u06cc\u0646\u0632 \u06a9\u0644\u06cc\u0646 \u0627\u0633\u0646\u06cc\u067e \u0634\u0627\u0679 \u0633\u06d2 \u0634\u0631\u0648\u0639 \u06c1\u0648\u06ba\u06d4 <code>putEvents<\/code> IDB \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0627\u06cc\u06a9 \u062a\u0639\u06cc\u0646\u0627\u062a\u06cc \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4 <code>put<\/code>\u06cc\u06c1 \u0627\u0648\u0648\u0631 \u0631\u0627\u0626\u0679 \u06c1\u06d2\u060c \u0688\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646 \u0646\u06c1\u06cc\u06ba\u06d4 <code>getAllEvents<\/code> \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc \u06af\u0626\u06cc \u062a\u0645\u0627\u0645 \u0627\u0634\u06cc\u0627\u0621 \u06a9\u0648 \u0644\u0648\u0679\u0627\u062a\u0627 \u06c1\u06d2: <code>visitedAt<\/code> \u0627\u0646\u0688\u06cc\u06a9\u0633 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0627\u0648\u0631 <code>getEventCount<\/code> \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0633\u0627\u062f\u06c1 \u0634\u0645\u0627\u0631 \u0644\u0648\u0679\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p><code>_db<\/code>    \u06cc\u06c1 \u0627\u06cc\u06a9 \u0645\u0627\u0688\u06cc\u0648\u0644 \u0633\u0637\u062d \u06a9\u0627 \u0633\u0646\u06af\u0644\u0679\u0646 \u0648\u0639\u062f\u06c1 \u06c1\u06d2\u060c \u0644\u06c1\u0630\u0627 \u062a\u0648\u0633\u06cc\u0639 \u06a9\u06d2 \u062a\u0645\u0627\u0645 \u062d\u0635\u06d2 \u0628\u0634\u0645\u0648\u0644 \u0633\u0631\u0648\u0633 \u0648\u0631\u06a9\u0631\u0632 \u0627\u0648\u0631 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688\u0632\u060c \u0627\u06cc\u06a9 \u06c1\u06cc \u06a9\u0646\u06a9\u0634\u0646 \u06a9\u0627 \u0627\u0634\u062a\u0631\u0627\u06a9 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>DB_VERSION<\/code> \u0648\u0642\u062a \u0634\u0631\u0648\u0639 <code>1<\/code> \u06cc\u06c1\u0627\u06ba \u0628\u0639\u062f \u06a9\u06d2 \u062d\u0635\u0648\u06ba \u0645\u06cc\u06ba\u060c \u062c\u0628 \u0622\u067e \u0633\u06cc\u0634\u0646\u0632\u060c \u0627\u0646\u0679\u06cc\u0646\u0679 \u062a\u06be\u0631\u06cc\u0688\u0632\u060c \u0627\u0648\u0631 \u0628\u0631\u0627\u0646\u0688 \u0688\u06cc\u0679\u0627 \u0634\u0627\u0645\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0622\u067e \u0627\u0633 \u0637\u0631\u062d \u0627\u06cc\u06a9 \u0646\u06cc\u0627 \u0645\u062d\u0641\u0648\u0638 \u0627\u0633\u0679\u0648\u0631 \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba \u06af\u06d2: <code>if (!db.objectStoreNames.contains(...))<\/code> \u0627\u0648\u0631 \u0627\u0633 \u0646\u0645\u0628\u0631 \u06a9\u0648 \u0679\u06a9\u0631\u0627\u0646\u0627\u06d4 \u0627\u0633 \u06af\u0627\u0631\u0688 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2 \u06a9\u06c1 \u0645\u0648\u062c\u0648\u062f\u06c1 \u0635\u0627\u0631\u0641\u06cc\u0646 \u0627\u067e\u0646\u06d2 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u0645\u0648\u062c\u0648\u062f \u0627\u0633\u0679\u0648\u0631\u0632 \u06a9\u0648 \u0686\u06be\u0648\u0626\u06d2 \u0628\u063a\u06cc\u0631 \u0645\u062d\u0641\u0648\u0638 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u0627\u067e \u06af\u0631\u06cc\u0688 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-capturing-new-visits-live\">\u062d\u0642\u06cc\u0642\u06cc \u0648\u0642\u062a \u0645\u06cc\u06ba \u0646\u0626\u06d2 \u062f\u0648\u0631\u0648\u06ba \u067e\u0631 \u0642\u0628\u0636\u06c1 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<p>\u0633\u0631\u0648\u0633 \u0648\u0631\u06a9\u0631\u0632 \u062a\u0648\u0633\u06cc\u0639 \u06a9\u0627 \u06c1\u0645\u06cc\u0634\u06c1 \u062d\u0635\u06c1 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0628\u0646\u0627\u0646\u0627 <code>src\/background.ts<\/code>:<\/p>\n<pre><code class=\"language-typescript\">import { hashId, extractDomain, isHttpUrl } from \".\/lib\/util\";\nimport { putEvents } from \".\/db\/index\";\nimport type { RawEvent } from \".\/types\";\n\nchrome.runtime.onInstalled.addListener(() => {\n  console.log(\"[openloops] Extension installed.\");\n});\n\nchrome.action.onClicked.addListener(() => {\n  chrome.runtime.openOptionsPage();\n});\n\nconst DEDUP_MS = 3_000;\nconst recentCaptures = new Map<number url:=\"\" string=\"\" at:=\"\" number=\"\">();\n\nchrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {\n  if (changeInfo.status !== \"complete\" || !tab.url) return;\n\n  const url = tab.url;\n\n  if (!isHttpUrl(url)) return;\n\n  const last = recentCaptures.get(tabId);\n  const now = Date.now();\n  if (last && last.url === url && now - last.at < DEDUP_MS) {\n    console.log(`[openloops] dedup skip \u2014 tab ({tabId} ){url}`);\n    return;\n  }\n\n  recentCaptures.set(tabId, { url, at: now });\n\n  const event: RawEvent = {\n    id: hashId(url, now),\n    url,\n    domain: extractDomain(url),\n    title: tab.title ?? url,\n    visitedAt: now,\n    source: \"live\",\n  };\n\n  putEvents([event]).then(() => {\n    console.log(`[openloops] captured ({event.domain} \u2014 ){event.title}`);\n  }).catch((err) => {\n    console.error(\"[openloops] putEvents failed:\", err);\n  });\n});\n<\/number><\/code><\/pre>\n<p><code>chrome.action.onClicked<\/code>    \u0679\u0648\u0644 \u0628\u0627\u0631 \u06a9\u0627 \u0622\u0626\u06cc\u06a9\u0646 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u06a9\u0648 \u067e\u0627\u067e \u0627\u067e \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0679\u06cc\u0628 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u06a9\u06be\u0648\u0644\u0646\u06d2 \u06a9\u0627 \u0633\u0628\u0628 \u0628\u0646\u062a\u0627 \u06c1\u06d2\u06d4 <code>options_page<\/code> \u0627\u067e\u0646\u06d2 \u0645\u06cc\u0646\u06cc \u0641\u06cc\u0633\u0679 \u0645\u06cc\u06ba \u0627\u0646\u062f\u0631\u0627\u062c \u062f\u0631\u062c \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<p>\u0644\u0627\u0626\u06cc\u0648 \u06a9\u06cc\u067e\u0686\u0631 \u0627\u0646\u062f\u0631\u0648\u0646\u06cc \u0637\u0648\u0631 \u067e\u0631 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 <code>tabs.onUpdated<\/code> \u0627\u06cc\u06a9 \u0633\u0627\u0645\u0639\u06cc\u0646 \u062c\u0648 \u0635\u0641\u062d\u06c1 \u0644\u0648\u0688 \u06c1\u0648\u0646\u06d2\u060c \u0631\u06cc \u0688\u0627\u0626\u0631\u06cc\u06a9\u0679 \u06c1\u0648\u0646\u06d2 \u0627\u0648\u0631 \u0679\u0627\u0626\u0679\u0644 \u0627\u067e \u0688\u06cc\u0679 \u06c1\u0648\u0646\u06d2 \u067e\u0631 \u06a9\u0631\u0648\u0645 \u0628\u0627\u0631 \u0628\u0627\u0631 \u0641\u0627\u0626\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 (\u0644\u06cc\u06a9\u0646 \u0622\u067e \u06a9\u0648 \u0635\u0631\u0641 \u0627\u0633 \u0644\u0645\u062d\u06d2 \u0645\u06cc\u06ba \u062f\u0644\u0686\u0633\u067e\u06cc \u06c1\u0648\u0646\u06cc \u0686\u0627\u06c1\u06cc\u06d2) <code>changeInfo.status === \"complete\"<\/code>. \u0648\u06c1\u0627\u06ba \u0633\u06d2\u060c <code>isHttpUrl<\/code> \u06cc\u06c1 \u06c1\u0631 \u0627\u0633 \u0686\u06cc\u0632 \u06a9\u0648 \u062d\u0630\u0641 \u06a9\u0631 \u062f\u06cc\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u0627\u0635\u0644 \u0648\u06cc\u0628 \u0635\u0641\u062d\u06c1 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u060c \u0688\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646 \u06af\u0627\u0631\u0688 \u0628\u06d2 \u06a9\u0627\u0631 \"\u0688\u0648\u0646\" \u0627\u06cc\u0648\u0646\u0679\u0633 \u06a9\u0648 \u062e\u062a\u0645 \u06a9\u0631 \u062f\u06cc\u062a\u0627 \u06c1\u06d2 \u062c\u0646\u06c1\u06cc\u06ba SPA \u0641\u0627\u0626\u0631 \u06a9\u0631\u0646\u0627 \u067e\u0633\u0646\u062f \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0628\u0627\u0642\u06cc\u06d4 <code>RawEvent<\/code> \u06a9\u06d2 \u0633\u0627\u062a\u06be <code>source: \"live\"<\/code>.<\/p>\n<p>\u0688\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646 \u06af\u0627\u0631\u0688 \u0688\u06cc\u0632\u0627\u0626\u0646 \u06a9\u06cc \u0628\u06c1\u062a\u0631\u06cc\u0646 \u06a9\u0648\u0634\u0634 \u0633\u06d2 \u06c1\u06d2\u06d4 <code>recentCaptures<\/code> \u06cc\u06c1 \u0628\u0627\u0642\u0627\u0639\u062f\u06c1 \u0627\u0646 \u0645\u06cc\u0645\u0648\u0631\u06cc \u06c1\u06d2\u06d4 <code>Map<\/code>\u06a9\u0631\u0648\u0645 \u0633\u0631\u0648\u0633 \u0648\u0631\u06a9\u0631 \u06a9\u0648 \u0627\u06cc\u0648\u0646\u0679\u0633 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0631\u0648\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 <code>Map<\/code> \u0627\u0633 \u06a9\u06d2 \u0633\u0627\u062a\u06be\u06d4 \u0627\u06cc\u06a9 \u06c1\u06cc \u0648\u06cc\u06a9 \u0627\u067e \u0633\u06cc\u0634\u0646 \u0645\u06cc\u06ba \u0641\u0627\u0644\u062a\u0648 \u0628\u0631\u0633\u0679 \u0627\u0628 \u0628\u06be\u06cc \u06a9\u0645 \u06c1\u0648 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0644\u06cc\u06a9\u0646 \u062c\u0628 \u0633\u0631\u0648\u0633 \u0648\u0631\u06a9\u0631 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u062a\u0648 \u0646\u06c1\u06cc\u06ba\u060c \u0627\u0648\u0631 \u06cc\u06c1 \u0627\u06cc\u06a9 \u0642\u0627\u0628\u0644 \u0642\u0628\u0648\u0644 \u062a\u062c\u0627\u0631\u062a \u06c1\u06d2\u06d4 <code>hashId<\/code> \u062c\u0628 \u0622\u067e IndexedDB \u067e\u0631 \u067e\u06c1\u0646\u0686\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0622\u067e \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u06c1\u06cc \u0627\u06cc\u06a9 \u0628\u06d2 \u0636\u0631\u0631 \u06a9\u0644\u0648\u0646 \u0628\u0646\u0627 \u0631\u06c1\u06d2 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0622\u062e\u0631\u06cc \u062a\u062d\u0631\u06cc\u0631 \u0628\u06be\u06cc \u06a9\u0686\u06be \u0639\u062c\u06cc\u0628 \u0644\u06af\u062a\u06cc \u06c1\u06d2\u06d4 <code>putEvents([event]).then(...).catch(...)<\/code> \u0627\u0633 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 <code>await<\/code>. \u0633\u0646\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u06a9\u0648 \u062a\u062d\u0631\u06cc\u0631 \u06a9\u06cc \u062a\u06a9\u0645\u06cc\u0644 \u06a9\u0648 \u0631\u0648\u06a9\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0633\u0631\u0648\u0633 \u0648\u0631\u06a9\u0631 \u0627\u062a\u0646\u06cc \u062f\u06cc\u0631 \u062a\u06a9 \u0632\u0646\u062f\u06c1 \u0631\u06c1\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0648\u06c1 \u0627\u06cc\u06a9 IndexedDB \u062a\u062d\u0631\u06cc\u0631 \u06a9\u0648 \u0645\u06a9\u0645\u0644 \u06a9\u0631 \u0633\u06a9\u06d2 \u0686\u0627\u06c1\u06d2 \u0627\u0633\u06d2 \u0645\u0639\u0637\u0644 \u06a9\u0631 \u062f\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u0648\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u0635\u0631\u0641 \u062a\u062d\u0631\u06cc\u0631 \u06a9\u0648 \u0645\u06a9\u0645\u0644 \u06a9\u0631\u0646\u0627 \u0627\u0648\u0631 \u062c\u0627\u0631\u06cc \u0631\u06a9\u06be\u0646\u0627 \u06a9\u0627\u0641\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u06a9\u06c1 <code>source<\/code> \u06a9\u06be\u06cc\u062a\u0648\u06ba \u06a9\u0627 \u0648\u0632\u0646 \u067e\u06c1\u0644\u06d2 \u0638\u0627\u06c1\u0631 \u06c1\u0648\u0646\u06d2 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0627\u0633 \u0637\u0631\u062d \u06a9\u0648\u0688 \u0628\u0639\u062f \u0645\u06cc\u06ba \"\u0635\u0627\u0631\u0641 \u0646\u06d2 \u0627\u0635\u0644 \u0645\u06cc\u06ba \u06c1\u0633\u0679\u0631\u06cc \u06a9\u0648 \u0628\u0627\u0632\u06cc\u0627\u0641\u062a \u06a9\u06cc\u0627\" \u0627\u0648\u0631 \"\u0627\u06cc\u06a9\u0633\u0679\u06cc\u0646\u0634\u0646 \u0635\u0631\u0641 5 \u0645\u0646\u0679 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u06be\u0644\u0627 \u062a\u06be\u0627\" \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0641\u0631\u0642 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633 \u06af\u0627\u0626\u06cc\u0688 \u0645\u06cc\u06ba \u0628\u0639\u062f \u0645\u06cc\u06ba \u0627\u067e\u0646\u06d2 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u06a9\u0648 \u0688\u06cc\u0632\u0627\u0626\u0646 \u06a9\u0631\u062a\u06d2 \u0648\u0642\u062a \u0622\u0646 \u0628\u0648\u0631\u0688\u0646\u06af \u06a9\u06d2 \u0644\u06cc\u06d2 \u06cc\u06c1 \u0627\u06c1\u0645 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0628 \u0627\u06cc\u06a9\u0633\u0679\u06cc\u0646\u0634\u0646 \u0628\u0646\u0627\u0626\u06cc\u06ba \u0627\u0648\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0644\u0648\u0688 \u06a9\u0631\u06cc\u06ba (<code>npm run build<\/code>\u060c \u067e\u06be\u0631 \u062a\u0648\u0633\u06cc\u0639\u06cc \u06a9\u0627\u0631\u0688 \u067e\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0644\u0648\u0688 \u0622\u0626\u06cc\u06a9\u0646 \u067e\u0631 \u06a9\u0644\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4 <code>chrome:\/\/extensions<\/code>)\u060c \u0686\u0646\u062f \u0635\u0641\u062d\u0627\u062a \u067e\u0631 \u062c\u0627\u0626\u06cc\u06ba\u060c \u067e\u06be\u0631 \u0633\u0631\u0648\u0633 \u0648\u0631\u06a9\u0631 \u06a9\u06d2 DevTools \u06a9\u0648 \u06a9\u06be\u0648\u0644\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u0648\u0633\u06cc\u0639\u06cc \u06a9\u0627\u0631\u0688 \u0645\u06cc\u06ba \"\u0633\u0631\u0648\u0633 \u0648\u0631\u06a9\u0631\" \u067e\u0631 \u06a9\u0644\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4 \u0622\u067e \u062f\u06cc\u06a9\u06be \u0633\u06a9\u06cc\u06ba \u06af\u06d2 <code>[openloops] captured ...<\/code> \u0627\u06cc\u06a9 \u0644\u0627\u06af \u0644\u0627\u0626\u0646 \u0638\u0627\u06c1\u0631 \u06c1\u0648\u06af\u06cc \u062c\u0648 \u0627\u0633 \u0628\u0627\u062a \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u062a\u06cc \u06c1\u06d2 \u06a9\u06c1 \u0631\u06cc\u0626\u0644 \u0679\u0627\u0626\u0645 \u06a9\u06cc\u067e\u0686\u0631 \u06a9\u0627\u0645 \u06a9\u0631 \u0631\u06c1\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-backfilling-14-days-of-history\">14 \u062f\u0646 \u06a9\u06d2 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u06a9\u0648 \u067e\u064f\u0631 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<p>\u0644\u0627\u0626\u06cc\u0648 \u06a9\u06cc\u067e\u0686\u0631 \u0622\u067e \u06a9\u0648 \u0635\u0631\u0641 \u0648\u06c1\u06cc \u062f\u06cc\u06a9\u06be\u0646\u06d2 \u062f\u06cc\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u06c1\u0648 \u0631\u06c1\u0627 \u06c1\u06d2\u06d4 <em>~ \u0628\u0639\u062f<\/em> \u0627\u06cc\u06a9\u0633\u0679\u06cc\u0646\u0634\u0646 \u06a9\u0648 \u0627\u0646\u0633\u0679\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0628\u06be\u06cc \u0627\u0648\u067e\u0646 \u0644\u0648\u067e\u0633 \u06a9\u0648 \u06a9\u0627\u0631\u0622\u0645\u062f \u0628\u0646\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062d\u0627\u0644\u06cc\u06c1 \u062a\u0627\u0631\u06cc\u062e \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0622\u0628\u0627\u062f \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u06af\u06cc\u06d4 \u0628\u0646\u0627\u0646\u0627 <code>src\/pipeline\/backfill.ts<\/code>:<\/p>\n<pre><code class=\"language-typescript\">import { extractDomain, hashId, isHttpUrl } from \"..\/lib\/util\";\nimport { putEvents, clearEvents } from \"..\/db\/index\";\nimport type { RawEvent } from \"..\/types\";\n\nconst CONCURRENCY = 50;\n\nasync function visitsForItem(\n  item: chrome.history.HistoryItem,\n  startTime: number\n): Promise<rawevent> {\n  if (!item.url) return [];\n  if (!isHttpUrl(item.url)) return [];\n\n  const visits = await chrome.history.getVisits({ url: item.url });\n\n  const events: RawEvent[] = [];\n  for (const visit of visits) {\n    if (!visit.visitTime || visit.visitTime < startTime) continue;\n\n    events.push({\n      id: hashId(item.url, visit.visitTime),\n      url: item.url,\n      domain: extractDomain(item.url),\n      title: item.title ?? item.url,\n      visitedAt: visit.visitTime,\n      source: \"backfill\",\n    });\n  }\n\n  return events;\n}\n\nexport async function backfillHistory(days = 14): Promise<number> {\n  await clearEvents();\n\n  const startTime = Date.now() - days * 24 * 60 * 60 * 1000;\n\n  const historyItems = await chrome.history.search({\n    text: \"\",\n    startTime,\n    maxResults: 100_000,\n  });\n\n  let totalWritten = 0;\n\n  for (let i = 0; i < historyItems.length; i += CONCURRENCY) {\n    const batch = historyItems.slice(i, i + CONCURRENCY);\n    const batchResults = await Promise.all(\n      batch.map((item) => visitsForItem(item, startTime))\n    );\n    const events = batchResults.flat();\n    await putEvents(events);\n    totalWritten += events.length;\n  }\n\n  return totalWritten;\n}\n<\/number><\/rawevent><\/code><\/pre>\n<p><code>backfillHistory<\/code>    \u06cc\u06c1 \u0627\u06cc\u06a9 \u0641\u0648\u0646 \u06a9\u0627\u0644 \u0633\u06d2 \u0634\u0631\u0648\u0639 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 <code>clearEvents<\/code> \u06cc\u06c1 \u0627\u0633\u0679\u0648\u0631\u06cc\u062c \u06a9\u0648 \u0635\u0627\u0641 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062a\u0627\u06a9\u06c1 \u06c1\u0631 \u0631\u0646 \u0645\u0646\u062a\u062e\u0628 \u0648\u0646\u0688\u0648 \u06a9\u0627 \u0635\u0627\u0641 \u0633\u0646\u06cc\u067e \u0634\u0627\u0679 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u062a\u0645\u0627\u0645 \u062c\u0633\u0645\u0627\u0646\u06cc \u062f\u0648\u0631\u06d2 \u0627\u0628 \u0628\u06be\u06cc \u0645\u0648\u062c\u0648\u062f \u06c1\u06cc\u06ba\u06d4 <code>chrome.history<\/code>\u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u06a9\u0686\u06be \u0628\u06be\u06cc \u0636\u0627\u0626\u0639 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u067e\u06be\u0631 \u062a\u0644\u0627\u0634 \u06a9\u0631\u06cc\u06ba: <code>maxResults: 100_000<\/code>100 \u06a9\u06cc \u0688\u06cc\u0641\u0627\u0644\u0679 \u0642\u062f\u0631 \u06a9\u0633\u06cc \u0628\u06be\u06cc \u0634\u062e\u0635 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0628\u06c1\u062a \u06a9\u0645 \u06c1\u06d2 \u062c\u0648 \u06a9\u0686\u06be \u062f\u0646\u0648\u06ba \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u062d\u0642\u06cc\u0642\u06cc \u062f\u0646\u06cc\u0627 \u0645\u06cc\u06ba \u0628\u0631\u0627\u0624\u0632\u0646\u06af \u06a9\u0631 \u0631\u06c1\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u06c1\u0631 \u0627\u06cc\u06a9 \u0645\u0645\u0627\u062b\u0644\u062a <code>HistoryItem<\/code> \u067e\u0627\u0633 <code>visitsForItem<\/code>\u06a9\u0631\u0648\u0645 \u06a9\u0686\u06be \u0628\u06be\u06cc \u0648\u0627\u067e\u0633 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u062c\u0648 \u0644\u0648\u0679\u062a\u0627 \u06c1\u06d2 \u0627\u0633\u06d2 \u0686\u06be\u0648\u0691 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 <code>url<\/code> \u06cc\u06c1 \u06a9\u0686\u06be \u062d\u0630\u0641 \u0634\u062f\u06c1 \u062a\u0627\u0631\u06cc\u062e \u06a9\u06d2 \u0627\u0646\u062f\u0631\u0627\u062c\u0627\u062a \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0639\u062c\u06cc\u0628 \u0628\u0627\u062a \u06c1\u06d2 \u0627\u0648\u0631 \u06cc\u06c1 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u063a\u06cc\u0631 \u0648\u06cc\u0628 \u06cc\u0648 \u0622\u0631 \u0627\u06cc\u0644 \u06a9\u0648 \u0686\u06be\u0648\u0691 \u062f\u06cc\u062a\u0627 \u06c1\u06d2: <code>isHttpUrl<\/code>\u0627\u0633 \u0634\u06d2 \u06a9\u06cc \u0645\u06a9\u0645\u0644 \u0645\u0644\u0627\u062d\u0638\u06c1 \u06a9\u06cc \u06af\u0626\u06cc \u0641\u06c1\u0631\u0633\u062a \u062d\u0627\u0635\u0644 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2\u06d4<\/p>\n<p>\u06a9\u0627\u0644 \u06a9\u0631\u0646\u0627 <code>getVisits<\/code> \u0627\u0633 \u067e\u0631 \u0628\u06be\u0631\u0648\u0633\u06c1 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 <code>search<\/code> \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u062a\u0646\u06c1\u0627 \u0631\u06c1\u0646\u0627 \u0636\u0631\u0648\u0631\u06cc \u06c1\u06d2\u06d4 <code>chrome.history.search<\/code> \u0627\u06cc\u06a9 \u06a9\u0627\u0644 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u067e\u0631\u06a9\u0634\u0634 \u06c1\u06d2\u060c \u06cc\u06c1 URL \u06a9\u06d2 \u062a\u0645\u0627\u0645 \u062f\u0648\u0631\u0648\u06ba \u06a9\u0648 \u06a9\u0645 \u06a9\u0631 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 <em>\u0633\u0628 \u0633\u06d2 \u062d\u0627\u0644\u06cc\u06c1<\/em> \u0627\u06cc\u06a9 \u0627\u06af\u0631 \u0622\u067e \u06a9\u0633\u06cc \u0686\u06cc\u0632 \u06a9\u0648 \u0688\u06cc\u0628\u06af \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u062f\u0648 \u062f\u0646\u0648\u06ba \u0645\u06cc\u06ba \u062a\u06cc\u0646 \u0628\u0627\u0631 \u0627\u0633\u06cc \u0627\u0633\u0679\u06cc\u06a9 \u0627\u0648\u0648\u0631 \u0641\u0644\u0648 \u062c\u0648\u0627\u0628 \u06a9\u0648 \u062f\u06cc\u06a9\u06be \u0686\u06a9\u06d2 \u06c1\u06cc\u06ba\u060c <code>search<\/code> \u0622\u067e \u06a9\u0648 \u0627\u06af\u0644\u06d2 \u062d\u0635\u06d2 \u0645\u06cc\u06ba \u062a\u06cc\u0646\u0648\u06ba \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u06af\u06cc\u060c \u062c\u0648 \u0627\u06cc\u06a9 \u0642\u0637\u0627\u0631 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0648\u0627\u0642\u0639\u0627\u062a \u06a9\u0648 \u0633\u06cc\u0634\u0646\u0632 \u0645\u06cc\u06ba \u062a\u0642\u0633\u06cc\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \"3 \u062f\u0646 \u067e\u06c1\u0644\u06d2 \u0627\u06cc\u06a9 \u0648\u0632\u0679\" \u0627\u0648\u0631 \"\u0645\u0633\u0644\u0633\u0644 \u0688\u06cc\u0628\u06af\u0646\u06af \u0633\u06cc\u0634\u0646\" \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0641\u0631\u0642 \u06c1\u06d2\u06d4<\/p>\n<p><code>getVisits<\/code>    \u06cc\u06c1 \u0679\u0627\u0626\u0645 \u0627\u0633\u0679\u06cc\u0645\u067e \u06a9\u06cc \u0645\u06a9\u0645\u0644 \u0641\u06c1\u0631\u0633\u062a \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u06cc\u06c1 \u0648\u0627\u067e\u0633 \u0622\u062a\u0627 \u06c1\u06d2: <em>\u06c1\u0631<\/em> \u0686\u0648\u0646\u06a9\u06c1 \u062a\u0627\u0631\u06cc\u062e \u06a9\u06cc \u062d\u062f \u0633\u06d2 \u0642\u0637\u0639 \u0646\u0638\u0631 URL \u06a9\u06cc \u062a\u0627\u0631\u06cc\u062e \u06c1\u06d2\u060c <code>visitsForItem<\/code> \u0641\u0644\u0679\u0631\u0646\u06af \u06a9\u0627 \u0645\u0639\u06cc\u0627\u0631 <code>startTime<\/code> \u062e\u0648\u062f \u0627\u0648\u0631 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 <code>chrome.history.search<\/code> \u0636\u0631\u0648\u0631\u062a \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0628\u0631\u0627\u0624\u0632\u0631 \u06a9\u06cc \u062a\u0627\u0631\u06cc\u062e \u06a9\u06cc \u0648\u062c\u06c1 \u0633\u06d2 \u0628\u06cc\u06a9 \u0641\u0644\u0646\u06af \u062f\u0633\u06cc\u0648\u06ba \u06c1\u0632\u0627\u0631 \u0622\u0626\u0679\u0645\u0632 \u0648\u0627\u067e\u0633 \u06a9\u0631 \u0633\u06a9\u062a\u06cc \u06c1\u06d2\u06d4 <code>getVisits<\/code> \u0628\u06cc\u0686\u0648\u06ba \u0645\u06cc\u06ba <code>CONCURRENCY<\/code>\u0633\u0628 \u06a9\u0686\u06be \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2\u060c \u0627\u0633\u06d2 50 \u067e\u0631 \u0633\u06cc\u0679 \u06a9\u0631\u06cc\u06ba\u06d4 \u06a9\u0631\u0648\u0645 \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u0639\u0645\u0644 \u062f\u0631\u0622\u0645\u062f \u067e\u0631 \u0633\u062e\u062a \u062d\u062f\u0648\u062f \u06a9\u0648 \u062f\u0633\u062a\u0627\u0648\u06cc\u0632 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>getVisits<\/code> \u0644\u06cc\u06a9\u0646 \u0627\u06af\u0631 \u0622\u067e \u0627\u06cc\u06a9 \u0648\u0642\u062a \u0645\u06cc\u06ba 50 \u0627\u0691\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0622\u067e \u0627\u0628 \u0628\u06be\u06cc \u0628\u06c1\u06c1 \u062c\u0627\u0646\u06d2 \u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u062c\u0648\u0627\u0628 \u062f\u06d2 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-checkpoint\">\u0686\u0648\u06a9\u06cc<\/h3>\n<p>\u0622\u067e \u0639\u0627\u0645 \u0637\u0648\u0631 \u067e\u0631 \u0628\u0631\u0627\u0624\u0632\u0646\u06af \u0627\u0648\u0631 \u062f\u06cc\u06a9\u06be \u06a9\u0631 \u0644\u0627\u0626\u06cc\u0648 \u06a9\u06cc\u067e\u0686\u0631 \u06a9\u0648 \u0686\u06cc\u06a9 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>raw_events<\/code> fill : \u06a9\u06be\u0648\u0644\u0646\u0627 <code>chrome:\/\/extensions<\/code>\u0627\u0648\u067e\u0646 \u0644\u0648\u067e\u0633 \u06a9\u0627\u0631\u0688 \u0645\u06cc\u06ba\u060c \"\u0633\u0631\u0648\u0633 \u0648\u0631\u06a9\u0631\" \u067e\u0631 \u06a9\u0644\u06a9 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u067e\u06be\u0631 <strong>\u062f\u0631\u062e\u0648\u0627\u0633\u062a<\/strong> \u0679\u06cc\u0628 \u2192 <strong>\u0627\u0646\u0688\u06cc\u06a9\u0633\u0688 \u0688\u06cc \u0628\u06cc<\/strong> \u2192 <code>openloops<\/code> \u2192 <code>raw_events<\/code>\u06cc\u06c1\u0627\u06ba \u06c1\u0631 \u0627\u06cc\u06a9 \u0642\u0637\u0627\u0631 \u06c1\u06d2\u06d4 <code>RawEvent<\/code> \u06a9\u06d2 \u0633\u0627\u062a\u06be <code>source: \"live\"<\/code>.<\/p>\n<p><code>backfillHistory<\/code>    \u0627\u0633 \u06a9\u0627 \u0627\u0628\u06be\u06cc \u062a\u06a9 \u062e\u0648\u062f \u0633\u06d2 \u06a9\u0648\u0626\u06cc UI \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u062c\u0628 \u06c1\u0645 \u067e\u0627\u0631\u0679 13 \u0645\u06cc\u06ba \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u0631\u06cc\u0644 \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u06c1\u0645 \u0627\u0633\u06d2 \"Scan My History\" \u0628\u0679\u0646 \u0633\u06d2 \u062c\u0648\u0691 \u062f\u06cc\u06ba \u06af\u06d2\u06d4 \u0627\u0628\u06be\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2 \u0635\u0631\u0641 \u0645\u0631\u062a\u0628 \u06a9\u0631\u0646\u0627 \u06c1\u06cc \u06a9\u0627\u0641\u06cc \u06c1\u06d2\u06d4 <code>raw_events<\/code> \u06cc\u06c1 \u0644\u0627\u0626\u06cc\u0648 \u06a9\u06cc\u067e\u0686\u0631 \u0633\u06d2 \u0628\u06be\u0631\u0627 \u06c1\u0648\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0644\u06d2 \u062d\u0635\u06d2 \u0645\u06cc\u06ba\u060c \u06c1\u0645 \u0627\u0633 \u062e\u0627\u0645 \u062f\u06be\u0627\u0631\u06d2 \u06a9\u0648 \u0627\u06cc\u06a9 \u0633\u0679\u0631\u06a9\u0686\u0631\u0688 \u0633\u06cc\u0634\u0646\u060c \u06cc\u0627 \u0633\u06cc\u0634\u0646 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u0646\u0627 \u0634\u0631\u0648\u0639 \u06a9\u0631 \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h2 id=\"heading-how-to-turn-noise-into-sessions\">\u0634\u0648\u0631 \u06a9\u0648 \u0633\u06cc\u0634\u0646 \u0645\u06cc\u06ba \u06a9\u06cc\u0633\u06d2 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/h2>\n<p>\u0622\u067e \u06a9\u06cc \u0627\u0635\u0644 \u0628\u0631\u0627\u0624\u0632\u0646\u06af \u06c1\u0633\u0679\u0631\u06cc \u0627\u06cc\u0633\u06cc \u0633\u0631\u06af\u0631\u0645\u06cc \u0633\u06d2 \u0628\u06be\u0631\u06cc \u06c1\u0648\u0626\u06cc \u06c1\u06d2 \u062c\u0633 \u06a9\u0627 \u0627\u0633 \u0633\u06d2 \u06a9\u0648\u0626\u06cc \u062a\u0639\u0644\u0642 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 \u062c\u0648 \u0622\u067e \u0627\u0635\u0644 \u0645\u06cc\u06ba \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u06a9\u0648\u0634\u0634 \u06a9\u0631 \u0631\u06c1\u06d2 \u062a\u06be\u06d2\u06d4 \u062a\u062d\u0642\u06cc\u0642 \u06a9\u06d2 \u0627\u06cc\u06a9 \u062f\u0648\u067e\u06c1\u0631 \u06a9\u0648 Gmail\u060c Slack\u060c \u06cc\u0627 YouTube \u06a9\u06d2 \u062f\u0631\u062c\u0646\u0648\u06ba \u0648\u0632\u0679\u0633 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0648\u0642\u0641\u06c1 \u062f\u06cc\u0627 \u062c\u0627 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u060c \u062c\u0646 \u06a9\u06d2 \u0639\u0646\u0648\u0627\u0646 \u0633\u06d2 \u0635\u0641\u062d\u0627\u062a \"\u0646\u06cc\u0627 \u0679\u06cc\u0628\" \u06cc\u0627 \"\u0688\u06cc\u0634 \u0628\u0648\u0631\u0688\" \u06c1\u06cc\u06ba \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0628\u0631\u0627\u0624\u0632\u0631 \u0645\u06cc\u06ba \u0631\u06cc\u06a9\u0627\u0631\u0688 \u06c1\u0648\u0646\u06d2 \u067e\u0631 \u0635\u0641\u062d\u06c1 \u0644\u0648\u0688\u0646\u06af \u062e\u062a\u0645 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u0627 \u062a\u06be\u0627\u06d4<\/p>\n<p>\u0627\u0633 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u06a9\u06c1 \u0627\u0633 \u0645\u06cc\u06ba \u0633\u06d2 \u06a9\u0633\u06cc \u06a9\u0648 \u0628\u06be\u06cc \u0628\u0627\u0645\u0639\u0646\u06cc \u0686\u06cc\u0632 \u0645\u06cc\u06ba \u06af\u0631\u0648\u067e \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2\u060c \u062f\u0648 \u0686\u06cc\u0632\u06cc\u06ba \u0636\u0631\u0648\u0631\u06cc \u06c1\u06cc\u06ba\u06d4 \u06cc\u0639\u0646\u06cc\u060c \u0634\u0648\u0631 \u06a9\u0648 \u0641\u0644\u0679\u0631 \u06a9\u06cc\u0627 \u062c\u0627\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u060c \u0627\u0648\u0631 \u0628\u0627\u0642\u06cc \u06a9\u0648 \u0633\u06cc\u0634\u0646\u0632 \u0645\u06cc\u06ba \u062a\u0642\u0633\u06cc\u0645 \u06a9\u06cc\u0627 \u062c\u0627\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u060c \u06cc\u0639\u0646\u06cc \u0648\u0642\u062a \u06a9\u06d2 \u0648\u0642\u0641\u0648\u06ba \u0633\u06d2 \u0627\u0644\u06af \u06c1\u0648\u0646\u06d2 \u0648\u0627\u0644\u06cc \u0633\u0631\u06af\u0631\u0645\u06cc \u06a9\u06cc \u0645\u0633\u0644\u0633\u0644 \u062d\u062f\u0648\u062f\u06d4<\/p>\n<p>\u0627\u0633 \u0633\u06cc\u06a9\u0634\u0646 \u0645\u06cc\u06ba\u060c \u06c1\u0645 \u0627\u06cc\u06a9 \u0686\u06be\u0648\u0679\u06d2 \u0645\u0637\u0644\u0648\u0628\u06c1 \u0627\u0644\u0641\u0627\u0638 \u06a9\u06d2 \u0627\u06cc\u06a9\u0633\u0679\u0631\u06cc\u06a9\u0679\u0631 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u0646 \u062f\u0648\u0646\u0648\u06ba \u0645\u0631\u0627\u062d\u0644 \u06a9\u0648 \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0633\u06d2 \u06c1\u0631 \u0633\u06cc\u0634\u0646 \u0627\u067e\u0646\u06d2 \u0645\u0648\u0627\u062f \u06a9\u0648 \u0628\u06cc\u0627\u0646 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u06cc\u06c1\u06cc \u0648\u0636\u0627\u062d\u062a \u0628\u0639\u062f \u0645\u06cc\u06ba \u06a9\u0644\u0633\u0679\u0631\u0646\u06af \u06a9\u0648 \u0645\u0636\u0628\u0648\u0637 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-filtering-out-noise\">\u0634\u0648\u0631 \u0641\u0644\u0679\u0631\u0646\u06af<\/h3>\n<p>\u0628\u0646\u0627\u0646\u0627 <code>src\/pipeline\/noise.ts<\/code>:<\/p>\n<pre><code class=\"language-typescript\">import type { RawEvent } from \"..\/types\";\nimport { isHttpUrl, isLocalHost } from \"..\/lib\/util\";\n\nexport const BLOCKED_DOMAINS: readonly string[] = [\n  \"mail.google.com\",\n  \"outlook.live.com\",\n  \"outlook.office.com\",\n  \"calendar.google.com\",\n  \"slack.com\",\n  \"app.slack.com\",\n  \"discord.com\",\n  \"web.whatsapp.com\",\n  \"teams.microsoft.com\",\n  \"messenger.com\",\n];\n\nexport const ADULT_DOMAINS: readonly string[] = [\n  \"xvideos.com\",\n  \"pornhub.com\",\n  \"xnxx.com\",\n  \"xhamster.com\",\n  \"redtube.com\",\n  \"youporn.com\",\n  \"spankbang.com\",\n];\n\nexport const JUNK_DOMAINS: readonly string[] = [\n  \"trk.myperfect2give.com\",\n  \"t.buenotraffic.com\",\n  \"bwredir.com\",\n  \"osom.saintscommunity.net\",\n];\n\nconst ALL_BLOCKED = [...BLOCKED_DOMAINS, ...ADULT_DOMAINS, ...JUNK_DOMAINS];\n\nfunction domainIsBlocked(domain: string): boolean {\n  return ALL_BLOCKED.some(\n    (blocked) => domain === blocked || domain.endsWith(\".\" + blocked)\n  );\n}\n\nexport const NOISE_TITLE_PREFIXES: readonly string[] = [\n  \"new tab\",\n  \"new chat\",\n  \"untitled\",\n  \"inbox\",\n  \"home\",\n  \"dashboard\",\n  \"sign in\",\n  \"log in\",\n  \"loading\",\n];\n\nfunction titleIsGeneric(title: string, domain: string): boolean {\n  if (title.trim() === \"\") return true;\n  if (title.toLowerCase() === domain.toLowerCase()) return true;\n\n  const lower = title.toLowerCase();\n  return NOISE_TITLE_PREFIXES.some((prefix) => lower.startsWith(prefix));\n}\n\nexport function isNoise(event: RawEvent): boolean {\n  if (!isHttpUrl(event.url)) return true;\n  if (isLocalHost(event.domain)) return true;\n  return domainIsBlocked(event.domain) || titleIsGeneric(event.title, event.domain);\n}\n<\/code><\/pre>\n<p><code>isNoise<\/code>    \u06cc\u06c1 \u0627\u06cc\u06a9 \u0648\u0627\u062d\u062f \u0641\u0646\u06a9\u0634\u0646 \u06c1\u06d2 \u062c\u0633\u06d2 \u0628\u0627\u0642\u06cc \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u0627\u0644 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u060c \u0627\u06cc\u06a9 \u062f\u0648\u0633\u0631\u06d2 \u06a9\u06d2 \u0627\u0648\u067e\u0631 \u0686\u0627\u0631 \u0686\u06cc\u06a9 \u0627\u0633\u0679\u06cc\u06a9 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0648 \u0645\u062e\u062a\u0644\u0641 \u0642\u0633\u0645 \u06a9\u06d2 \u0634\u0648\u0631 \u06a9\u0648 \u067e\u06a9\u0691\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u067e\u06c1\u0644\u06d2 \u062f\u0648 \u0686\u06cc\u06a9 \u067e\u0686\u06be\u0644\u06d2 \u0645\u062f\u062f\u06af\u0627\u0631\u0648\u06ba \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>isHttpUrl<\/code> \u0627\u0648\u0631 <code>isLocalHost<\/code> \u06a9\u0633\u06cc \u0628\u06be\u06cc \u0686\u06cc\u0632 \u06a9\u0648 \u062d\u0630\u0641 \u06a9\u0631\u06cc\u06ba \u062c\u0648 \u062d\u0642\u06cc\u0642\u06cc \u0648\u06cc\u0628 \u0635\u0641\u062d\u06c1 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 \u06cc\u0627 \u0622\u067e \u06a9\u06d2 \u0645\u0642\u0627\u0645\u06cc \u062a\u0631\u0642\u06cc\u0627\u062a\u06cc \u0633\u0631\u0648\u0631 \u06a9\u06cc \u0637\u0631\u0641 \u0627\u0634\u0627\u0631\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0648\u06c1\u06cc \u0641\u0644\u0679\u0631 \u06c1\u06d2 \u062c\u0648 \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u0622\u067e \u06a9\u06cc \u06af\u0631\u0641\u062a\u0627\u0631\u06cc \u06a9\u06cc \u062d\u0641\u0627\u0638\u062a \u06a9\u0631 \u0631\u06c1\u0627 \u06c1\u06d2\u06d4 \u062c\u0648 \u06c1\u0645 \u06cc\u06c1\u0627\u06ba \u062f\u0648\u0628\u0627\u0631\u06c1 \u062f\u06cc\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba \u0648\u06c1 \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u0628\u06cc\u0644\u0679 \u0627\u0648\u0631 \u0645\u0639\u0637\u0644 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06cc \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc \u06c1\u06d2\u06d4 <code>raw_events<\/code> \u0627\u06af\u0631 \u06cc\u06c1 \u06a9\u06cc\u067e\u0686\u0631 \u0686\u06cc\u06a9 \u067e\u0627\u0633 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0628 \u0628\u06be\u06cc \u0622\u067e \u0633\u06cc\u0634\u0646 \u0645\u06cc\u06ba \u062f\u0627\u062e\u0644 \u0646\u06c1\u06cc\u06ba \u06c1\u0648 \u067e\u0627\u0626\u06cc\u06ba \u06af\u06d2\u06d4<\/p>\n<p><code>BLOCKED_DOMAINS<\/code>    \u0645\u0648\u0627\u0635\u0644\u0627\u062a \u0627\u0648\u0631 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631\u06cc \u0679\u0648\u0644\u0632 \u062c\u06cc\u0633\u06d2 Gmail\u060c Slack\u060c Discord\u060c WhatsApp Web\u060c \u0627\u0648\u0631 \u0645\u0632\u06cc\u062f \u06a9\u0627 \u0627\u062d\u0627\u0637\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0627\u06cc\u06a9 \u0627\u06cc\u0633\u0627 \u0622\u0644\u06c1 \u06c1\u06d2 \u062c\u0633 \u06a9\u0627 \u0645\u0633\u0644\u0633\u0644 \u062f\u0648\u0631\u06c1 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u0644\u06cc\u06a9\u0646 \u0627\u0633 \u06a9\u0627 \u0627\u067e\u0646\u0627 \u06a9\u0648\u0626\u06cc \u062a\u062d\u0642\u06cc\u0642\u06cc \u0627\u0631\u0627\u062f\u06c1 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 <code>domainIsBlocked<\/code> \u0686\u0648\u0646\u06a9\u06c1 \u0639\u06cc\u0646 \u0688\u0648\u0645\u06cc\u0646 \u0627\u0648\u0631 \u062a\u0645\u0627\u0645 \u0630\u06cc\u0644\u06cc \u0688\u0648\u0645\u06cc\u0646\u0632 \u062f\u0648\u0646\u0648\u06ba \u0645\u0645\u0627\u062b\u0644 \u06c1\u06cc\u06ba\u060c <code>slack.com<\/code> \u0641\u06c1\u0631\u0633\u062a \u0645\u06cc\u06ba \u0628\u06be\u06cc <code>app.slack.com<\/code>. <code>ADULT_DOMAINS<\/code> \u0627\u0648\u0631 <code>JUNK_DOMAINS<\/code> \u06cc\u06c1 \u0627\u06cc\u06a9 \u0645\u062a\u0639\u0644\u0642\u06c1 \u0648\u062c\u06c1 \u0633\u06d2 \u0645\u0648\u062c\u0648\u062f \u06c1\u06d2\u060c \u0628\u0627\u0644\u063a\u0648\u06ba \u06a9\u06d2 \u0645\u0648\u0627\u062f \u0627\u0648\u0631 \u0645\u0639\u0644\u0648\u0645 \u0679\u0631\u06cc\u06a9\u0631 \u06a9\u0648 \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u062e\u0627\u0631\u062c \u06a9\u0631\u0646\u06d2 \u06cc\u0627 \u062a\u06be\u0631\u06cc\u0688\u0632 \u0633\u06d2 \u0688\u0648\u0645\u06cc\u0646\u0632 \u06a9\u0648 \u0631\u06cc \u0688\u0627\u0626\u0631\u06cc\u06a9\u0679 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2\u06d4<\/p>\n<p><code>BLOCKED_DOMAINS<\/code>    \u06cc\u06c1 \u0627\u06cc\u06a9 \u06a9\u06cc\u0648\u0631\u06cc\u0679\u0688 \u0633\u0679\u06cc\u0679\u06a9 \u0644\u0633\u0679 \u06c1\u06d2\u060c \u062c\u0648 \u0628\u0639\u062f \u0645\u06cc\u06ba \u0627\u0633 \u06af\u0627\u0626\u06cc\u0688 \u0645\u06cc\u06ba \u062f\u0648\u0633\u0631\u06d2 \u0641\u0631\u06cc\u06a9\u0648\u0626\u0646\u0633\u06cc \u067e\u0631 \u0645\u0628\u0646\u06cc \u0688\u06cc\u0679\u06cc\u06a9\u0679\u0631 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0636\u0645\u06cc\u0645\u06c1 \u06a9\u06cc \u06af\u0626\u06cc \u06c1\u06d2\u06d4 <code>ambient.ts<\/code>. \u06cc\u06c1 \u062a\u0645\u0627\u0645 \u0688\u0648\u0645\u06cc\u0646\u0632 \u06a9\u0648 \u062d\u0630\u0641 \u06a9\u0631 \u062f\u06d2 \u06af\u0627 \u062c\u0648 \u062a\u0642\u0631\u06cc\u0628\u0627\u064b \u06c1\u0631 \u0633\u06cc\u0634\u0646 \u0645\u06cc\u06ba \u0638\u0627\u06c1\u0631 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0642\u0637\u0639 \u0646\u0638\u0631 \u0627\u0633 \u06a9\u06d2 \u06a9\u06c1 \u0648\u06c1 \u0688\u0648\u0645\u06cc\u0646 \u0627\u0635\u0644 \u0645\u06cc\u06ba \u06a9\u06cc\u0627 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0622\u062e\u0631\u06cc \u0686\u06cc\u06a9 \u062a\u06be\u0627\u060c <code>titleIsGeneric<\/code>\u063a\u06cc\u0631 \u0645\u062f\u062f\u06af\u0627\u0631 \u0639\u0646\u0648\u0627\u0646\u0627\u062a \u0648\u0627\u0644\u06d2 \u0635\u0641\u062d\u0627\u062a \u06a9\u0648 \u067e\u06a9\u0691\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u0639\u0646\u06cc\u060c \u0627\u06cc\u06a9 \u062e\u0627\u0644\u06cc \u0639\u0646\u0648\u0627\u0646\u060c \u0627\u06cc\u06a9 \u0639\u0646\u0648\u0627\u0646 \u062c\u0648 \u0622\u067e \u06a9\u06d2 \u0688\u0648\u0645\u06cc\u0646 \u0646\u0627\u0645 \u0633\u06d2 \u0645\u0644\u062a\u0627 \u062c\u0644\u062a\u0627 \u06c1\u06d2\u060c \u06cc\u0627 \u0627\u06cc\u06a9 \u0639\u0646\u0648\u0627\u0646 \u062c\u0648 \u0639\u0627\u0645 \u0633\u0627\u0628\u0642\u06c1 \u200b\u200b\u062c\u06cc\u0633\u06d2 \"\u0646\u06cc\u0627 \u0679\u06cc\u0628\"\u060c \"\u0688\u06cc\u0634 \u0628\u0648\u0631\u0688\"\u060c \"\u0644\u0648\u0688\u0646\u06af...\" \u06cc\u0627 \"\u0633\u0627\u0626\u0646 \u0627\u0646\" \u0633\u06d2 \u0634\u0631\u0648\u0639 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 <code>NOISE_TITLE_PREFIXES<\/code> \u0686\u0648\u0646\u06a9\u06c1 \u06cc\u06c1 \u0686\u06be\u0648\u0679\u06d2 \u062d\u0631\u0648\u0641 \u06a9\u06d2 \u0639\u0646\u0648\u0627\u0646 \u06a9\u06d2 \u0622\u063a\u0627\u0632 \u0633\u06d2 \u0645\u06cc\u0644 \u06a9\u06be\u0627\u062a\u0627 \u06c1\u06d2\u060c \"\u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 | \u0648\u0631\u0633\u0644\" \u06a9\u0648 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u0637\u06d2 \u0634\u062f\u06c1 \"\u0688\u06cc\u0634 \u0628\u0648\u0631\u0688\" \u06a9\u06d2 \u0628\u0627\u0644\u06a9\u0644 \u0622\u06af\u06d2 \u0686\u06be\u0648\u0691 \u062f\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062c\u0628\u06a9\u06c1 \u0627\u0633\u06cc \u0688\u0648\u0645\u06cc\u0646 \u0633\u06d2 \u0645\u0648\u0627\u062f \u0633\u06d2 \u0628\u06be\u0631\u067e\u0648\u0631 \u0639\u0646\u0648\u0627\u0646\u0627\u062a \u06a9\u0648 \u0627\u0633\u06cc \u0637\u0631\u062d \u0631\u06a9\u06be\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0628\u0646\u0627\u0646\u0627 <code>src\/pipeline\/keywords.ts<\/code>. \u06cc\u06c1 NLP \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u060c \u06cc\u06c1 \u0633\u0679\u0627\u067e \u0627\u0644\u0641\u0627\u0638 \u06a9\u0648 \u06c1\u0679\u0627\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f \u062a\u0639\u062f\u062f \u06a9\u0627 \u062d\u0633\u0627\u0628 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0645\u062a\u0639\u0644\u0642\u06c1 \u062a\u0644\u0627\u0634 \u06a9\u06d2 \u0633\u06cc\u0634\u0646\u0632 \u0645\u06cc\u06ba \"\u0679\u0627\u0626\u067e \u0627\u0633\u06a9\u0631\u067e\u0679 \u062c\u0646\u0631\u06a9\u0633\" \u06cc\u0627 \"\u0631\u06cc\u06cc\u06a9\u0679 \u06c1\u06a9\u0633\" \u062c\u06cc\u0633\u06cc \u0686\u06cc\u0632\u0648\u06ba \u06a9\u0648 \u0633\u0627\u0645\u0646\u06d2 \u0644\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0627\u0641\u06cc \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-typescript\">import { BLOCKED_DOMAINS } from \".\/noise\";\n\nexport const STOPWORDS: ReadonlySet<string> = new Set([\n  \"the\", \"and\", \"for\", \"with\", \"you\", \"your\", \"how\", \"what\", \"this\", \"that\",\n  \"from\", \"are\", \"was\", \"not\", \"but\", \"all\", \"can\", \"has\", \"have\", \"will\",\n  \"its\", \"out\", \"one\", \"get\", \"our\", \"had\", \"just\", \"about\", \"also\", \"more\",\n  \"into\", \"than\", \"then\", \"when\", \"their\", \"there\", \"which\", \"would\", \"been\",\n  \"his\", \"her\", \"who\", \"they\", \"she\", \"him\", \"now\", \"any\", \"way\", \"use\",\n  \"using\", \"used\", \"make\", \"made\",\n  \"google\", \"youtube\", \"search\", \"chat\", \"new\", \"home\", \"www\", \"com\", \"org\",\n  \"net\", \"page\", \"site\", \"tab\", \"view\", \"app\", \"log\", \"sign\", \"login\",\n  \"official\", \"free\", \"online\", \"best\", \"top\", \"open\",\n]);\n\nexport const PLATFORM_STOPWORDS: ReadonlySet<string> = new Set([\n  \"instagram\", \"facebook\", \"youtube\", \"claude\", \"google\", \"linkedin\",\n  \"twitter\", \"reddit\", \"netflix\", \"amazon\", \"gmail\", \"whatsapp\", \"tiktok\",\n  \"messenger\",\n  \"stories\", \"story\", \"reel\", \"reels\", \"shorts\", \"short\", \"feed\", \"watch\",\n  \"video\", \"videos\", \"music\", \"post\", \"posts\", \"message\", \"messages\",\n  \"dm\", \"dms\", \"notification\", \"notifications\", \"profile\", \"home\", \"login\",\n  \"signin\", \"follow\", \"followers\",\n]);\n\nfunction derivedDomainLabels(): Set<string> {\n  const labels = new Set<string>();\n  for (const domain of BLOCKED_DOMAINS) {\n    const label = domain.split(\".\").at(-2);\n    if (label) labels.add(label);\n  }\n  return labels;\n}\n\nconst ALL_STOP_TOKENS: ReadonlySet<string> = new Set([\n  ...STOPWORDS,\n  ...PLATFORM_STOPWORDS,\n  ...derivedDomainLabels(),\n]);\n\nexport function extractKeywords(titles: string[], max = 8): string[] {\n  const freq = new Map<string number=\"\">();\n\n  for (const title of titles) {\n    const tokens = title.toLowerCase().split(\/[^a-z0-9]+\/);\n    for (const token of tokens) {\n      if (token.length < 3) continue;\n      if (\/^d+$\/.test(token)) continue;\n      if (ALL_STOP_TOKENS.has(token)) continue;\n\n      freq.set(token, (freq.get(token) ?? 0) + 1);\n    }\n  }\n\n  return [...freq.entries()]\n    .sort((a, b) => b[1] - a[1])\n    .slice(0, max)\n    .map(([token]) => token);\n}\n<\/string><\/string><\/string><\/string><\/string><\/string><\/code><\/pre>\n<p><code>extractKeywords<\/code>    \u06cc\u06c1 \u0648\u0627\u0642\u0639\u0627\u062a \u06a9\u06d2 \u0627\u06cc\u06a9 \u06af\u0631\u0648\u067e \u0633\u06d2 \u0635\u0641\u062d\u06c1 \u06a9\u0627 \u0639\u0646\u0648\u0627\u0646 \u0644\u06cc\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0645\u0627\u0645 \u063a\u06cc\u0631 \u0645\u0648\u0636\u0648\u0639 \u0622\u0626\u0679\u0645\u0632 \u06a9\u0648 \u06c1\u0679\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0627\u06a9\u062b\u0631 \u0622\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0627\u0644\u0641\u0627\u0638 \u0645\u06cc\u06ba \u0633\u06d2 \u0686\u0646\u062f \u06a9\u0648 \u0648\u0627\u067e\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0627\u0633\u0679\u0631\u067e\u0646\u06af \u0646\u0627\u0645 \"\u0627\u0633\u0679\u0627\u067e \u0648\u0631\u0688\" \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p><code>STOPWORDS<\/code>    \u0627\u0633 \u0645\u06cc\u06ba \u0639\u0627\u0645 \u0627\u0646\u06af\u0631\u06cc\u0632\u06cc \u0641\u0646\u06a9\u0634\u0646 \u0627\u0644\u0641\u0627\u0638 \u062c\u06cc\u0633\u06d2 \"the\" \u0627\u0648\u0631 \"with\" \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0633\u0627\u062a\u06be \u0639\u0627\u0645 \u0633\u0627\u0626\u06cc\u0679 \u06a9\u0631\u0648\u0645 \u062c\u06cc\u0633\u06d2 \"search\"\u060c \"login\" \u0627\u0648\u0631 \"page\" \u06a9\u0627 \u0627\u062d\u0627\u0637\u06c1 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4 \u062e\u0648\u062f \u0633\u06d2\u060c \u0622\u067e \"Instagram\" \u06cc\u0627 \"reels\" \u062c\u06cc\u0633\u06d2 \u0639\u0646\u0648\u0627\u0646 \u0645\u06cc\u06ba \"Reels \u00b7 Instagram\" \u062c\u06cc\u0633\u06d2 \u0679\u0648\u06a9\u0646 \u067e\u0627\u0633 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0648\u06c1 \u0679\u0648\u06a9\u0646 \u0627\u0633 \u0633\u06cc\u0634\u0646 \u06a9\u06d2 \u06a9\u0644\u06cc\u062f\u06cc \u0627\u0644\u0641\u0627\u0638 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0638\u0627\u06c1\u0631 \u06c1\u0648\u06ba \u06af\u06d2\u06d4<\/p>\n<p>\u0648\u06c1 \u062e\u0644\u0627 \u06c1\u06d2\u06d4 <code>PLATFORM_STOPWORDS<\/code> \u0628\u0646\u062f \"Reels \u00b7 Instagram\" \u06cc\u0627 \"Watch - YouTube\" \u062c\u06cc\u0633\u06d2 \u0639\u0646\u0648\u0627\u0646\u0627\u062a \u0627\u0633 \u0679\u0648\u0644 \u06a9\u06cc \u0646\u0634\u0627\u0646\u062f\u06c1\u06cc \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0633\u06d2 \u0622\u067e \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631 \u0631\u06c1\u06d2 \u062a\u06be\u06d2\u060c \u0646\u06c1 \u06a9\u06c1 \u0622\u067e \u0646\u06d2 \u0627\u0633 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u06a9\u06cc\u0627 \u06a9\u06cc\u0627\u06d4 \u062a\u0648 <code>PLATFORM_STOPWORDS<\/code> \u0633\u0648\u0634\u0644 \u0645\u06cc\u0688\u06cc\u0627 UI \u06a9\u0631\u0648\u0645 \u062c\u06cc\u0633\u06d2 \"\u06a9\u06c1\u0627\u0646\u06cc\u0627\u06ba\"\u060c \"\u0641\u06cc\u0688\"\u060c \"DM\"\u060c \"\u0627\u0637\u0644\u0627\u0639\u0627\u062a\" \u06a9\u06d2 \u0633\u0627\u062a\u06be \u067e\u0644\u06cc\u0679 \u0641\u0627\u0631\u0645 \u0627\u0648\u0631 \u0628\u0631\u0627\u0646\u0688 \u06a9\u06d2 \u0646\u0627\u0645\u0648\u06ba \u06a9\u0648 \u06c1\u0679\u0627 \u062f\u06cc\u06ba\u06d4 \u0627\u0633 \u0641\u06c1\u0631\u0633\u062a \u06a9\u06d2 \u0628\u063a\u06cc\u0631\u060c \"Instagram\" \u06cc\u0627 \"View\" \u062c\u06cc\u0633\u06d2 \u06a9\u0644\u06cc\u062f\u06cc \u0627\u0644\u0641\u0627\u0638 \u0633\u0645\u0627\u062c\u06cc \u067e\u0644\u06cc\u0679 \u0641\u0627\u0631\u0645\u0632 \u06a9\u06d2 \u0633\u06cc\u0634\u0646\u0632 \u0633\u06d2 \u0646\u06a9\u0627\u0644\u06d2 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0686\u0648\u0646\u06a9\u06c1 \u062a\u0645\u0627\u0645 \u0633\u0648\u0634\u0644 \u0645\u06cc\u0688\u06cc\u0627 \u0633\u06cc\u0634\u0646\u0632 \u0627\u06cc\u06a9 \u0628\u06d2 \u0645\u0639\u0646\u06cc \u06a9\u0644\u06cc\u062f\u06cc \u0644\u0641\u0638 \u06a9\u0627 \u0627\u0634\u062a\u0631\u0627\u06a9 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u06a9\u0644\u0633\u0679\u0631\u0646\u06af \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646 \u06cc\u06c1 \u062a\u06be\u0631\u06cc\u0688 \u0679\u0627\u0626\u0679\u0644 \u0628\u0646 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u062e\u0627\u0645\u0648\u0634\u06cc \u0633\u06d2 \u063a\u06cc\u0631 \u0645\u062a\u0639\u0644\u0642\u06c1 \u0633\u06cc\u0634\u0646\u0632 \u06a9\u0648 \u0627\u06a9\u0679\u06be\u0627 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p><code>derivedDomainLabels<\/code>    \u0627\u0633\u0679\u0627\u067e \u0648\u0631\u0688\u0632 \u06a9\u06d2 \u062a\u06cc\u0633\u0631\u06d2 \u0645\u0627\u062e\u0630 \u06a9\u0648 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u0645\u0637\u0627\u0628\u0642\u062a \u067e\u0630\u06cc\u0631 \u0631\u06a9\u06be\u062a\u0627 \u06c1\u06d2\u06d4 <code>BLOCKED_DOMAINS<\/code>\u0627\u067e\u0646\u06d2 \u0679\u0627\u067e \u0644\u06cc\u0648\u0644 \u0688\u0648\u0645\u06cc\u0646 \u0633\u06d2 \u0641\u0648\u0631\u0627\u064b \u067e\u06c1\u0644\u06d2 \u0644\u06cc\u0628\u0644 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 \u062a\u0648 <code>mail.google.com<\/code> \u0628\u0646 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>google<\/code> \u0627\u0648\u0631 <code>web.whatsapp.com<\/code> \u0628\u0646 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>whatsapp<\/code>. \u0627\u06af\u0631 \u0622\u067e \u0628\u0639\u062f \u0645\u06cc\u06ba \u0627\u0633 \u0628\u0644\u0627\u06a9 \u0644\u0633\u0679 \u0645\u06cc\u06ba \u0646\u0626\u06d2 \u0688\u0648\u0645\u06cc\u0646\u0632 \u0634\u0627\u0645\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0622\u067e \u0628\u063a\u06cc\u0631 \u06a9\u0633\u06cc \u0627\u0636\u0627\u0641\u06cc \u0631\u06cc\u06a9\u0627\u0631\u0688 \u06a9\u06d2 \u0627\u0646 \u0646\u0627\u0645\u0648\u06ba \u06a9\u0648 \u0627\u067e\u0646\u06d2 \u0645\u0637\u0644\u0648\u0628\u06c1 \u0627\u0644\u0641\u0627\u0638 \u06a9\u0648 \u0622\u0644\u0648\u062f\u06c1 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u0631\u0648\u06a9 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u06af\u0631 \u0645\u0627\u0688\u06cc\u0648\u0644 \u0644\u0648\u0688 \u06a9\u0631\u062a\u06d2 \u0648\u0642\u062a \u062a\u06cc\u0646\u0648\u06ba \u0633\u06cc\u0679\u0648\u06ba \u06a9\u0648 \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u0645\u0644\u0627 \u062f\u06cc\u0627 \u062c\u0627\u0626\u06d2\u06d4 <code>ALL_STOP_TOKENS<\/code>, <code>extractKeywords<\/code> \u06cc\u06c1 \u0628\u0630\u0627\u062a \u062e\u0648\u062f \u0633\u0627\u062f\u06c1 \u06c1\u06d2\u06d4 \u062a\u0645\u0627\u0645 \u0639\u0646\u0648\u0627\u0646\u0627\u062a \u06a9\u0648 \u0686\u06be\u0648\u0679\u06d2 \u062d\u0631\u0648\u0641 \u0645\u06cc\u06ba \u0628\u0646\u0627\u0626\u06cc\u06ba\u060c \u063a\u06cc\u0631 \u062d\u0631\u0641\u06cc \u06cc\u0627 \u0639\u062f\u062f\u06cc \u0627\u0646\u062f\u0631\u0627\u062c\u0627\u062a \u0645\u06cc\u06ba \u062a\u0642\u0633\u06cc\u0645 \u06a9\u0631\u06cc\u06ba\u060c 3 \u062d\u0631\u0648\u0641 \u0633\u06d2 \u0686\u06be\u0648\u0679\u06d2 \u06cc\u0627 \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u0627\u0639\u062f\u0627\u062f \u067e\u0631 \u0645\u0634\u062a\u0645\u0644 \u0679\u0648\u06a9\u0646\u0632 \u06a9\u0648 \u06c1\u0679\u0627 \u062f\u06cc\u06ba\u060c \u0627\u0648\u0631 \u062a\u0645\u0627\u0645 \u0627\u0646\u062f\u0631\u0627\u062c\u0627\u062a \u06a9\u0648 \u0627\u0644\u06af \u06a9\u0631\u06cc\u06ba <code>ALL_STOP_TOKENS<\/code>. \u0627\u0633 \u06a9\u06d2 \u0628\u0639\u062f \u06cc\u06c1 \u0628\u0627\u0642\u06cc \u0627\u0634\u06cc\u0627\u0621 \u06a9\u0648 \u0634\u0645\u0627\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0633\u0628 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0628\u0627\u0631 \u0628\u0627\u0631 \u0622\u0646\u06d2 \u0648\u0627\u0644\u06cc \u0627\u0634\u06cc\u0627\u0621 \u06a9\u0648 \u0648\u0627\u067e\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-extending-the-database-for-sessions\">\u0633\u06cc\u0634\u0646\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u06a9\u06cc \u062a\u0648\u0633\u06cc\u0639<\/h3>\n<p>\u0633\u06cc\u0634\u0646\u0632 \u06a9\u0648 \u0631\u06c1\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062c\u06af\u06c1 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 \u067e\u06c1\u0644\u06d2 \u0627\u0633 \u06af\u0627\u0626\u06cc\u0688 \u0645\u06cc\u06ba <code>src\/db\/index.ts<\/code> \u0622\u067e \u0646\u06d2 \u0627\u0628\u06be\u06cc \u0627\u06cc\u06a9 \u0627\u0633\u06a9\u06cc\u0645\u0627 \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u06cc \u06c1\u06d2\u06d4 <code>raw_events<\/code> \u0648\u0631\u0698\u0646 1 \u0633\u06d2\u06d4 <code>sessions<\/code> \u0648\u0631\u0698\u0646 \u0645\u062d\u0641\u0648\u0638 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0633\u06d2 2 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<p>\u067e\u06c1\u0644\u06d2 \u0627\u0633\u06a9\u06cc\u0645\u0627 \u06a9\u0648 \u0628\u0691\u06be\u0627 \u062f\u06cc\u06ba\u06d4 <code>upgrade<\/code> \u06a9\u0627\u0644 \u0628\u06cc\u06a9:<\/p>\n<pre><code class=\"language-typescript\">import type { RawEvent, Session } from \"..\/types\";\n\ninterface OpenloopsDB extends DBSchema {\n  raw_events: {\n    key: string;\n    value: RawEvent;\n    indexes: { by_visitedAt: number };\n  };\n  sessions: {\n    key: string;\n    value: Session;\n    indexes: { by_startedAt: number };\n  };\n}\n\nconst DB_VERSION = 2;\n\nexport function getDB(): Promise<idbpdatabase>> {\n  if (!_db) {\n    _db = openDB<openloopsdb>(DB_NAME, DB_VERSION, {\n      upgrade(db) {\n        if (!db.objectStoreNames.contains(\"raw_events\")) {\n          const s = db.createObjectStore(\"raw_events\", { keyPath: \"id\" });\n          s.createIndex(\"by_visitedAt\", \"visitedAt\");\n        }\n        if (!db.objectStoreNames.contains(\"sessions\")) {\n          const s = db.createObjectStore(\"sessions\", { keyPath: \"id\" });\n          s.createIndex(\"by_startedAt\", \"startedAt\");\n        }\n      },\n    });\n  }\n  return _db;\n}\n<\/openloopsdb><\/idbpdatabase><\/code><\/pre>\n<p>\u067e\u06be\u0631 \u0627\u067e\u0646\u06d2 \u0633\u06cc\u0634\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0636\u0631\u0648\u0631\u06cc \u0645\u062f\u062f\u06af\u0627\u0631 \u0641\u0646\u06a9\u0634\u0646\u0632 \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 <code>raw_events<\/code> \u0627\u06cc\u06a9 \u0645\u062f\u062f\u06af\u0627\u0631 \u062c\u0648 \u0622\u067e \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u0644\u06a9\u06be \u0686\u06a9\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0648\u06c1 \u0627\u06cc\u06a9 \u06c1\u06cc \u0634\u06a9\u0644 \u06a9\u06cc \u067e\u06cc\u0631\u0648\u06cc \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba: <code>putSessions<\/code> \u0639\u0645\u062f\u06af\u06cc \u0633\u06d2 \u0628\u06cc\u0686\u0632 \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4 <code>clearSessions<\/code> \u062f\u0648\u0628\u0627\u0631\u06c1 \u062a\u0639\u0645\u06cc\u0631 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0627\u0633\u0679\u0648\u0631 \u06a9\u0648 \u0635\u0627\u0641 \u06a9\u0631\u06cc\u06ba\u060c <code>getAllSessions<\/code> \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc \u06af\u0626\u06cc \u062a\u0645\u0627\u0645 \u0627\u0634\u06cc\u0627\u0621 \u06a9\u0648 \u0644\u0648\u0679\u0627\u062a\u0627 \u06c1\u06d2: <code>startedAt<\/code> \u0627\u0646\u0688\u06cc\u06a9\u0633 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 <code>getSessionCount<\/code> \u0631\u0642\u0645 \u0644\u0648\u0679\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-typescript\">export async function putSessions(sessions: Session[]): Promise<void> {\n  if (sessions.length === 0) return;\n  const db = await getDB();\n  const tx = db.transaction(\"sessions\", \"readwrite\");\n  await Promise.all([...sessions.map((s) => tx.store.put(s)), tx.done]);\n}\n\nexport async function clearSessions(): Promise<void> {\n  const db = await getDB();\n  return db.clear(\"sessions\");\n}\n\nexport async function getAllSessions(): Promise<session> {\n  const db = await getDB();\n  return db.getAllFromIndex(\"sessions\", \"by_startedAt\");\n}\n\nexport async function getSessionCount(): Promise<number> {\n  const db = await getDB();\n  return db.count(\"sessions\");\n}\n<\/number><\/session><\/void><\/void><\/code><\/pre>\n<p>\u06a9\u06c1 <code>if (!db.objectStoreNames.contains(...))<\/code> \u067e\u0686\u06be\u0644\u0627 \u062a\u062d\u0641\u0638 \u0648\u06c1\u06cc \u06c1\u06d2 \u062c\u0648 \u0627\u0633\u06d2 \u0645\u062d\u0641\u0648\u0638 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u062c\u0633 \u06a9\u06d2 \u067e\u0627\u0633 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u06c1\u06cc \u0648\u0631\u0698\u0646 1 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u06c1\u06d2\u06d4 <code>raw_events<\/code> \u062d\u0642\u06cc\u0642\u06cc \u0688\u06cc\u0679\u0627 \u0633\u06d2 \u0628\u06be\u0631\u0627 \u06c1\u0648\u0627\u060c \u0622\u067e \u06a9\u0648 \u06a9\u0686\u06be \u0646\u06cc\u0627 \u0645\u0644\u062a\u0627 \u06c1\u06d2\u06d4 <code>sessions<\/code> \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u0645\u0648\u062c\u0648\u062f \u0686\u06cc\u0632\u0648\u06ba \u06a9\u0648 \u0686\u06be\u0648\u0626\u06d2 \u0628\u063a\u06cc\u0631 \u0627\u0633\u06d2 \u0627\u0648\u067e\u0631 \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-segmenting-events-into-sessions\">\u0648\u0627\u0642\u0639\u0627\u062a \u06a9\u0648 \u0633\u06cc\u0634\u0646\u0632 \u0645\u06cc\u06ba \u062a\u0642\u0633\u06cc\u0645 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<p>\u0633\u06cc\u0634\u0646 \u0646\u06cc\u0648\u06cc\u06af\u06cc\u0634\u0646 \u0633\u0631\u06af\u0631\u0645\u06cc \u06a9\u0627 \u0627\u06cc\u06a9 \u0645\u0633\u0644\u0633\u0644 \u0628\u0644\u0627\u06a9 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u060c \u062c\u0628 \u0628\u06be\u06cc \u062f\u0648 \u0644\u06af\u0627\u062a\u0627\u0631 \u0648\u0627\u0642\u0639\u0627\u062a \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0648\u0642\u0641\u06c1 \u062e\u062a\u0645 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u062a\u0648 \u0627\u06cc\u06a9 \u0646\u06cc\u0627 \u0633\u06cc\u0634\u0646 \u0634\u0631\u0648\u0639 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 <code>SESSION_GAP_MS<\/code>. \u0628\u0646\u0627\u0646\u0627 <code>src\/pipeline\/sessions.ts<\/code>:<\/p>\n<pre><code class=\"language-typescript\">import { getAllEvents, clearSessions, putSessions } from \"..\/db\/index\";\nimport { isNoise } from \".\/noise\";\nimport { extractKeywords } from \".\/keywords\";\nimport { hashId } from \"..\/lib\/util\";\nimport type { RawEvent, Session } from \"..\/types\";\n\nconst SESSION_GAP_MS = 30 * 60 * 1000;\n\nfunction rankDomains(events: RawEvent[]): string[] {\n  const freq = new Map<string number=\"\">();\n  for (const e of events) {\n    freq.set(e.domain, (freq.get(e.domain) ?? 0) + 1);\n  }\n  return [...freq.entries()]\n    .sort((a, b) => b[1] - a[1])\n    .map(([domain]) => domain);\n}\n\nfunction buildSession(events: RawEvent[]): Session {\n  const startedAt = events[0].visitedAt;\n  const endedAt = events[events.length - 1].visitedAt;\n\n  return {\n    id: hashId(events[0].url, startedAt),\n    events,\n    startedAt,\n    endedAt,\n    domains: rankDomains(events),\n    keywords: extractKeywords(events.map((e) => e.title)),\n  };\n}\n\nexport async function buildSessions(): Promise<{ events: number; sessions: number }> {\n  const allEvents = await getAllEvents();\n\n  const meaningful = allEvents.filter((e) => !isNoise(e));\n\n  if (meaningful.length === 0) {\n    await clearSessions();\n    return { events: 0, sessions: 0 };\n  }\n\n  const sessions: Session[] = [];\n  let currentGroup: RawEvent[] = [meaningful[0]];\n\n  for (let i = 1; i < meaningful.length; i++) {\n    const gap = meaningful[i].visitedAt - meaningful[i - 1].visitedAt;\n\n    if (gap > SESSION_GAP_MS) {\n      sessions.push(buildSession(currentGroup));\n      currentGroup = [meaningful[i]];\n    } else {\n      currentGroup.push(meaningful[i]);\n    }\n  }\n  sessions.push(buildSession(currentGroup));\n\n  const substantive = sessions.filter(\n    (s) => !(s.events.length === 1 && s.keywords.length === 0)\n  );\n\n  await clearSessions();\n  await putSessions(substantive);\n\n  return { events: meaningful.length, sessions: substantive.length };\n}\n<\/string><\/code><\/pre>\n<p><code>buildSessions<\/code>    \u067e\u0627\u0646\u0686 \u0686\u06cc\u0632\u06cc\u06ba \u062a\u0631\u062a\u06cc\u0628 \u0633\u06d2 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<ol>\n<li>\n<p>\u0648\u0642\u062a \u06a9\u06d2 \u0644\u062d\u0627\u0638 \u0633\u06d2 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u0626\u06d2 \u06af\u0626\u06d2 \u062a\u0645\u0627\u0645 \u062e\u0627\u0645 \u0648\u0627\u0642\u0639\u0627\u062a \u06a9\u0648 \u0644\u0648\u0688 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u06a9\u0686\u06be \u0628\u06be\u06cc \u0686\u06be\u0648\u0691 \u062f\u0648 <code>isNoise<\/code> \u062c\u06be\u0646\u0688\u0627<\/p>\n<\/li>\n<li>\n<p>\u06cc\u06c1 \u0641\u06c1\u0631\u0633\u062a \u06a9\u06d2 \u0628\u0627\u0642\u06cc \u062d\u0635\u0648\u06ba \u0633\u06d2 \u06af\u0632\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u062c\u0628 \u0628\u06be\u06cc \u062f\u0648 \u0644\u06af\u0627\u062a\u0627\u0631 \u0648\u0627\u0642\u0639\u0627\u062a \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0648\u0642\u0641\u06c1 \u062e\u062a\u0645 \u06c1\u0648\u062c\u0627\u062a\u0627 \u06c1\u06d2 \u062a\u0648 \u0627\u06cc\u06a9 \u0646\u06cc\u0627 \u0633\u06cc\u0634\u0646 \u0634\u0631\u0648\u0639 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 <code>SESSION_GAP_MS<\/code> (\u0627\u0648\u0631 \u06a9\u0686\u06be \u0628\u06be\u06cc \u0644\u0648\u067e \u06a9\u0648 \u0628\u0646\u062f \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06c1\u0630\u0627 \u062c\u0628 \u0644\u0648\u067e \u062e\u062a\u0645 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u062a\u0648 \u06cc\u06c1 \u0622\u062e\u0631\u06cc \u062c\u0627\u0631\u06cc \u06af\u0631\u0648\u067e \u06a9\u0648 \u062f\u06be\u06a9\u06cc\u0644 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4)<\/p>\n<\/li>\n<li>\n<p>\u0627\u06cc\u0633\u06d2 \u0633\u06cc\u0634\u0646\u0648\u06ba \u06a9\u0648 \u0686\u06be\u0648\u0691 \u062f\u06cc\u06ba \u062c\u0648 \u0627\u06cc\u06a9 \u06c1\u06cc \u0627\u06cc\u0648\u0646\u0679\u0633 \u0628\u0646\u062a\u06d2 \u06c1\u06cc\u06ba \u0628\u063a\u06cc\u0631 \u0646\u06a9\u0627\u0644\u06d2 \u062c\u0627\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0645\u0637\u0644\u0648\u0628\u06c1 \u0627\u0644\u0641\u0627\u0638 \u06a9\u06d2 (\u0639\u0627\u0645 \u0637\u0648\u0631 \u067e\u0631 \u06af\u0645\u0631\u0627\u06c1 \u0635\u0641\u062d\u06c1 \u06a9\u0633\u06cc \u0627\u0648\u0631 \u0686\u06cc\u0632 \u0633\u06d2 \u063a\u06cc\u0631 \u0645\u0646\u0633\u0644\u06a9 \u06c1\u0648\u062a\u0627 \u06c1\u06d2)\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0646\u062a\u0627\u0626\u062c \u06a9\u0648 \u0628\u0631\u0642\u0631\u0627\u0631 \u0631\u06a9\u06be\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<\/ol>\n<p>\u06c1\u0631 \u0633\u06cc\u0634\u0646 \u06a9\u06d2 <code>domains<\/code> \u0627\u0648\u0631 <code>keywords<\/code> \u0645\u0642\u0627\u0645\u06cc <code>rankDomains<\/code> \u0627\u0648\u0631 <code>extractKeywords<\/code> \u0635\u0631\u0641 \u0627\u0633 \u06af\u0631\u0648\u067e \u0645\u06cc\u06ba \u0627\u06cc\u0648\u0646\u0679\u0633 \u0686\u0644\u06cc\u06ba \u06af\u06d2\u06d4 <code>rankDomains<\/code> \u06cc\u06c1 \u06c1\u0631 \u0688\u0648\u0645\u06cc\u0646 \u0633\u06d2 \u0648\u0627\u0642\u0639\u0627\u062a \u06a9\u06cc \u062a\u0639\u062f\u0627\u062f \u0634\u0645\u0627\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u062a\u0639\u062f\u062f \u06a9\u06d2 \u0644\u062d\u0627\u0638 \u0633\u06d2 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u0633\u06cc\u0634\u0646 \u0645\u06cc\u06ba \u0633\u0628 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u062f\u06cc\u06a9\u06be\u06d2 \u062c\u0627\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0688\u0648\u0645\u06cc\u0646 \u067e\u06c1\u0644\u06d2 \u0622\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u06a9\u0627\u0645 \u06a9\u06cc \u06af\u0626\u06cc \u0645\u062b\u0627\u0644\u06cc\u06ba \"\u0641\u06c1\u0631\u0633\u062a \u0633\u06d2 \u06af\u0632\u0631\u0646\u0627\" \u06a9\u0648 \u0679\u06be\u0648\u0633 \u0628\u0646\u0627\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 \u0622\u0626\u06cc\u06d2 \u067e\u0627\u0646\u0686 \u0648\u0627\u0642\u0639\u0627\u062a (A \u0633\u06d2 E) \u06a9\u0648 \u062f\u06cc\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0646\u06c1\u0648\u06ba \u0646\u06d2 \u0634\u0648\u0631 \u0641\u0644\u0679\u0631\u0646\u06af \u06a9\u0648 \u0645\u0646\u0638\u0648\u0631 \u06a9\u06cc\u0627\u06d4<\/p>\n<pre><code class=\"language-plaintext\">A  t= 0 min  \"TypeScript generics - Stack Overflow\"   stackoverflow.com\nB  t= 5 min  \"TypeScript Handbook\"                    typescriptlang.org\nC  t=10 min  \"microsoft\/TypeScript - GitHub\"          github.com\n   \u2191 gap to D = 45 min  >  SESSION_GAP_MS (30 min)  \u2192 SPLIT HERE\nD  t=55 min  \"React hooks explained - YouTube\"         youtube.com\nE  t=60 min  \"useEffect cleanup - Stack Overflow\"     stackoverflow.com\n<\/code><\/pre>\n<p>\u062c\u06cc\u0633\u06d2 \u062c\u06cc\u0633\u06d2 \u0644\u0648\u067e A \u0633\u06d2 B \u06a9\u06cc \u0637\u0631\u0641 C \u06a9\u06cc \u0637\u0631\u0641 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u06c1\u0631 \u0627\u06cc\u06a9 \u0648\u0642\u0641\u06c1 30 \u0645\u0646\u0679 \u06a9\u06cc \u062d\u062f \u0633\u06d2 \u06a9\u0645 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u060c \u062a\u06cc\u0646\u0648\u06ba \u06a9\u0648 \u0627\u06cc\u06a9 \u06c1\u06cc \u06af\u0631\u0648\u067e \u0645\u06cc\u06ba \u0631\u06a9\u06be\u062a\u06d2 \u06c1\u0648\u0626\u06d2\u06d4 C \u0633\u06d2 D \u062a\u06a9 \u0686\u06be\u0644\u0627\u0646\u06af \u0644\u06af\u0627\u0646\u06d2 \u0645\u06cc\u06ba 45 \u0645\u0646\u0679 \u0644\u06af\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>SESSION_GAP_MS<\/code>\u062a\u0648 \u0644\u0648\u067e \u0628\u0646\u062f \u06c1\u06d2 <code>[A, B, C]<\/code> \u0633\u06cc\u0634\u0646 1 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 D \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u06cc\u06a9 \u0646\u06cc\u0627 \u06af\u0631\u0648\u067e \u0634\u0631\u0648\u0639 \u06a9\u0631\u06cc\u06ba\u06d4 D \u0633\u06d2 E \u062a\u06a9 \u06a9\u0627 \u0648\u0642\u062a \u0635\u0631\u0641 5 \u0645\u0646\u0679 \u06c1\u06d2\u060c \u0644\u06c1\u0630\u0627 \u062c\u0628 E D \u0645\u06cc\u06ba \u0634\u0627\u0645\u0644 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0644\u0648\u067e \u062e\u062a\u0645 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u060c \u06af\u0631\u0648\u067e \u0633\u06cc\u0634\u0646 2 \u0628\u0646 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0633\u06cc\u0634\u0646 1 \u062f\u0631\u062c \u0630\u06cc\u0644 \u0645\u0637\u0644\u0648\u0628\u06c1 \u0627\u0644\u0641\u0627\u0638 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0679\u06cc\u06af \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2: <code>typescript<\/code> \u0627\u0648\u0631 <code>generics<\/code>\u0633\u06cc\u0634\u0646 2 \u06a9\u0648 \u0679\u06cc\u06af \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4 <code>react<\/code> \u0627\u0648\u0631 <code>hooks<\/code>\u062d\u0627\u0644\u0627\u0646\u06a9\u06c1 \u062f\u0648\u0646\u0648\u06ba \u0633\u06cc\u0634\u0646 \u0627\u06cc\u06a9 \u06c1\u06cc \u062f\u0646 \u06c1\u0648\u0626\u06d2 \u062a\u06be\u06d2\u06d4<\/p>\n<p><code>SESSION_GAP_MS<\/code>    \u0627\u0633\u06d2 30 \u0645\u0646\u0679 \u067e\u0631 \u0633\u06cc\u0679 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u06cc\u06c1 \u0648\u06c1\u06cc \u0688\u06cc\u0641\u0627\u0644\u0679 \u06c1\u06d2 \u062c\u0633\u06d2 Google Analytics \u0627\u0648\u0631 \u0645\u0644\u062a\u06d2 \u062c\u0644\u062a\u06d2 \u0679\u0648\u0644\u0632 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0632\u06cc\u0627\u062f\u06c1 \u062a\u0631 \u0628\u0631\u0627\u0624\u0632\u0646\u06af \u067e\u06cc\u0679\u0631\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u0648\u0632\u0648\u06ba \u06c1\u06d2\u06d4<\/p>\n<p>\u062a\u062c\u0627\u0631\u062a \u062f\u0648\u0646\u0648\u06ba \u0637\u0631\u06cc\u0642\u0648\u06ba \u0633\u06d2 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 \u0686\u06be\u0648\u0679\u06d2 \u0648\u0642\u0641\u0648\u06ba \u06a9\u06d2 \u0646\u062a\u06cc\u062c\u06d2 \u0645\u06cc\u06ba \u0632\u06cc\u0627\u062f\u06c1 \u0633\u06cc\u0634\u0646 \u0627\u0648\u0631 \u0686\u06be\u0648\u0679\u06d2 \u0633\u06cc\u0634\u0646 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062c\u0648 \u06a9\u0644\u0633\u0679\u0631\u0646\u06af \u06a9\u0648 \u0645\u0632\u06cc\u062f \u062a\u0641\u0635\u06cc\u0644\u06cc \u0633\u06af\u0646\u0644 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u0627\u06cc\u06a9 \u0645\u0633\u0644\u0633\u0644 \u06a9\u0627\u0645 \u06a9\u06d2 \u0645\u062a\u0639\u062f\u062f \u0679\u06a9\u0691\u0648\u06ba \u0645\u06cc\u06ba \u062a\u0642\u0633\u06cc\u0645 \u06c1\u0648\u0646\u06d2 \u06a9\u0627 \u062e\u0637\u0631\u06c1 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u0644\u0645\u0628\u06d2 \u0648\u0642\u0641\u0648\u06ba \u06a9\u06d2 \u0646\u062a\u06cc\u062c\u06d2 \u0645\u06cc\u06ba \u06a9\u0645 \u0633\u06cc\u0634\u0646 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0627\u06cc\u0633\u06cc \u0633\u0631\u06af\u0631\u0645\u06cc\u0648\u06ba \u06a9\u06d2 \u0636\u0645 \u06c1\u0648\u0646\u06d2 \u06a9\u0627 \u062e\u0637\u0631\u06c1 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u062c\u0646 \u06a9\u0627 \u0627\u0635\u0644 \u0645\u06cc\u06ba \u06a9\u0648\u0626\u06cc \u062a\u0639\u0644\u0642 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<p>30 \u0645\u0646\u0679 \u0627\u06cc\u06a9 \u0645\u0639\u0642\u0648\u0644 \u0646\u0642\u0637\u06c1 \u0622\u063a\u0627\u0632 \u06c1\u06d2\u060c \u0627\u06cc\u06a9 \u0642\u0633\u0645 \u06a9\u0627 \u0645\u0633\u062a\u0642\u0644 \u062c\u0633 \u067e\u0631 \u0622\u067e \u0648\u0627\u067e\u0633 \u0622 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u06cc\u06c1 \u062f\u06cc\u06a9\u06be\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f \u0627\u06cc\u0688\u062c\u0633\u0679 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u0622\u067e \u06a9\u06d2 \u062a\u06be\u0631\u06cc\u0688\u0632 \u06a9\u06cc\u0633\u06d2 \u0646\u06a9\u0644\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-checkpoint\"><strong>\u0686\u0648\u06a9\u06cc<\/strong><\/h3>\n<p><code>buildSessions<\/code>    \u0627\u0628\u06be\u06cc \u062a\u06a9 \u06a9\u0648\u0626\u06cc UI \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u0627\u0633 \u06af\u0627\u0626\u06cc\u0688 \u0645\u06cc\u06ba \u0628\u0639\u062f \u0645\u06cc\u06ba \u0627\u067e\u0646\u0627 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u0688\u06cc\u0632\u0627\u0626\u0646 \u06a9\u0631\u062a\u06d2 \u0648\u0642\u062a\u060c \u0622\u067e \"\u0645\u06cc\u0631\u06d2 \u0631\u06cc\u06a9\u0627\u0631\u0688\u0632 \u062a\u0644\u0627\u0634 \u06a9\u0631\u06cc\u06ba\" \u06a9\u06d2 \u0633\u0627\u062a\u06be \"\u0633\u06cc\u0634\u0646 \u0628\u0646\u0627\u0626\u06cc\u06ba\" \u06a9\u06d2 \u0628\u0679\u0646 \u0633\u06d2 \u0644\u0646\u06a9 \u06a9\u0631\u06cc\u06ba \u06af\u06d2\u06d4<\/p>\n<p>\u0627\u0628\u06be\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u0645\u0642\u0635\u062f \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u0627\u0633 \u0633\u06cc\u06a9\u0634\u0646 \u0645\u06cc\u06ba \u06c1\u0631 \u0686\u06cc\u0632 \u06a9\u0648 \u0635\u0627\u0641 \u0633\u062a\u06be\u0631\u0627 \u0645\u0631\u062a\u0628 \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2\u06d4 <code>src\/pipeline\/noise.ts<\/code>, <code>src\/pipeline\/keywords.ts<\/code>\u0627\u067e \u0688\u06cc\u0679 <code>src\/db\/index.ts<\/code>\u0627\u0648\u0631 <code>src\/pipeline\/sessions.ts<\/code> \u06c1\u0631 \u0686\u06cc\u0632 \u06a9\u0648 \u063a\u0644\u0637\u06cc\u0648\u06ba \u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u0628\u0646\u0627\u0646\u0627 \u0686\u0627\u06c1\u0626\u06d2\u06d4 <code>getDB()<\/code> \u0627\u06af\u0644\u06cc \u0628\u0627\u0631 \u0627\u06cc\u06a9\u0633\u0679\u06cc\u0646\u0634\u0646 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0644\u0648\u0688 \u06c1\u0648\u0646\u06d2 \u067e\u0631\u060c \u0627\u0633\u06d2 \u0648\u0631\u0698\u0646 2 \u06a9\u06cc \u0627\u0637\u0644\u0627\u0639 \u062f\u06cc\u0646\u06cc \u0686\u0627\u06c1\u06cc\u06d2 (\u0688\u06cc\u0648 \u0679\u0648\u0644\u0632 \u0645\u06cc\u06ba \u062f\u06a9\u06be\u0627\u0626\u06cc \u062f\u06d2 \u0631\u06c1\u0627 \u06c1\u06d2)\u06d4 <strong>\u062f\u0631\u062e\u0648\u0627\u0633\u062a<\/strong> \u2192 <strong>\u0627\u0646\u0688\u06cc\u06a9\u0633\u0688 \u0688\u06cc \u0628\u06cc<\/strong> \u2192 <code>openloops<\/code>\u062f\u0648\u0646\u0648\u06ba \u0627\u0628 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0645\u06cc\u06ba \u062f\u0631\u062c \u06c1\u06cc\u06ba\u06d4 <code>raw_events<\/code> \u0627\u0648\u0631 <code>sessions<\/code> \u0628\u0637\u0648\u0631 \u0622\u0628\u062c\u06cc\u06a9\u0679 \u0627\u0633\u0679\u0648\u0631)\u06d4<\/p>\n<p>\u0633\u06cc\u0634\u0646\u0632 \u06a9\u06d2 \u062a\u06cc\u0627\u0631 \u06c1\u0648\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f\u060c \u0627\u06af\u0644\u0627 \u0633\u06cc\u06a9\u0634\u0646 \u0627\u0633 \u0633\u0679\u0631\u06a9\u0686\u0631\u0688 \u0644\u06cc\u06a9\u0646 \u0645\u0646\u0642\u0637\u0639 \u0688\u06cc\u0679\u0627 \u06a9\u0648 \u0644\u06d2 \u062c\u0627\u0626\u06d2 \u06af\u0627 \u0627\u0648\u0631 \u0633\u06cc\u0634\u0646\u0632 \u06a9\u0648 \u0627\u0646\u0679\u06cc\u0646\u0679 \u062a\u06be\u0631\u06cc\u0688\u0632 \u0645\u06cc\u06ba \u06af\u0631\u0648\u067e \u06a9\u0631\u06d2 \u06af\u0627\u060c \u062c\u0648 \u0627\u0633 \u067e\u0648\u0631\u06d2 \u067e\u0631\u0648\u062c\u06cc\u06a9\u0679 \u06a9\u0627 \u0646\u0627\u0645 \u06c1\u06d2\u06d4<\/p>\n<h2 id=\"heading-how-to-cluster-sessions-into-intent-threads\">\u0633\u06cc\u0634\u0646\u0648\u06ba \u06a9\u0648 \u0627\u0631\u0627\u062f\u06d2 \u06a9\u06d2 \u062f\u06be\u0627\u06af\u0648\u06ba \u0645\u06cc\u06ba \u06a9\u06cc\u0633\u06d2 \u06a9\u0644\u0633\u0679\u0631 \u06a9\u0631\u06cc\u06ba\u06d4<\/h2>\n<p>\u0627\u06cc\u06a9 \u0633\u06cc\u0634\u0646 \u0627\u0646 \u0648\u0627\u0642\u0639\u0627\u062a \u06a9\u0648 \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u062c\u0648\u0691\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u0648\u0642\u062a \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0633\u0627\u062a\u06be \u0642\u0631\u06cc\u0628 \u0648\u0627\u0642\u0639 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0644\u06cc\u06a9\u0646 \u062c\u0648 \u0622\u067e \u0648\u0627\u0642\u0639\u06cc \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u06a9\u0648\u0634\u0634 \u06a9\u0631 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba \u0648\u06c1 \u0634\u0627\u0630 \u0648 \u0646\u0627\u062f\u0631 \u06c1\u06cc \u0627\u06cc\u06a9 \u0633\u06cc\u0634\u0646 \u0645\u06cc\u06ba \u0641\u0679 \u0628\u06cc\u0679\u06be\u062a\u0627 \u06c1\u06d2\u06d4 \u0644\u06cc\u067e \u0679\u0627\u067e \u06a9\u0627 \u0645\u0648\u0627\u0632\u0646\u06c1 4 \u062f\u0646\u0648\u06ba \u0645\u06cc\u06ba 3 \u0633\u06cc\u0634\u0646\u0632 \u0645\u06cc\u06ba \u06a9\u06cc\u0627 \u062c\u0627 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 \u062c\u0646 \u0633\u0648\u0627\u0644\u0627\u062a \u06a9\u0648 \u0622\u067e \u062f\u06cc\u06a9\u06be\u0646\u0627 \u0686\u0627\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba \u0648\u06c1 \u062f\u0648 \u06c1\u0641\u062a\u0648\u06ba \u062a\u06a9 \u06c1\u0631 \u0686\u0646\u062f \u062f\u0646\u0648\u06ba \u0645\u06cc\u06ba 10 \u0645\u0646\u0679 \u06a9\u06d2 \u0644\u06cc\u06d2 \u067e\u0627\u067e \u0627\u067e \u06c1\u0648 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u0633 \u0633\u06cc\u06a9\u0634\u0646 \u0645\u06cc\u06ba\u060c \u06c1\u0645 \u0645\u062a\u0639\u0644\u0642\u06c1 \u0633\u06cc\u0634\u0646\u0632 \u06a9\u0648 \u0627\u0646\u0679\u06cc\u0646\u0679 \u062a\u06be\u0631\u06cc\u0688\u0632 \u0645\u06cc\u06ba \u06af\u0631\u0648\u067e \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u067e\u06be\u0631 \u06c1\u0631 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u0648 \u0627\u0633\u06a9\u0648\u0631 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u0622\u06cc\u0627 \u0627\u0648\u067e\u0646 \u0644\u0648\u067e \u06a9\u0633\u06cc \u062d\u0642\u06cc\u0642\u06cc \u0686\u06cc\u0632 \u06a9\u06cc \u0646\u0645\u0627\u0626\u0646\u062f\u06af\u06cc \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u06cc\u06c1 \u0627\u0628 \u0628\u06be\u06cc \u06a9\u062a\u0646\u0627 \u0632\u0646\u062f\u06c1 \u06c1\u06d2\u06d4<\/p>\n<p>\u062f\u0648 \u0641\u0627\u0626\u0644\u06cc\u06ba \u06cc\u06c1 \u06a9\u0631\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 <code>src\/pipeline\/ambient.ts<\/code> \u06cc\u06c1 \u0627\u06cc\u0633\u06d2 \u0688\u0648\u0645\u06cc\u0646\u0632 \u06a9\u0627 \u067e\u062a\u06c1 \u0644\u06af\u0627\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u0645\u062e\u0635\u0648\u0635 \u0627\u0631\u0627\u062f\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0622\u067e \u06a9\u06d2 \u0631\u0648\u0632\u0645\u0631\u06c1 \u06a9\u06d2 \u0645\u0639\u0645\u0648\u0644\u0627\u062a \u06a9\u0627 \u062d\u0635\u06c1 \u06c1\u06cc\u06ba\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u06cc\u06c1 \u063a\u06cc\u0631 \u0645\u062a\u0639\u0644\u0642\u06c1 \u0633\u06cc\u0634\u0646\u0632 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u063a\u0644\u0637 \u0645\u0645\u0627\u062b\u0644\u062a \u0646\u06c1\u06cc\u06ba \u067e\u06cc\u062f\u0627 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>src\/pipeline\/threads.ts<\/code> \u0627\u0635\u0644 \u06a9\u0644\u0633\u0679\u0631\u0646\u06af \u0627\u0648\u0631 \u0627\u0633\u06a9\u0648\u0631\u0646\u06af \u0627\u0646\u062c\u0627\u0645 \u062f\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-detecting-ambient-domains\">\u0642\u0631\u06cc\u0628\u06cc \u0688\u0648\u0645\u06cc\u0646 \u06a9\u0627 \u067e\u062a\u06c1 \u0644\u06af\u0627\u0646\u0627<\/h3>\n<p>\u06a9\u0686\u06be \u0688\u0648\u0645\u06cc\u0646\u0632 \u062a\u0642\u0631\u06cc\u0628\u0627\u064b \u06c1\u0631 \u0633\u06cc\u0634\u0646 \u0645\u06cc\u06ba \u0638\u0627\u06c1\u0631 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0642\u0637\u0639 \u0646\u0638\u0631 \u0627\u0633 \u06a9\u06d2 \u06a9\u06c1 \u0622\u067e \u06a9\u06cc\u0627 \u06a9\u0631 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba\u06d4 youtube.com \u06a9\u0648 \u0628\u06cc\u06a9 \u06af\u0631\u0627\u0624\u0646\u0688 \u0634\u0648\u0631 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u060c \u06c1\u0631 \u0631\u0648\u0632 \u06a9\u0645\u0679 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0688\u06cc\u0648\u0644\u067e\u0631\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2 github.com\u060c \u0627\u0648\u0631 claude.ai \u0627\u067e\u0646\u06d2 \u062c\u0646\u0631\u0644 \u0627\u0633\u0633\u0679\u0646\u0679 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 \u0627\u06af\u0631 \u0627\u0646 \u0688\u0648\u0645\u06cc\u0646\u0632 \u06a9\u06d2 \u0633\u06cc\u0634\u0646\u0632 \u06a9\u0627 \u06a9\u0644\u0633\u0679\u0631\u0646\u06af \u0627\u0633\u06cc \u0637\u0631\u062d \u0645\u0648\u0627\u0632\u0646\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0633 \u0637\u0631\u062d \u06cc\u06c1 \u06a9\u0633\u06cc \u062f\u0648\u0633\u0631\u06d2 \u0688\u0648\u0645\u06cc\u0646 \u06a9\u06d2 \u0633\u06cc\u0634\u0646\u0632 \u06a9\u0627 \u0645\u0648\u0627\u0632\u0646\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u062f\u0648 \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u063a\u06cc\u0631 \u0645\u062a\u0639\u0644\u0642\u06c1 \u0633\u06cc\u0634\u0646\u0632 \u0627\u06cc\u06a9 \u062c\u06cc\u0633\u06d2 \u0646\u0638\u0631 \u0622\u0626\u06cc\u06ba \u06af\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0648\u06c1 \u062f\u0648\u0646\u0648\u06ba youtube.com \u06a9\u0648 \u0645\u0627\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0633\u0628 \u06a9\u0686\u06be \u0622\u062e\u0631 \u06a9\u0627\u0631 \u0627\u06cc\u06a9 \u0628\u0691\u06d2 \u062f\u06be\u0627\u06af\u06d2 \u0645\u06cc\u06ba \u0636\u0645 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4<\/p>\n<p><code>ambient.ts<\/code>    \u06c1\u0645 \u062a\u0639\u062f\u062f \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u0631\u06a9\u06d2 \u0627\u0633 \u0645\u0633\u0626\u0644\u06d2 \u06a9\u0648 \u062d\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0645\u0648\u0636\u0648\u0639 \u0633\u06d2 \u0642\u0637\u0639 \u0646\u0638\u0631\u060c \u0627\u06af\u0631 \u06a9\u0648\u0626\u06cc \u0688\u0648\u0645\u06cc\u0646 \u0627\u067e\u0646\u06cc \u0633\u0631\u06af\u0631\u0645\u06cc \u06a9\u06cc \u0645\u062f\u062a \u06a9\u06d2 \u06a9\u0627\u0641\u06cc \u0628\u0691\u06d2 \u062d\u0635\u06d2 \u0645\u06cc\u06ba \u0638\u0627\u06c1\u0631 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u06cc\u06c1 \u0627\u06cc\u06a9 \u067e\u06cc\u0631\u06cc\u0641\u0631\u0644 \u0688\u0648\u0645\u06cc\u0646 \u06c1\u06d2\u06d4<\/p>\n<p>\u0628\u0646\u0627\u0646\u0627 <code>src\/pipeline\/ambient.ts<\/code>:<\/p>\n<pre><code class=\"language-typescript\">import type { Session } from \"..\/types\";\n\nexport const UBIQUITY_THRESHOLD = 0.6;\nexport const MIN_ACTIVE_DAYS = 3;\n\nfunction toDay(epochMs: number): string {\n  return new Date(epochMs).toDateString();\n}\n\nexport function detectAmbientDomains(sessions: Session[]): Set<string> {\n  const allEvents = sessions.flatMap((s) => s.events);\n\n  const activeDays = new Set(allEvents.map((e) => toDay(e.visitedAt)));\n  const totalActiveDays = activeDays.size;\n\n  if (totalActiveDays < MIN_ACTIVE_DAYS) {\n    return new Set();\n  }\n\n  const domainDayMap = new Map<string set=\"\">>();\n  for (const event of allEvents) {\n    const day = toDay(event.visitedAt);\n    if (!domainDayMap.has(event.domain)) {\n      domainDayMap.set(event.domain, new Set());\n    }\n    domainDayMap.get(event.domain)!.add(day);\n  }\n\n  const ambient = new Set<string>();\n  for (const [domain, days] of domainDayMap) {\n    const ubiquity = days.size \/ totalActiveDays;\n    if (ubiquity >= UBIQUITY_THRESHOLD) {\n      ambient.add(domain);\n      console.log(\n        `[openloops] ambient: ({domain} (){days.size}\/({totalActiveDays} days, ubiquity=){ubiquity.toFixed(2)})`\n      );\n    }\n  }\n\n  return ambient;\n}\n<\/string><\/string><\/string><\/code><\/pre>\n<p><code>toDay<\/code>    \u06cc\u06c1 \u06a9\u06cc\u0644\u0646\u0688\u0631 \u06a9\u06cc \u062a\u0627\u0631\u06cc\u062e \u06a9\u06d2 \u062a\u0627\u0631\u0648\u06ba \u0645\u06cc\u06ba \u0679\u0627\u0626\u0645 \u0627\u0633\u0679\u06cc\u0645\u067e \u06a9\u0648 \u06a9\u0645 \u06a9\u0631 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u06c1\u06cc \u062f\u0646 \u06a9\u06d2 \u062f\u0648 \u0648\u0627\u0642\u0639\u0627\u062a \u0639\u06cc\u0646 \u0648\u0642\u062a \u0633\u06d2 \u0642\u0637\u0639 \u0646\u0638\u0631 \u0627\u06cc\u06a9 \u06c1\u06cc \u06a9\u0644\u06cc\u062f \u067e\u06cc\u062f\u0627 \u06a9\u0631\u06cc\u06ba \u06af\u06d2\u06d4<\/p>\n<p><code>detectAmbientDomains<\/code>    \u067e\u06c1\u0644\u06d2\u060c \u06c1\u0645 \u062d\u0633\u0627\u0628 \u0644\u06af\u0627\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u0628\u0631\u0627\u0624\u0632\u0646\u06af \u06a9\u06cc \u0633\u0631\u06af\u0631\u0645\u06cc \u06a9\u062a\u0646\u06d2 \u062f\u0646\u0648\u06ba \u0645\u06cc\u06ba \u062a\u06be\u06cc\u06d4 \u062f\u0648\u0633\u0631\u06d2 \u0644\u0641\u0638\u0648\u06ba \u0645\u06cc\u06ba <code>totalActiveDays<\/code> - \u067e\u06be\u0631 \u06c1\u0645 \u06c1\u0631 \u0688\u0648\u0645\u06cc\u0646 \u0633\u06d2 \u062a\u0627\u0631\u06cc\u062e\u0648\u06ba \u06a9\u06d2 \u0633\u06cc\u0679 \u062a\u06a9 \u0627\u06cc\u06a9 \u0646\u0642\u0634\u06c1 \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0633 \u067e\u0631 \u0648\u06c1 \u0688\u0648\u0645\u06cc\u0646 \u0638\u0627\u06c1\u0631 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u0688\u0648\u0645\u06cc\u0646\u0632 \u06a9\u06cc \u06c1\u0631 \u062c\u06af\u06c1 \u06c1\u06d2\u06d4 <code>days.size \/ totalActiveDays<\/code>\u0641\u0639\u0627\u0644 \u062f\u0646\u0648\u06ba \u06a9\u0627 \u0641\u06cc\u0635\u062f \u062c\u0633 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0688\u0648\u0645\u06cc\u0646 \u0646\u0638\u0631 \u0622\u062a\u0627 \u06c1\u06d2\u06d4 \u0632\u06cc\u0627\u062f\u06c1 \u06cc\u0627 \u0632\u06cc\u0627\u062f\u06c1 <code>UBIQUITY_THRESHOLD<\/code> 0.6 \u0648\u0627\u067e\u0633 \u06a9\u06cc\u06d2 \u06af\u0626\u06d2 \u0633\u06cc\u0679 \u0645\u06cc\u06ba \u0634\u0627\u0645\u0644 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p><code>MIN_ACTIVE_DAYS<\/code>    \u0627\u0633 \u06a9\u06cc \u0648\u062c\u06c1 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u0635\u0631\u0641 \u0627\u06cc\u06a9 \u06cc\u0627 \u062f\u0648 \u062f\u0646 \u06a9\u06d2 \u0688\u06cc\u0679\u0627 \u06a9\u06d2 \u0633\u0627\u062a\u06be\u060c \u0622\u067e \u062c\u0648 \u0628\u06be\u06cc \u0688\u0648\u0645\u06cc\u0646 \u062f\u06cc\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba \u0648\u06c1 \u062a\u06a9\u0646\u06cc\u06a9\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0622\u067e \u06a9\u06d2 \u0641\u0639\u0627\u0644 \u062f\u0646\u0648\u06ba \u06a9\u06d2 100% \u067e\u0631 \u0638\u0627\u06c1\u0631 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0688\u06cc\u0679\u06cc\u06a9\u0679\u0631 \u06c1\u0631 \u0686\u06cc\u0632 \u06a9\u0648 \u0632\u06cc\u0631 \u0627\u0644\u062a\u0648\u0627\u0621 \u06a9\u06d2 \u0628\u0637\u0648\u0631 \u0646\u0634\u0627\u0646 \u0632\u062f \u06a9\u0631 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0641\u0639\u0627\u0644 \u062f\u0646\u0648\u06ba \u06a9\u06cc \u062a\u0639\u062f\u0627\u062f 3 \u0633\u06d2 \u06a9\u0645 \u06c1\u06d2\u060c \u062a\u0648 \u06c1\u0645 \u0627\u06cc\u06a9 \u062e\u0627\u0644\u06cc \u0633\u06cc\u0679 \u0648\u0627\u067e\u0633 \u06a9\u0631 \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u062f\u0631\u06cc\u0627\u0641\u062a \u06a9\u0648 \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u0686\u06be\u0648\u0691 \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u0633 \u0646\u0642\u0637\u06c1 \u0646\u0638\u0631 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0639\u0645\u0644\u06cc \u062a\u062c\u0627\u0631\u062a\u06cc \u062a\u0639\u0644\u0642\u0627\u062a \u06c1\u06cc\u06ba\u06d4 \u0627\u06af\u0631\u0686\u06c1 \u06cc\u06c1 \u0627\u0635\u0644 \u067e\u06cc\u0631\u06cc\u0641\u0631\u0644 \u0679\u0648\u0644\u0632 \u06a9\u06cc \u0635\u062d\u06cc\u062d \u0634\u0646\u0627\u062e\u062a \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u06cc\u06c1 \u0627\u0646 \u0688\u0648\u0645\u06cc\u0646\u0632 \u06a9\u0648 \u0628\u06be\u06cc \u062f\u0628\u0627 \u0633\u06a9\u062a\u0627 \u06c1\u06d2 \u062c\u0646 \u067e\u0631 \u06c1\u0645 \u0627\u06cc\u06a9 \u06c1\u0641\u062a\u06d2 \u0633\u06d2 \u0631\u0648\u0632\u0627\u0646\u06c1 \u0628\u06c1\u062a \u0632\u06cc\u0627\u062f\u06c1 \u062a\u062d\u0642\u06cc\u0642 \u06a9\u0631 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba\u060c \u062c\u0648 60% \u06a9\u06cc \u062d\u062f \u06a9\u0648 \u0628\u06be\u06cc \u0639\u0628\u0648\u0631 \u06a9\u0631 \u0644\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p><code>UBIQUITY_THRESHOLD<\/code>    \u06cc\u06c1 \u0627\u0633 \u0633\u0645\u062c\u06be\u0648\u062a\u06c1 \u06a9\u0627 \u06c1\u06cc\u0646\u0688\u0644 \u06c1\u06d2\u06d4 \u0627\u0648\u0646\u0686\u0627\u0626\u06cc \u0645\u06cc\u06ba \u0627\u0636\u0627\u0641\u06c1 \u062d\u0642\u06cc\u0642\u06cc \u0645\u062d\u06cc\u0637\u06cc \u0634\u0648\u0631 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u067e\u06cc\u0634 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0642\u06cc\u0645\u062a \u067e\u0631 \u063a\u0644\u0637 \u0645\u062b\u0628\u062a \u06a9\u0648 \u06a9\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-extending-the-database-for-intent-threads\">\u0627\u0631\u0627\u062f\u06d2 \u06a9\u06d2 \u062f\u06be\u0627\u06af\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u06a9\u06cc \u062a\u0648\u0633\u06cc\u0639<\/h3>\n<p>\u062f\u06be\u0627\u06af\u0648\u06ba \u06a9\u0648 \u0627\u0646 \u06a9\u06cc \u0627\u067e\u0646\u06cc \u0627\u0633\u0679\u0648\u0631\u06cc\u062c \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4 \u06a9\u0631\u06cc\u0634 <code>DB_VERSION<\/code> 3 \u0645\u06cc\u06ba \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 <code>intent_threads<\/code>\u0627\u0646\u0688\u06cc\u06a9\u0633\u0688 <code>lastSeen<\/code>\u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u0633\u0628 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u062d\u0627\u0644\u06cc\u06c1 \u0641\u0639\u0627\u0644 \u062a\u06be\u0631\u06cc\u0688\u0632 \u06a9\u0648 \u0638\u0627\u06c1\u0631 \u06a9\u0631 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-typescript\">import type { RawEvent, Session, IntentThread } from \"..\/types\";\n\ninterface OpenloopsDB extends DBSchema {\n  raw_events: {\n    key: string;\n    value: RawEvent;\n    indexes: { by_visitedAt: number };\n  };\n  sessions: {\n    key: string;\n    value: Session;\n    indexes: { by_startedAt: number };\n  };\n  intent_threads: {\n    key: string;\n    value: IntentThread;\n    indexes: { by_lastSeen: number };\n  };\n}\n\nconst DB_VERSION = 3;\n\nexport function getDB(): Promise<idbpdatabase>> {\n  if (!_db) {\n    _db = openDB<openloopsdb>(DB_NAME, DB_VERSION, {\n      upgrade(db) {\n        if (!db.objectStoreNames.contains(\"raw_events\")) {\n          const s = db.createObjectStore(\"raw_events\", { keyPath: \"id\" });\n          s.createIndex(\"by_visitedAt\", \"visitedAt\");\n        }\n        if (!db.objectStoreNames.contains(\"sessions\")) {\n          const s = db.createObjectStore(\"sessions\", { keyPath: \"id\" });\n          s.createIndex(\"by_startedAt\", \"startedAt\");\n        }\n        if (!db.objectStoreNames.contains(\"intent_threads\")) {\n          const s = db.createObjectStore(\"intent_threads\", { keyPath: \"id\" });\n          s.createIndex(\"by_lastSeen\", \"lastSeen\");\n        }\n      },\n    });\n  }\n  return _db;\n}\n<\/openloopsdb><\/idbpdatabase><\/code><\/pre>\n<p>\u067e\u06be\u0631 \u0645\u0645\u0627\u062b\u0644 \u0645\u062f\u062f\u06af\u0627\u0631 \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-typescript\">export async function putThreads(threads: IntentThread[]): Promise<void> {\n  if (threads.length === 0) return;\n  const db = await getDB();\n  const tx = db.transaction(\"intent_threads\", \"readwrite\");\n  await Promise.all([...threads.map(\n}\n\nexport async function clearThreads(): Promise<void> {\n  const db = await getDB();\n  return db.clear(\"intent_threads\");\n}\n\nexport async function getAllThreads(): Promise<intentthread> {\n  const db = await getDB();\n  const index = db\n    .transaction(\"intent_threads\", \"readonly\")\n    .store.index(\"by_lastSeen\");\n\n  let cursor = await index.openCursor(null, \"prev\");\n  const results: IntentThread[] = [];\n  while (cursor) {\n    results.push(cursor.value);\n    cursor = await cursor.continue();\n  }\n  return results;\n}\n\nexport async function getThreadCount(): Promise<number> {\n  const db = await getDB();\n  return db.count(\"intent_threads\");\n}\n<\/number><\/intentthread><\/void><\/void><\/code><\/pre>\n<p><code>putThreads<\/code>, <code>clearThreads<\/code>\u0627\u0648\u0631 <code>getThreadCount<\/code> \u06cc\u06c1 \u0627\u0633\u06cc \u0637\u0631\u0632 \u06a9\u06cc \u067e\u06cc\u0631\u0648\u06cc \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>sessions<\/code> \u0648\u06c1 \u0645\u062f\u062f\u06af\u0627\u0631 \u062c\u0633 \u0646\u06d2 \u067e\u06c1\u0644\u06d2 \u0645\u06cc\u0631\u06cc \u0645\u062f\u062f \u06a9\u06cc \u062a\u06be\u06cc\u06d4 <code>getAllThreads<\/code> \u06cc\u06c1\u0627\u06ba \u0639\u062c\u06cc\u0628 \u0628\u0627\u062a \u06c1\u06d2: \u0628\u062c\u0627\u0626\u06d2 <code>getAllFromIndex<\/code>\u0627\u06af\u0631 \u06cc\u06c1 \u0635\u0631\u0641 \u0686\u0691\u06be\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u06a9\u0631\u0633\u0631 \u06a9\u06be\u0644 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>by_lastSeen<\/code> \u06a9\u0648 <code>\"prev\"<\/code> \u0633\u0645\u062a \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u062f\u0633\u062a\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0645\u0646\u062a\u0642\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 \u0627\u0633 \u0633\u06d2 \u0622\u067e \u06a9\u0648 \u0622\u0631\u0688\u0631 \u06a9\u06cc\u06d2 \u06af\u0626\u06d2 \u062a\u06be\u0631\u06cc\u0688\u0632 \u0645\u0644\u06cc\u06ba \u06af\u06d2\u060c \u062c\u0648 \u062d\u0627\u0644 \u06c1\u06cc \u0645\u06cc\u06ba \u0641\u0639\u0627\u0644 \u0633\u06d2 \u0634\u0631\u0648\u0639 \u06c1\u0648 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba\u060c \u06cc\u0639\u0646\u06cc \u0648\u06c1 \u0622\u0631\u0688\u0631 \u062c\u0648 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u0627\u0633\u0679\u06cc\u0679\u0633 \u06af\u0631\u0648\u067e \u06a9\u0627\u0631\u0688\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0686\u0627\u06c1\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-clustering-sessions-into-threads\">\u062f\u06be\u0627\u06af\u0648\u06ba \u0645\u06cc\u06ba \u06a9\u0644\u0633\u0679\u0631 \u0633\u06cc\u0634\u0646\u0632<\/h3>\n<p>\u0627\u06cc\u06a9 \u0628\u0627\u0631 \u062c\u0628 \u0622\u0633 \u067e\u0627\u0633 \u06a9\u06d2 \u0688\u0648\u0645\u06cc\u0646\u0632 \u06a9\u06cc \u0634\u0646\u0627\u062e\u062a \u06c1\u0648\u062c\u0627\u0626\u06d2 <code>src\/pipeline\/threads.ts<\/code> \u0627\u0628 \u0627\u0635\u0644 \u06a9\u0627\u0645 \u0622\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2 \u0633\u06cc\u0634\u0646\u0632 \u06a9\u0648 \u062a\u06be\u0631\u06cc\u0688\u0632 \u0645\u06cc\u06ba \u06af\u0631\u0648\u067e \u06a9\u0631\u0646\u0627 \u0627\u0648\u0631 \u067e\u06be\u0631 \u06c1\u0631 \u0633\u06cc\u0634\u0646 \u06a9\u0648 \u0627\u0633\u06a9\u0648\u0631 \u06a9\u0631\u0646\u0627 \u0627\u0648\u0631 \u062f\u0631\u062c\u06c1 \u0628\u0646\u062f\u06cc \u06a9\u0631\u0646\u0627\u06d4<\/p>\n<p>\u0646\u0642\u0637\u06c1 \u0646\u0638\u0631 \u0644\u0627\u0644\u0686\u06cc \u0627\u062c\u062a\u0645\u0627\u0639\u06cc \u06a9\u0644\u0633\u0679\u0631\u0646\u06af \u06c1\u06d2\u06d4 \u062a\u0627\u0631\u06cc\u062e \u06a9\u06d2 \u0645\u0637\u0627\u0628\u0642 \u0633\u06cc\u0634\u0646\u0632 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u062c\u0627\u0626\u06cc\u06ba \u0627\u0648\u0631 \u06c1\u0631 \u0633\u06cc\u0634\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0633\u0628 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0645\u0644\u062a\u06d2 \u062c\u0644\u062a\u06d2 \u0645\u0648\u062c\u0648\u062f\u06c1 \u062a\u06be\u0631\u06cc\u0688 \u0645\u06cc\u06ba \u0636\u0645 \u06c1\u0648 \u062c\u0627\u0626\u06cc\u06ba \u06cc\u0627 \u0627\u06af\u0631 \u06a9\u0686\u06be \u0645\u0644\u062a\u0627 \u062c\u0644\u062a\u0627 \u0646\u06c1 \u06c1\u0648 \u062a\u0648 \u0646\u06cc\u0627 \u062a\u06be\u0631\u06cc\u0688 \u0634\u0631\u0648\u0639 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<p>\u06c1\u0645 \u062f\u0631\u0622\u0645\u062f\u060c \u067e\u06cc\u0645\u0627\u0646\u06c1 \u0645\u0633\u062a\u0642\u0644\u060c \u0627\u0648\u0631 \u0645\u0645\u0627\u062b\u0644\u062a \u06a9\u06d2 \u062d\u0633\u0627\u0628 \u0633\u06d2 \u0634\u0631\u0648\u0639 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-typescript\">import { getAllSessions, clearThreads, putThreads } from \"..\/db\/index\";\nimport { detectAmbientDomains } from \".\/ambient\";\nimport { hashId } from \"..\/lib\/util\";\nimport type { Session, IntentThread } from \"..\/types\";\n\nexport const SIMILARITY_THRESHOLD = 0.15;\nexport const DOMAIN_WEIGHT = 0.5;\nexport const KEYWORD_WEIGHT = 0.5;\n\ninterface ThreadBuilder {\n  id: string;\n  sessions: Session[];\n  domainSet: Set<string>;\n  keywordSet: Set<string>;\n}\n\nfunction jaccard(a: Set<string>, b: Set<string>): number {\n  if (a.size === 0 && b.size === 0) return 0;\n  let intersection = 0;\n  for (const item of a) {\n    if (b.has(item)) intersection++;\n  }\n  const union = a.size + b.size - intersection;\n  return intersection \/ union;\n}\n\nfunction similarity(\n  session: Session,\n  thread: ThreadBuilder,\n  ambient: Set<string>\n): number {\n  const sessionDomains  = new Set(session.domains.filter((d) => !ambient.has(d)));\n  const threadDomains   = new Set([...thread.domainSet].filter((d) => !ambient.has(d)));\n  const sessionKeywords = new Set(session.keywords);\n\n  const domainScore   = jaccard(sessionDomains, threadDomains);\n  const keywordScore  = jaccard(sessionKeywords, thread.keywordSet);\n\n  return DOMAIN_WEIGHT * domainScore + KEYWORD_WEIGHT * keywordScore;\n}\n<\/string><\/string><\/string><\/string><\/string><\/code><\/pre>\n<p><code>ThreadBuilder<\/code>    \u0627\u06cc\u06a9 \u062a\u063a\u06cc\u0631 \u067e\u0630\u06cc\u0631 \u062c\u0645\u0639 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u0627 \u062c\u0648 \u0635\u0631\u0641 \u06a9\u0644\u0633\u0679\u0631\u0646\u06af \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u0639\u0646\u06cc \u06cc\u06c1 \u0627\u0633 \u062f\u06be\u0627\u06af\u06d2 \u06a9\u0627 \u0627\u0645\u062a\u0632\u0627\u062c \u06c1\u06d2 \u062c\u0633 \u0645\u06cc\u06ba \u0633\u06cc\u0634\u0646 \u06c1\u0648 \u0631\u06c1\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0628 \u062a\u06a9 \u062f\u06cc\u06a9\u06be\u06d2 \u06af\u0626\u06d2 \u062a\u0645\u0627\u0645 \u0688\u0648\u0645\u06cc\u0646\u0632 \u0627\u0648\u0631 \u06a9\u0644\u06cc\u062f\u06cc \u0627\u0644\u0641\u0627\u0638\u06d4 <code>jaccard<\/code> \u0645\u0639\u06cc\u0627\u0631\u06cc \u0633\u06cc\u0679 \u0645\u0645\u0627\u062b\u0644\u062a \u06a9\u0627 \u067e\u06cc\u0645\u0627\u0646\u06c1 \u0686\u0648\u0631\u0627\u06c1\u06d2 \u06a9\u0627 \u0633\u0627\u0626\u0632 \u06c1\u06d2 \u062c\u0633\u06d2 \u06cc\u0648\u0646\u06cc\u0646 \u06a9\u06d2 \u0633\u0627\u0626\u0632 \u0633\u06d2 \u062a\u0642\u0633\u06cc\u0645 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062c\u0648 0 \u06a9\u0648 0 \u0633\u06d2 \u062a\u0642\u0633\u06cc\u0645 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u062f\u0648 \u062e\u0627\u0644\u06cc \u0633\u06cc\u0679\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 0 \u0644\u0648\u0679\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p><code>similarity<\/code>    \u0627\u06cc\u06a9 \u0627\u0645\u06cc\u062f\u0648\u0627\u0631 \u06a9\u06d2 \u0633\u06cc\u0634\u0646 \u06a9\u0627 \u0627\u06cc\u06a9 \u062c\u0627\u0631\u06cc \u062a\u06be\u0631\u06cc\u0688 \u0633\u06d2 \u0645\u0648\u0627\u0632\u0646\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0634\u062a\u0631\u0627\u06a9 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u062f\u0648\u0646\u0648\u06ba \u0641\u0631\u06cc\u0642 \u0688\u0648\u0645\u06cc\u0646\u0632 \u06a9\u0627 \u0645\u0648\u0627\u0632\u0646\u06c1 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u067e\u0691\u0648\u0633\u06cc \u0688\u0648\u0645\u06cc\u0646\u0632 \u06a9\u0648 \u0641\u0644\u0679\u0631 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>youtube.com<\/code> \u06cc\u06c1 \u0622\u067e \u06a9\u06d2 \u0633\u06a9\u0648\u0631 \u0645\u06cc\u06ba \u06a9\u0628\u06be\u06cc \u062d\u0635\u06c1 \u0646\u06c1\u06cc\u06ba \u0688\u0627\u0644\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633 \u06a9\u06d2 \u0628\u0639\u062f \u06c1\u0645 \u0688\u0648\u0645\u06cc\u0646 Jaccard \u0633\u06a9\u0648\u0631 \u0627\u0648\u0631 \u06a9\u0644\u06cc\u062f\u06cc \u0644\u0641\u0638 Jaccard \u0633\u06a9\u0648\u0631 \u06a9\u0627 \u0627\u0644\u06af \u0627\u0644\u06af \u062d\u0633\u0627\u0628 \u0644\u06af\u0627\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0646 \u06a9\u0648 \u0627\u0633 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062c\u0648\u0691\u062a\u06d2 \u06c1\u06cc\u06ba: <code>DOMAIN_WEIGHT<\/code> \u0627\u0648\u0631 <code>KEYWORD_WEIGHT<\/code>\u062f\u0648\u0646\u0648\u06ba 0.5 \u06c1\u06cc\u06ba\u060c \u062c\u0633 \u06a9\u0627 \u06a9\u06c1\u0646\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0688\u0648\u0645\u06cc\u0646 \u0688\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646 \u0627\u0648\u0631 \u06a9\u0644\u06cc\u062f\u06cc \u0627\u0644\u0641\u0627\u0638 \u06a9\u06cc \u0646\u0642\u0644 \u062d\u062a\u0645\u06cc \u0646\u0645\u0628\u0631 \u0645\u06cc\u06ba \u0628\u0631\u0627\u0628\u0631 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u06af\u0644\u0627\u060c \u06a9\u0644\u0633\u0679\u0631\u0646\u06af \u0644\u0648\u067e \u062e\u0648\u062f \u06c1\u06d2:<\/p>\n<pre><code class=\"language-typescript\">function clusterSessions(\n  sessions: Session[],\n  ambient: Set<string>\n): ThreadBuilder[] {\n  const threads: ThreadBuilder[] = [];\n\n  for (const session of sessions) {\n    let bestThread: ThreadBuilder | null = null;\n    let bestScore = 0;\n\n    for (const thread of threads) {\n      const score = similarity(session, thread, ambient);\n      if (score > bestScore) {\n        bestScore = score;\n        bestThread = thread;\n      }\n    }\n\n    if (bestThread && bestScore >= SIMILARITY_THRESHOLD) {\n      bestThread.sessions.push(session);\n      for (const d of session.domains)  bestThread.domainSet.add(d);\n      for (const k of session.keywords) bestThread.keywordSet.add(k);\n    } else {\n      threads.push({\n        id: hashId(session.id, session.startedAt),\n        sessions: [session],\n        domainSet:  new Set(session.domains),\n        keywordSet: new Set(session.keywords),\n      });\n    }\n  }\n\n  return threads;\n}\n<\/string><\/code><\/pre>\n<p><code>clusterSessions<\/code>    \u067e\u0631 \u0628\u06be\u0631\u0648\u0633\u06c1 \u06a9\u0631\u06cc\u06ba <code>sessions<\/code> \u06cc\u06c1 \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u062a\u0627\u0631\u06cc\u062e \u06a9\u06d2 \u0644\u062d\u0627\u0638 \u0633\u06d2 \u0645\u0646\u0638\u0645 \u06c1\u06d2\u06d4 <code>getAllSessions<\/code> \u0627\u0646\u0688\u06cc\u06a9\u0633 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u06af\u0627\u0631\u0646\u0679\u06cc \u0634\u062f\u06c1\u06d4 \u06c1\u0631 \u0633\u06cc\u0634\u0646 \u0645\u06cc\u06ba\u060c \u06c1\u0645 \u0627\u0628 \u062a\u06a9 \u0628\u0646\u0627\u0626\u06d2 \u06af\u0626\u06d2 \u062a\u0645\u0627\u0645 \u062a\u06be\u0631\u06cc\u0688\u0632 \u06a9\u0648 \u0627\u0633\u06a9\u0648\u0631 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0628\u06c1\u062a\u0631\u06cc\u0646 \u0645\u06cc\u0686 \u0631\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u06cc\u06a9 \u0628\u0627\u0631 \u062c\u0628 \u0648\u06c1 \u0627\u0639\u0644\u06cc \u0627\u0633\u06a9\u0648\u0631 \u0635\u0627\u0641 \u06c1\u0648\u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>SIMILARITY_THRESHOLD<\/code>\u0633\u06cc\u0634\u0646\u0632 \u06a9\u0648 \u0636\u0645 \u06a9\u0631 \u062f\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0646 \u06a9\u06d2 \u0688\u0648\u0645\u06cc\u0646\u0632 \u0627\u0648\u0631 \u06a9\u0644\u06cc\u062f\u06cc \u0627\u0644\u0641\u0627\u0638 \u062a\u06be\u0631\u06cc\u0688\u0632 \u06a9\u06d2 \u0645\u062c\u0645\u0648\u0639\u06cc \u0633\u06cc\u0679 \u0645\u06cc\u06ba \u0634\u0627\u0645\u0644 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u0633 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2 \u06a9\u06c1 \u0628\u0639\u062f \u06a9\u06d2 \u0633\u06cc\u0634\u0646\u0632 \u06a9\u0627 \u0645\u0648\u0627\u0632\u0646\u06c1 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u06d2 \u0633\u06cc\u0634\u0646 \u0633\u06d2 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <em>\u067e\u0648\u0631\u06cc<\/em> \u0645\u062c\u0645\u0648\u0639\u06cc \u062a\u0627\u0631\u06cc\u062e \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0646\u06c1 \u0635\u0631\u0641 \u0628\u06cc\u062c \u0633\u06cc\u0634\u0646\u0632\u06d4 \u0627\u06af\u0631 \u06a9\u0686\u06be \u0628\u06be\u06cc \u062d\u062f \u06a9\u0648 \u0635\u0627\u0641 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0633\u06cc\u0634\u0646 \u0627\u06cc\u06a9 \u0646\u0626\u06d2 \u062f\u06be\u0627\u06af\u06d2 \u06a9\u0627 \u0628\u06cc\u062c \u0628\u0646 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u06cc\u06a9 \u062d\u0642\u06cc\u0642\u06cc \u062f\u0646\u06cc\u0627 \u06a9\u06cc \u0645\u062b\u0627\u0644 \u0633\u06d2 \u067e\u062a\u06c1 \u0686\u0644\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u06cc\u06c1 \u06a9\u06cc\u0633\u06d2 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u0641\u0631\u0636 \u06a9\u0631\u06cc\u06ba <code>detectAmbientDomains<\/code> \u0648\u0627\u067e\u0633\u06cc <code>{ youtube.com }<\/code>\u062a\u06cc\u0646 \u0633\u06cc\u0634\u0646 \u0645\u0646\u062f\u0631\u062c\u06c1 \u0630\u06cc\u0644 \u062a\u0631\u062a\u06cc\u0628 \u0645\u06cc\u06ba \u0622\u062a\u06d2 \u06c1\u06cc\u06ba:<\/p>\n<pre><code class=\"language-plaintext\">S1: domains=[stackoverflow.com, typescriptlang.org]\n    keywords=[typescript, generics, interface, mapped]\n\nS2: domains=[stackoverflow.com, typescriptlang.org, github.com]\n    keywords=[typescript, generics, utility, types]\n\nS3: domains=[python.org, docs.python.org]\n    keywords=[python, async, await, coroutine]\n<\/code><\/pre>\n<p>S1 \u067e\u06c1\u0644\u06d2 \u0622\u062a\u0627 \u06c1\u06d2\u06d4 \u0628\u06cc\u062c \u06a9\u0627 \u062f\u06be\u0627\u06af\u06c1 A \u0627\u06af\u0631 \u0627\u0628\u06be\u06cc \u062a\u06a9 \u06a9\u0648\u0626\u06cc \u062f\u06be\u0627\u06af\u06c1 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 <code>domainSet = {stackoverflow.com, typescriptlang.org}<\/code>, <code>keywordSet = {typescript, generics, interface, mapped}<\/code>.<\/p>\n<p>S2 \u062a\u06be\u0631\u06cc\u0688 A \u06a9\u06d2 \u062e\u0644\u0627\u0641 \u0627\u0633\u06a9\u0648\u0631 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0646\u06c1 \u06c1\u06cc \u0633\u06cc\u0679 \u0645\u06cc\u06ba \u0622\u0633 \u067e\u0627\u0633 \u06a9\u0627 \u0645\u0627\u062d\u0648\u0644 \u0634\u0627\u0645\u0644 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 <code>youtube.com<\/code>\u060c \u062a\u0648 \u06a9\u0686\u06be \u0628\u06be\u06cc \u0641\u0644\u0679\u0631 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0688\u0648\u0645\u06cc\u0646 \u062c\u06cc\u06a9\u0627\u0631\u0688 \u06c1\u06d2\u06d4 <code>|{stackoverflow.com, typescriptlang.org}| \/ |{stackoverflow.com, typescriptlang.org, github.com}|<\/code>\u06cc\u0627 2\/3 \u2252 0.667\u06d4 \u06a9\u0644\u06cc\u062f\u06cc \u0644\u0641\u0638 \u062c\u06cc\u06a9\u0627\u0631\u0688 <code>|{typescript, generics}| \/ |{typescript, generics, interface, mapped, utility, types}|<\/code>\u06cc\u0627 2\/6 \u2252 0.333\u06d4 \u0645\u0634\u062a\u0631\u06a9\u06c1 \u0645\u0645\u0627\u062b\u0644\u062a \u06c1\u06d2\u06d4 <code>0.5 \u00d7 0.667 + 0.5 \u00d7 0.333 = 0.5<\/code>\u0622\u0631\u0627\u0645 \u0633\u06d2 \u067e\u06cc\u0679 <code>SIMILARITY_THRESHOLD<\/code> (0.15)\u060c \u062a\u0648 S2 \u06a9\u0648 \u062a\u06be\u0631\u06cc\u0688 A \u0645\u06cc\u06ba \u0636\u0645 \u06a9\u0631 \u062f\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0627\u0633 \u06a9\u06d2 \u0633\u06cc\u0679 \u06a9\u0648 \u0628\u0691\u06be\u0627 \u06a9\u0631 \u0634\u0627\u0645\u0644 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2: <code>github.com<\/code>, <code>utility<\/code>\u0627\u0648\u0631 <code>types<\/code>.<\/p>\n<p>S3 \u062a\u06be\u0631\u06cc\u0688 A \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633\u06a9\u0648\u0631 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4 \u062a\u06be\u0631\u06cc\u0688 A \u0627\u0648\u0631 \u062a\u06be\u0631\u06cc\u0688 A \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0628\u0627\u0644\u06a9\u0644 \u06a9\u0648\u0626\u06cc \u0627\u0648\u0648\u0631\u0644\u06cc\u067e \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 <code>{python.org, docs.python.org}<\/code> \u0686\u0648\u0646\u06a9\u06c1 \u0648\u06c1 \u062a\u06be\u0631\u06cc\u0688 A \u0645\u06cc\u06ba \u0688\u0648\u0645\u06cc\u0646\u0632 \u06cc\u0627 \u0645\u0637\u0644\u0648\u0628\u06c1 \u0627\u0644\u0641\u0627\u0638 \u06a9\u06d2 \u0633\u06cc\u0679 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u06c1\u06cc\u06ba\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u0627\u0646 \u06a9\u06d2 \u062c\u06cc\u06a9\u0627\u0631\u0688 \u0627\u0633\u06a9\u0648\u0631 \u062a\u0645\u0627\u0645 0 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0646 \u06a9\u06cc \u0645\u0634\u062a\u0631\u06a9\u06c1 \u0645\u0645\u0627\u062b\u0644\u062a 0 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u062d\u062f \u0633\u06d2 \u0646\u06cc\u0686\u06d2 \u06c1\u06d2\u060c \u0627\u0633 \u0644\u06cc\u06d2 S3 \u0627\u06cc\u06a9 \u0646\u06cc\u0627 \u062a\u06be\u0631\u06cc\u0688 B \u062a\u06cc\u0627\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0646\u062a\u06cc\u062c\u06c1: \u062a\u06be\u0631\u06cc\u0688 \u0627\u06d2 \u062f\u0648 \u0633\u06cc\u0634\u0646\u0632 \u0645\u06cc\u06ba \u0679\u0627\u0626\u067e \u0627\u0633\u06a9\u0631\u067e\u0679 \u0631\u06cc\u0633\u0631\u0686 \u0631\u06a9\u06be\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u062a\u06be\u0631\u06cc\u0688 \u0628\u06cc \u0627\u067e\u0646\u0627 \u0627\u0632\u06af\u0631 \u0633\u06cc\u0634\u0646 \u0631\u06a9\u06be\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p><code>SIMILARITY_THRESHOLD<\/code>    \u0627\u0633 \u0641\u0627\u0626\u0644 \u0645\u06cc\u06ba \u0648\u0627\u062d\u062f \u0633\u0628 \u0633\u06d2 \u0627\u06c1\u0645 \u0645\u0633\u062a\u0642\u0644 \u06c1\u06d2\u060c \u0627\u0648\u0631 0.15 \u0627\u0633 \u0633\u06d2 \u06a9\u0645 \u06c1\u06d2 \u062c\u0633 \u06a9\u0627 \u0622\u067e 50\/50 \u0648\u0632\u0646 \u0648\u0627\u0644\u06d2 \u062c\u06cc\u06a9\u0627\u0631\u0688 \u0633\u06a9\u0648\u0631 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0646\u062f\u0627\u0632\u06c1 \u0644\u06af\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 0.3 \u062c\u06cc\u0633\u06cc \u0627\u0628\u062a\u062f\u0627\u0626\u06cc \u0642\u062f\u0631 \u0632\u06cc\u0627\u062f\u06c1 \u0627\u0635\u0648\u0644\u06cc \u0644\u06af\u062a\u06cc \u06c1\u06d2\u06d4 \u0627\u0633 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2 \u06a9\u06c1 \u062f\u0648 \u0633\u06cc\u0634\u0646\u0632 \u06a9\u0648 \u0627\u067e\u0646\u06d2 \u0645\u0634\u062a\u0631\u06a9\u06c1 \u0688\u0648\u0645\u06cc\u0646\u0632 \u0627\u0648\u0631 \u06a9\u0644\u06cc\u062f\u06cc \u0627\u0644\u0641\u0627\u0638 \u06a9\u0627 \u062a\u0642\u0631\u06cc\u0628\u0627\u064b 1\/3 \u0634\u06cc\u0626\u0631 \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2 \u0627\u0633 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u06a9\u06c1 \u0648\u06c1 \u0627\u06cc\u06a9 \u06c1\u06cc \u062f\u06be\u0627\u06af\u06d2 \u06a9\u0627 \u062d\u0635\u06c1 \u0633\u0645\u062c\u06be\u06d2 \u062c\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<p>\u0644\u06cc\u06a9\u0646 \u062c\u0628 \u0645\u06cc\u06ba \u0627\u0633\u06d2 \u0627\u067e\u0646\u06cc \u0627\u0635\u0644 \u06af\u0646\u062f\u06cc \u0628\u0631\u0627\u0624\u0632\u0646\u06af \u06c1\u0633\u0679\u0631\u06cc \u06a9\u06d2 \u062e\u0644\u0627\u0641 \u0686\u0644\u0627\u062a\u0627 \u06c1\u0648\u06ba\u060c \u062a\u0648 \u06cc\u06c1 \u0628\u06c1\u062a \u0633\u0627\u0631\u06d2 \u062f\u06be\u0627\u06af\u0648\u06ba \u06a9\u0648 \u062c\u0646\u0645 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 \u0648\u06c1 \u0633\u06cc\u0634\u0646 \u062c\u0648 \u0648\u0627\u0636\u062d \u0637\u0648\u0631 \u067e\u0631 \u0627\u06cc\u06a9 \u06c1\u06cc \u0645\u0637\u0627\u0644\u0639\u06c1 \u06a9\u0627 \u062d\u0635\u06c1 \u062a\u06be\u06d2 \u0644\u06cc\u06a9\u0646 0.3 \u06a9\u0648 \u0635\u0627\u0641 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0627\u0641\u06cc \u0645\u0637\u0644\u0648\u0628\u06c1 \u0627\u0644\u0641\u0627\u0638 \u06a9\u0627 \u0627\u0634\u062a\u0631\u0627\u06a9 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u062a\u06be\u0627 \u0648\u06c1 \u0627\u0644\u06af \u0627\u0644\u06af \u062a\u06be\u0631\u06cc\u0688\u0632 \u0645\u06cc\u06ba \u062a\u0642\u0633\u06cc\u0645 \u06c1\u0648 \u06af\u0626\u06d2\u06d4<\/p>\n<p>\u062d\u062f \u06a9\u0648 0.15 \u062a\u06a9 \u06a9\u0645 \u06a9\u0631\u0646\u0627 \u0633\u06cc\u0634\u0646 \u06a9\u0648 \u06a9\u0645\u0632\u0648\u0631 \u06c1\u0648\u0646\u06d2 \u062f\u06cc\u062a\u0627 \u06c1\u06d2 \u0644\u06cc\u06a9\u0646 \u067e\u06be\u0631 \u0628\u06be\u06cc \u062d\u0642\u06cc\u0642\u06cc \u0633\u06af\u0646\u0644 \u0645\u06cc\u06ba \u0636\u0645 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0635\u0631\u0641 \u0627\u06cc\u06a9 \u0688\u0648\u0645\u06cc\u0646 \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u06a9\u0644\u06cc\u062f\u06cc \u0644\u0641\u0638 \u06a9\u0627 \u0627\u0634\u062a\u0631\u0627\u06a9 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u062f\u0648 \u0633\u06cc\u0634\u0646\u0632 \u067e\u06c1\u0644\u06d2 \u06c1\u06cc 0.15 \u0633\u06d2 \u062a\u062c\u0627\u0648\u0632 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062c\u0633 \u06a9\u06d2 \u0646\u062a\u06cc\u062c\u06d2 \u0645\u06cc\u06ba \u06a9\u0645 \u0645\u0633\u0644\u0633\u0644 \u062a\u06be\u0631\u06cc\u0688\u0632 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0648 \u062f\u0631\u062d\u0642\u06cc\u0642\u062a \u0622\u067e \u06a9\u06cc \u0628\u0631\u0627\u0624\u0632\u0646\u06af \u06c1\u0633\u0679\u0631\u06cc \u06a9\u06cc \u0638\u0627\u06c1\u0631\u06cc \u0634\u06a9\u0644 \u0633\u06d2 \u0645\u0644\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u06cc\u06c1 \u0627\u06cc\u06a9 \u0642\u0633\u0645 \u06a9\u0627 \u0645\u0633\u062a\u0642\u0644 \u06c1\u06d2 \u062c\u0633\u06d2 \u0622\u067e \u067e\u06c1\u0644\u06d2 \u0627\u0635\u0648\u0644\u0648\u06ba \u0633\u06d2 \u0627\u062e\u0630 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u062a\u062c\u0631\u0628\u0627\u062a\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0627\u06cc\u0688\u062c\u0633\u0679 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba (\u0627\u06cc\u06a9 \u062a\u06be\u0631\u06cc\u0688 \u0628\u0646\u0627\u0626\u06cc\u06ba\u060c \u0646\u062a\u0627\u0626\u062c \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0633\u06d2 \u0627\u06cc\u0688\u062c\u0633\u0679 \u06a9\u0631\u06cc\u06ba)\u06d4<\/p>\n<p><code>buildThreads<\/code>\u0627\u0633 \u06a9\u06d2 \u0628\u0639\u062f\u060c \u06c1\u0645 \u062a\u0645\u0627\u0645 \u062f\u06be\u0627\u06af\u0648\u06ba \u06a9\u06d2 \u0639\u0646\u0648\u0627\u0646\u060c \u0642\u0633\u0645\u060c \u062d\u06cc\u062b\u06cc\u062a\u060c \u0634\u06c1\u0631\u062a\u060c \u0627\u0648\u0631 \u0633\u0631\u0641\u06c1\u0631\u0633\u062a \u0645\u0637\u0644\u0648\u0628\u06c1 \u0627\u0644\u0641\u0627\u0638 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u06cc\u06a9 \u0679\u06cc\u0628\u0644 \u067e\u0631\u0646\u0679 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u062a\u0627\u06a9\u06c1 \u0622\u067e \u0627\u0646\u06c1\u06cc\u06ba \u0627\u067e\u0646\u06cc \u0622\u0646\u06a9\u06be\u0648\u06ba \u0633\u06d2 \u062f\u06cc\u06a9\u06be \u0633\u06a9\u06cc\u06ba\u06d4 \u0627\u06af\u0631 \u062f\u0648 \u062a\u06be\u0631\u06cc\u0688\u0632 \u0648\u0627\u0636\u062d \u0637\u0648\u0631 \u067e\u0631 \u0627\u06cc\u06a9 \u062f\u0648\u0633\u0631\u06d2 \u0633\u06d2 \u062a\u0639\u0644\u0642 \u0631\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba \u062a\u0648 \u06a9\u0645 \u0642\u062f\u0631 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 <code>SIMILARITY_THRESHOLD<\/code>. \u0627\u06af\u0631 \u06a9\u0633\u06cc \u062a\u06be\u0631\u06cc\u0688 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0639\u0646\u0648\u0627\u0646\u0627\u062a \u0627\u06cc\u06a9 \u062f\u0648\u0633\u0631\u06d2 \u0633\u06d2 \u062c\u0691\u06d2 \u06c1\u0648\u0626\u06d2 \u06c1\u06cc\u06ba \u062c\u0648 \u0648\u0627\u0636\u062d \u0637\u0648\u0631 \u067e\u0631 \u0627\u06cc\u06a9 \u062f\u0648\u0633\u0631\u06d2 \u0633\u06d2 \u0645\u062a\u0639\u0644\u0642 \u0646\u06c1\u06cc\u06ba \u06c1\u06cc\u06ba \u062a\u0648 \u0627\u0633 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u0648 \u0628\u0691\u06be\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-scoring-and-classifying-threads\">\u062a\u06be\u0631\u06cc\u0688 \u0627\u0633\u06a9\u0648\u0631\u0646\u06af \u0627\u0648\u0631 \u062f\u0631\u062c\u06c1 \u0628\u0646\u062f\u06cc<\/h3>\n<p>\u06a9\u0644\u0633\u0679\u0631\u0646\u06af \u0633\u06cc\u0634\u0646 \u06af\u0631\u0648\u067e\u0633 \u0628\u0646\u0627\u062a\u06cc \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u0633\u06cc\u0634\u0646 \u06af\u0631\u0648\u067e\u0633 \u0627\u0628\u06be\u06cc \u062a\u06a9 \u0646\u06c1\u06cc\u06ba \u06c1\u06cc\u06ba\u06d4 <code>IntentThread<\/code>. \u0628\u0627\u0642\u06cc <code>threads.ts<\/code> \u06c1\u0631 \u06af\u0631\u0648\u067e \u06a9\u0648 \u0627\u06cc\u06a9 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0633 \u0645\u06cc\u06ba \u0627\u0646\u0633\u0627\u0646\u06cc \u067e\u0691\u06be\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u0633\u06af\u0646\u0644\u0632 \u06a9\u0627 \u0627\u06cc\u06a9 \u0633\u06cc\u0679 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u0627\u0633 \u06a9\u06cc \u0642\u0633\u0645\u060c \u0627\u0639\u062a\u0645\u0627\u062f \u06a9\u0627 \u0627\u0633\u06a9\u0648\u0631\u060c \u062d\u06cc\u062b\u06cc\u062a \u0627\u0648\u0631 \u0648\u062c\u06c1 \u0628\u06cc\u0627\u0646 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0686\u0646\u062f \u0686\u06be\u0648\u0679\u06d2 \u0645\u062f\u062f\u06af\u0627\u0631 \u067e\u06c1\u0644\u06d2 \u0622\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-typescript\">export const BUYING_WORDS: readonly string[] = [\n  \"vs\", \"versus\", \"alternative\", \"alternatives\",\n  \"comparison\", \"pricing\", \"price\", \"review\", \"reviews\", \"best\",\n];\n\nexport const LEARNING_WORDS: readonly string[] = [\n  \"how to\", \"tutorial\", \"tutorials\", \"docs\", \"documentation\",\n  \"guide\", \"learn\", \"example\", \"examples\", \"crash course\", \"introduction\",\n];\n\nconst STATUS_ACTIVE_MS  = 48 * 60 * 60 * 1000;\nconst STATUS_STALLED_MS = 7  * 24 * 60 * 60 * 1000;\n\nfunction toTitleCase(s: string): string {\n  return s.charAt(0).toUpperCase() + s.slice(1);\n}\n\nfunction findMatches(titles: string[], wordList: readonly string[]): string[] {\n  const lower = titles.map(\n  const found = new Set<string>();\n\n  for (const word of wordList) {\n    const isPhrase = word.includes(\" \");\n    for (const title of lower) {\n      if (isPhrase) {\n        if (title.includes(word)) found.add(word);\n      } else {\n        const tokens = title.split(\/[^a-z0-9]+\/);\n        if (tokens.includes(word)) found.add(word);\n      }\n    }\n  }\n\n  return [...found];\n}\n\nfunction toCalendarDay(epochMs: number): string {\n  return new Date(epochMs).toDateString();\n}\n<\/string><\/code><\/pre>\n<p><code>BUYING_WORDS<\/code>    \u0627\u0648\u0631 <code>LEARNING_WORDS<\/code> \u06cc\u06c1 \u0627\u06cc\u06a9 \u0686\u06be\u0648\u0679\u06cc \u0630\u062e\u06cc\u0631\u06c1 \u0627\u0644\u0641\u0627\u0638 \u06c1\u06d2 \u062c\u0648 \u0627\u0631\u0627\u062f\u06d2 \u06a9\u0627 \u0627\u0638\u06c1\u0627\u0631 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4 <code>findMatches<\/code> \u06cc\u06c1 \u0627\u0646 \u0627\u0644\u0641\u0627\u0638 \u0645\u06cc\u06ba \u0633\u06d2 \u06a9\u0633\u06cc \u0627\u06cc\u06a9 \u06a9\u06d2 \u062e\u0644\u0627\u0641 \u0635\u0641\u062d\u06c1 \u06a9\u06d2 \u0639\u0646\u0648\u0627\u0646\u0627\u062a \u06a9\u06cc \u0641\u06c1\u0631\u0633\u062a \u06a9\u0648 \u0686\u06cc\u06a9 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u06c1\u06cc \u0627\u0644\u0641\u0627\u0638 \u0627\u0648\u0631 \u0641\u0642\u0631\u06d2 \u06a9\u0648 \u0645\u062e\u062a\u0644\u0641 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u062f\u06cc\u06a9\u06be\u062a\u0627 \u06c1\u06d2\u06d4 \u06a9\u062b\u06cc\u0631 \u0644\u0641\u0638\u06cc \u0622\u0626\u0679\u0645\u0632 \u062c\u06cc\u0633\u06d2 \"\u0637\u0631\u06cc\u0642\u06c1\" \u06a9\u0648 \u0630\u06cc\u0644\u06cc \u0627\u0633\u0679\u0631\u0646\u06af \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u062d\u0644 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0648\u06c1 \u06a9\u0627\u0641\u06cc \u0645\u062e\u0635\u0648\u0635 \u06c1\u06cc\u06ba \u06a9\u06c1 \u063a\u0644\u0637 \u0645\u062b\u0628\u062a \u06c1\u0648\u0646\u06d2 \u06a9\u0627 \u0627\u0645\u06a9\u0627\u0646 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u062a\u0627\u06c1\u0645\u060c \u0648\u0627\u062d\u062f \u0627\u0644\u0641\u0627\u0638 \u062c\u06cc\u0633\u06d2 \"\u062c\u0627\u0626\u0632\u06c1\" \u06a9\u0648 \u0639\u0646\u0648\u0627\u0646 \u0633\u06d2 \u063a\u06cc\u0631 \u062d\u0631\u0648\u0641\u0650 \u0639\u062f\u062f\u06cc \u062d\u0631\u0648\u0641 \u0633\u06d2 \u0627\u0644\u06af \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0645\u06a9\u0645\u0644 \u0679\u0648\u06a9\u0646 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u062d\u0644 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0633 \u0627\u0645\u062a\u06cc\u0627\u0632 \u06a9\u06d2 \u0628\u063a\u06cc\u0631\u060c \"\u062c\u0627\u0626\u0632\u06c1\" \u0628\u06be\u06cc \"\u0645\u062c\u0645\u0648\u0639\u06cc \u062c\u0627\u0626\u0632\u06c1\" \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u0645\u0645\u0627\u062b\u0644 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u0627\u060c \u062c\u0633 \u06a9\u06d2 \u0646\u062a\u06cc\u062c\u06d2 \u0645\u06cc\u06ba \"\u0645\u062c\u0645\u0648\u0639\u06cc \u062c\u0627\u0626\u0632\u06c1\" \u0635\u0641\u062d\u06c1 \u0633\u06d2 \u0645\u062a\u0639\u0644\u0642 \u062f\u06be\u0627\u06af\u0648\u06ba \u06a9\u06cc \u063a\u0644\u0637 \u062f\u0631\u062c\u06c1 \u0628\u0646\u062f\u06cc \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u06cc\u06d4 <code>toTitleCase<\/code> \u0627\u0648\u0631 <code>toCalendarDay<\/code> \u0627\u06af\u0644\u0627 \u0627\u06cc\u06a9 \u0686\u06be\u0648\u0679\u0627 \u0641\u0627\u0631\u0645\u06cc\u0679\u0646\u06af \u0645\u062f\u062f\u06af\u0627\u0631 \u06c1\u06d2 \u062c\u0648 \u06af\u0631\u06cc\u0688\u0646\u06af \u0641\u0646\u06a9\u0634\u0646 \u0645\u06cc\u06ba \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0633\u06a9\u0648\u0631 \u06a9\u06cc \u062a\u0642\u0631\u06cc\u0628\u060c <code>scoreThread<\/code>\u067e\u0631\u0648\u062c\u06cc\u06a9\u0679 \u06a9\u06cc \u0633\u0628 \u0633\u06d2 \u0637\u0648\u06cc\u0644 \u062e\u0635\u0648\u0635\u06cc\u062a \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u06cc\u06c1 \u0648\u06c1 \u062c\u06af\u06c1 \u06c1\u06d2 \u062c\u06c1\u0627\u06ba \u0627\u0628 \u062a\u06a9 \u062c\u0645\u0639 \u06a9\u06cc\u06d2 \u06af\u0626\u06d2 \u062a\u0645\u0627\u0645 \u0633\u06af\u0646\u0644\u0632 \u06a9\u0648 \u0641\u06cc\u0644\u0688\u0632 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>IntentThread<\/code>:<\/p>\n<pre><code class=\"language-typescript\">function scoreThread(builder: ThreadBuilder): IntentThread {\n  const { sessions, keywordSet } = builder;\n\n  const firstSeen  = sessions[0].startedAt;\n  const lastSeen   = sessions[sessions.length - 1].endedAt;\n\n  const allEvents  = sessions.flatMap((s) => s.events);\n  const totalEvents = allEvents.length;\n  const daySet     = new Set(allEvents.map((e) => toCalendarDay(e.visitedAt)));\n  const distinctDays = daySet.size;\n\n  const allTitles      = allEvents.map((e) => e.title);\n  const buyingMatches  = findMatches(allTitles, BUYING_WORDS);\n  const learningMatches = findMatches(allTitles, LEARNING_WORDS);\n\n  let type: IntentThread[\"type\"];\n  if (buyingMatches.length > 0) {\n    type = \"buying\";\n  } else if (learningMatches.length > 0) {\n    type = \"learning\";\n  } else if (distinctDays > 5 && sessions.length >= 3) {\n    type = \"planning\";\n  } else if (totalEvents >= 3) {\n    type = \"research\";\n  } else {\n    type = \"unclassified\";\n  }\n\n  const age = Date.now() - lastSeen;\n  const status: IntentThread[\"status\"] =\n    age < STATUS_ACTIVE_MS  ? \"active\"  :\n    age < STATUS_STALLED_MS ? \"stalled\" :\n    \"dormant\";\n\n  const confidence = parseFloat((\n    Math.min(distinctDays \/ 5, 1) * 0.35 +\n    Math.min(sessions.length \/ 5, 1) * 0.25 +\n    Math.min(totalEvents \/ 20, 1)  * 0.20 +\n    (type !== \"unclassified\" ? 1 : 0)  * 0.20\n  ).toFixed(2));\n\n  const signals: string[] = [];\n\n  if (distinctDays > 1)\n    signals.push(`revisited across ${distinctDays} days`);\n  if (type === \"buying\" && buyingMatches.length > 0)\n    signals.push(`comparison language: ${buyingMatches.join(\", \")}`);\n  if (type === \"learning\" && learningMatches.length > 0)\n    signals.push(`learning language: ${learningMatches.join(\", \")}`);\n  signals.push(`({sessions.length} session){sessions.length !== 1 ? \"s\" : \"\"}`);\n  if (totalEvents > 5)\n    signals.push(`${totalEvents} total events`);\n  if (type === \"planning\")\n    signals.push(\"sustained activity across many days\");\n\n  const ageDays = Math.floor(age \/ (24 * 60 * 60 * 1000));\n  if (ageDays === 0)       signals.push(\"last active today\");\n  else if (ageDays === 1)  signals.push(\"last active yesterday\");\n  else                     signals.push(`last active ${ageDays} days ago`);\n\n  const title =\n    [...keywordSet].slice(0, 3).map(toTitleCase).join(\" \") || \"Untitled Thread\";\n\n  return {\n    id: builder.id,\n    title,\n    sessions,\n    type,\n    confidence,\n    status,\n    firstSeen,\n    lastSeen,\n    distinctDays,\n    signals,\n  };\n}\n<\/code><\/pre>\n<p>\u06cc\u06c1\u0627\u06ba \u062f\u06cc\u06a9\u06be\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0628\u06c1\u062a \u06a9\u0686\u06be \u06c1\u06d2\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u06c1\u0631 \u0645\u06cc\u062f\u0627\u0646 \u0645\u06cc\u06ba \u0686\u06c1\u0644 \u0642\u062f\u0645\u06cc \u06a9\u0631\u0646\u0627 \u0642\u0627\u0628\u0644 \u0642\u062f\u0631 \u06c1\u06d2\u06d4 <code>IntentThread<\/code> \u062d\u0633\u0627\u0628\u06cc \u062a\u0631\u062a\u06cc\u0628 \u0645\u06cc\u06ba\u06d4<\/p>\n<p><code>firstSeen<\/code>    \u0627\u0648\u0631 <code>lastSeen<\/code> \u0633\u06cc\u062f\u06be\u0627 \u0628\u0627\u0624\u0646\u0688\u0631\u06cc \u0633\u06cc\u0634\u0646 \u0633\u06d2 \u0628\u0627\u06c1\u0631 \u0622\u0624\u06d4 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 <code>sessions<\/code> \u06a9\u0644\u0633\u0679\u0631\u0646\u06af \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u062a\u0627\u0631\u06cc\u062e\u06cc \u062a\u0631\u062a\u06cc\u0628 \u0645\u06cc\u06ba \u067e\u06c1\u0646\u0686\u062a\u0627 \u06c1\u06d2\u06d4 <code>distinctDays<\/code> \u0627\u0633\u06cc \u06a9\u06cc\u0644\u0646\u0688\u0631 \u062f\u0646 \u06a9\u06cc \u06a9\u0645\u06cc \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 <code>ambient.ts<\/code>. \u0627\u0633 \u0628\u0627\u0631\u060c \u06c1\u0645 \u062d\u0633\u0627\u0628 \u0644\u06af\u0627\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u06cc\u06c1 \u06a9\u0648\u0646 \u0633\u0627 \u062f\u0646 \u06c1\u06d2\u06d4 <em>\u0627\u0633 \u062a\u06be\u0631\u06cc\u0688 \u0645\u06cc\u06ba<\/em> \u0633\u0631\u06af\u0631\u0645\u06cc \u06a9\u06d2 \u062f\u0646\u0648\u06ba \u06a9\u06cc \u06a9\u0644 \u062a\u0639\u062f\u0627\u062f \u0633\u06d2 \u0642\u0637\u0639 \u0646\u0638\u0631 \u0627\u06cc\u0648\u0646\u0679 \u062c\u0627\u0631\u06cc \u0631\u06c1\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u06a9\u06cc \u0637\u0631\u0641 \u0633\u06d2 \u062f\u0631\u062c\u06c1 \u0628\u0646\u062f\u06cc <code>type<\/code> \u06cc\u06c1 \u062c\u06be\u0644\u06a9 \u0631\u06c1\u0627 \u06c1\u06d2\u060c \u0644\u06c1\u0630\u0627 \u0622\u0631\u0688\u0631 \u0627\u06c1\u0645 \u06c1\u06d2\u06d4 \u062a\u0642\u0627\u0628\u0644\u06cc \u0632\u0628\u0627\u0646 (<code>BUYING_WORDS<\/code>) \u067e\u06c1\u0644\u06d2 \u0686\u06cc\u06a9 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633 \u06a9\u06cc \u0648\u062c\u06c1 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u062f\u0648 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u06a9\u0627 \u0645\u0648\u0627\u0632\u0646\u06c1 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u062a\u06be\u0631\u06cc\u0688\u0632 \"\u062e\u0631\u06cc\u062f \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba\" \u0686\u0627\u06c1\u06d2 \u0627\u0646 \u0645\u06cc\u06ba \u0679\u06cc\u0648\u0679\u0648\u0631\u06cc\u0644 \u067e\u06cc\u062c\u0632 \u0628\u06be\u06cc \u0634\u0627\u0645\u0644 \u06c1\u0648\u06ba\u06d4 \u06cc\u06c1 \u0645\u0648\u0627\u0632\u0646\u06c1 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0645\u0636\u0628\u0648\u0637 \u0627\u0631\u0627\u062f\u06d2 \u06a9\u0627 \u0627\u0634\u0627\u0631\u06c1 \u06c1\u06d2\u06d4<\/p>\n<p>\u0632\u0628\u0627\u0646 \u0633\u06cc\u06a9\u06be\u0646\u0627 \u0622\u06af\u06d2 \u0622\u062a\u0627 \u06c1\u06d2\u06d4 \u062c\u0628 \u0633\u06d2\u060c <code>planning<\/code> 5 \u062f\u0646 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0686\u0644\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u062f\u06be\u0627\u06af\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u062d\u0641\u0648\u0638 \u06c1\u06d2\u06d4 <em>\u0627\u0648\u0631<\/em> \u0627\u06cc\u06a9 \u06af\u06c1\u0631\u0627\u0626\u06cc \u0633\u06d2 \u062a\u062c\u0632\u06cc\u06c1 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0645\u0633\u062a\u0642\u0644\u060c \u062a\u06a9\u0631\u0627\u0631\u06cc \u0633\u0631\u06af\u0631\u0645\u06cc \u06a9\u06d2 \u06a9\u0645 \u0627\u0632 \u06a9\u0645 \u062a\u06cc\u0646 \u0633\u06cc\u0634\u0646 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<p><code>research<\/code>    \u0627\u0633 \u06a9\u0627 \u0645\u0642\u0635\u062f \u06a9\u0633\u06cc \u0628\u06be\u06cc \u0627\u06cc\u0633\u06cc \u0686\u06cc\u0632 \u06a9\u0648 \u0634\u0627\u0645\u0644 \u06a9\u0631\u0646\u0627 \u06c1\u06d2 \u062c\u0633 \u0645\u06cc\u06ba \u062a\u06cc\u0646 \u06cc\u0627 \u0627\u0633 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0648\u0627\u0642\u0639\u0627\u062a \u0634\u0627\u0645\u0644 \u06c1\u0648\u06ba \u062c\u0648 \u06a9\u0633\u06cc \u062e\u0627\u0635 \u0686\u06cc\u0632 \u0633\u06d2 \u0645\u06cc\u0644 \u0646\u06c1\u06cc\u06ba \u06a9\u06be\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>unclassified<\/code> \u062c\u0648 \u0631\u06c1 \u06af\u06cc\u0627 \u06c1\u06d2 \u0648\u06c1 \u062a\u06be\u0631\u06cc\u0688\u0632 \u06c1\u06cc\u06ba \u062c\u0646 \u0645\u06cc\u06ba \u0639\u0627\u0645 \u0637\u0648\u0631 \u067e\u0631 \u0627\u0639\u062a\u0645\u0627\u062f \u06a9\u06d2 \u0644\u06cc\u06d2 \u0628\u06c1\u062a \u06a9\u0645 \u0633\u0631\u06af\u0631\u0645\u06cc \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p><code>status<\/code>    \u06cc\u06c1 \u062e\u0627\u0644\u0635\u062a\u0627\u064b \u0627\u06cc\u06a9 \u0641\u0646\u06a9\u0634\u0646 \u06c1\u06d2 \u06a9\u06c1 \u06cc\u06c1 \u06a9\u062a\u0646\u0627 \u0639\u0631\u0635\u06c1 \u067e\u06c1\u0644\u06d2 \u062a\u06be\u0627\u06d4 <code>lastSeen<\/code> \u067e\u0686\u06be\u0644\u0627: 48 \u06af\u06be\u0646\u0679\u06d2 \u0633\u06d2 \u0628\u06be\u06cc \u06a9\u0645 <code>active<\/code>7 \u062f\u0646 \u0633\u06d2 \u06a9\u0645 <code>stalled<\/code>\u062c\u0648 \u0628\u06be\u06cc \u067e\u0631\u0627\u0646\u0627 \u06c1\u06d2 <code>dormant<\/code>.<\/p>\n<p><code>confidence<\/code>    \u06cc\u06c1 \u0686\u0627\u0631 \u0633\u06af\u0646\u0644\u0632 \u06a9\u0627 \u0648\u0632\u0646\u06cc \u0645\u062c\u0645\u0648\u0639\u06c1 \u06c1\u06d2\u060c \u06c1\u0631 \u0627\u06cc\u06a9 \u06a9\u0648 \u0648\u0632\u0646 \u0645\u06cc\u06ba \u0688\u0627\u0644\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 1 \u067e\u0631 \u0645\u0639\u0645\u0648\u0644 \u0628\u0646\u0627\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06c1\u0630\u0627 \u06a9\u0644 1 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0646\u06c1\u06cc\u06ba \u06c1\u0648 \u0633\u06a9\u062a\u0627\u06d4 <code>distinctDays \/ 5<\/code>\u06cc\u06c1 1 \u062a\u06a9 \u0645\u062d\u062f\u0648\u062f \u06c1\u06d2\u060c 35% \u062a\u06a9 \u062d\u0635\u06c1 \u0688\u0627\u0644\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 5 \u062f\u0646 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u06a9\u06d2 \u0627\u0646\u0641\u0631\u0627\u062f\u06cc \u062f\u0646\u0648\u06ba \u06a9\u0648 \u0627\u0633 \u0645\u062d\u0648\u0631 \u067e\u0631 \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f \u0633\u0645\u062c\u06be\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>sessions.length \/ 5<\/code>\u0632\u06cc\u0627\u062f\u06c1 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 1 \u06a9\u0627 \u062d\u0635\u06c1 25% \u062a\u06a9 \u06c1\u06d2\u06d4 <code>totalEvents \/ 20<\/code>\u0632\u06cc\u0627\u062f\u06c1 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 1 \u06a9\u06d2 \u0633\u0627\u062a\u06be 20% \u062a\u06a9 \u062a\u0639\u0627\u0648\u0646 \u06a9\u0631\u06cc\u06ba\u06d4 \u0627\u0648\u0631 \u0686\u0627\u06c1\u06d2 <code>type<\/code> \u06a9\u06d2 \u0639\u0644\u0627\u0648\u06c1 <code>unclassified<\/code> \u0622\u062e\u0631\u06cc 20% \u0633\u0628 \u06cc\u0627 \u06a9\u0686\u06be \u0628\u06be\u06cc \u0646\u06c1\u06cc\u06ba \u0628\u0648\u0646\u0633 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u062f\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u062c\u0646 \u062a\u06be\u0631\u06cc\u0688\u0632 \u067e\u0631 5 \u062f\u0646\u0648\u06ba\u060c 5 \u0633\u06cc\u0634\u0646\u0632\u060c \u06cc\u0627 20 \u06cc\u0627 \u0627\u0633 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0627\u06cc\u0648\u0646\u0679\u0633 \u067e\u0631 \u0646\u0638\u0631\u062b\u0627\u0646\u06cc \u06a9\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0627\u0646\u06c1\u06cc\u06ba \u0635\u0627\u0641 \u0637\u0648\u0631 \u067e\u0631 \u062f\u0631\u062c\u06c1 \u0628\u0646\u062f\u06cc \u0628\u06be\u06cc \u06a9\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06d2\u060c \u0627\u0646\u06c1\u06cc\u06ba 1.0 \u06a9\u0627 \u0627\u0633\u06a9\u0648\u0631 \u0645\u0644\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06cc\u06a9 \u062f\u06be\u0627\u06af\u06c1 \u062c\u0648 \u062f\u0648 \u0627\u06cc\u0648\u0646\u0679\u0633 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0648\u0627\u062d\u062f \u0633\u06cc\u0634\u0646 \u06c1\u06d2 \u0627\u0648\u0631 \u0635\u0641\u0631 \u06a9\u06d2 \u0642\u0631\u06cc\u0628 \u06a9\u0648\u0626\u06cc \u062f\u0631\u062c\u06c1 \u0628\u0646\u062f\u06cc \u0627\u0633\u06a9\u0648\u0631 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<p><code>signals<\/code>    \u0627\u0639\u062a\u0645\u0627\u062f \u06a9\u06d2 \u0627\u0633\u06a9\u0648\u0631 \u0627\u0648\u0631 \u062d\u06cc\u062b\u06cc\u062a \u06a9\u0627 \u0627\u06cc\u06a9 \u0633\u0627\u062f\u06c1 \u0627\u0646\u06af\u0631\u06cc\u0632\u06cc \u0622\u0688\u0679 \u0679\u0631\u06cc\u0644\u06d4 \u06cc\u06c1 \u0628\u062a\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u062a\u06be\u0631\u06cc\u0688 \u062c\u06cc\u0633\u0627 \u0646\u0638\u0631 \u0622\u062a\u0627 \u06c1\u06d2\u060c \u062f\u06be\u0627\u06af\u06d2 \u067e\u0631 \u0646\u0638\u0631\u062b\u0627\u0646\u06cc \u06a9\u06cc\u06d2 \u062c\u0627\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u062f\u0646\u0648\u06ba \u06a9\u06cc \u062a\u0639\u062f\u0627\u062f\u060c \u0645\u0648\u0627\u0632\u0646\u06c1 \u06cc\u0627 \u0633\u06cc\u06a9\u06be\u0646\u06d2 \u0648\u0627\u0644\u06cc \u0632\u0628\u0627\u0646\u06cc\u06ba\u060c \u0633\u06cc\u0634\u0646\u0632 \u0627\u0648\u0631 \u0627\u06cc\u0648\u0646\u0679\u0633 \u06a9\u06cc \u062a\u0639\u062f\u0627\u062f\u060c \u0627\u0648\u0631 \u06cc\u06c1 \u06a9\u062a\u0646\u06cc \u062f\u06cc\u0631 \u062a\u06a9 \u0641\u0639\u0627\u0644 \u0631\u06c1\u0627\u06d4 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u0627\u0633 \u06a9\u06cc \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u0646\u0645\u0627\u0626\u0646\u062f\u06af\u06cc \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0622\u062e\u0631 \u06a9\u0627\u0631 <code>title<\/code> \u067e\u0644\u06cc\u0633 \u06c1\u0648\u0644\u0688\u0631: \u062a\u06be\u0631\u06cc\u0688 \u062c\u0645\u0639 \u06a9\u0631\u0646\u06d2 \u0645\u06cc\u06ba \u0633\u0631\u0641\u06c1\u0631\u0633\u062a 3 \u06a9\u0644\u06cc\u062f\u06cc \u0627\u0644\u0641\u0627\u0638\u06d4 <code>keywordSet<\/code>\u0639\u0646\u0648\u0627\u0646 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0634\u0631\u0648\u0639 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0633\u067e\u06cc\u0633 \u0633\u06d2 \u062c\u0691\u0627 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u060c \u06cc\u0627 <code>\"Untitled Thread\"<\/code> \u0627\u06af\u0631 \u06a9\u0686\u06be \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<p>\u06cc\u06c1 \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u06a9\u0645\u0632\u0648\u0631 \u06c1\u06d2\u06d4 AI \u0644\u06cc\u0628\u0644\u0646\u06af \u0627\u0633 \u06af\u0627\u0626\u06cc\u0688 \u0645\u06cc\u06ba \u0628\u0639\u062f \u0645\u06cc\u06ba \u0627\u0633 heuristic \u0639\u0646\u0648\u0627\u0646 \u06a9\u06cc \u062c\u06af\u06c1 \u0644\u06d2 \u0644\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 <code>summary<\/code> \u0627\u0648\u0631 <code>nextStep<\/code>\u062a\u06be\u0631\u06cc\u0688 \u06a9\u06d2 \u0627\u0635\u0644 \u0645\u0648\u0627\u062f \u067e\u0631 \u0645\u0628\u0646\u06cc \u06a9\u0686\u06be \u06c1\u06d2 (\u0644\u06cc\u06a9\u0646 \u062a\u06be\u0631\u06cc\u0688 \u0627\u0633 \u0642\u062f\u0645 \u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u0642\u0627\u0628\u0644 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06c1\u06cc\u06ba)\u06d4<\/p>\n<h3 id=\"heading-putting-it-together\">\u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u0631\u06a9\u06be\u0648<\/h3>\n<p><code>buildThreads<\/code>    \u06cc\u06c1 \u0627\u0633 \u0633\u06cc\u06a9\u0634\u0646 \u0645\u06cc\u06ba \u06c1\u0631 \u0686\u06cc\u0632 \u06a9\u0648 \u062c\u0648\u0691\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-typescript\">export async function buildThreads(): Promise<{ sessions: number; threads: number }> {\n  const sessions = await getAllSessions();\n\n  if (sessions.length === 0) {\n    await clearThreads();\n    return { sessions: 0, threads: 0 };\n  }\n\n  const ambient = detectAmbientDomains(sessions);\n\n  const builders = clusterSessions(sessions, ambient);\n\n  const substantive = builders.filter(\n    (b) => !(b.sessions.length === 1 && b.sessions[0].events.length < 3)\n  );\n\n  const threads = substantive.map(scoreThread);\n\n  await clearThreads();\n  await putThreads(threads);\n\n  console.table(\n    threads.map(\n      title:        t.title,\n      type:         t.type,\n      status:       t.status,\n      confidence:   t.confidence,\n      distinctDays: t.distinctDays,\n      sessions:     t.sessions.length,\n      events:       t.sessions.reduce((n, s) => n + s.events.length, 0),\n      keywords:     [...new Set(t.sessions.flatMap((s) => s.keywords))].slice(0, 5).join(\", \"),\n    }))\n  );\n\n  return { sessions: sessions.length, threads: threads.length };\n}\n<\/code><\/pre>\n<p>\u0622\u0631\u0688\u0631 \u06cc\u06c1\u0627\u06ba \u0627\u06c1\u0645 \u06c1\u06d2\u06d4 <code>detectAmbientDomains<\/code> \u06a9\u0644\u0633\u0679\u0631\u0646\u06af \u06c1\u0648\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u06c1\u0631 \u0633\u06cc\u0634\u0646 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u0627\u06cc\u0645\u0628\u06cc\u0626\u0646\u0679 \u0688\u0679\u06cc\u06a9\u0634\u0646 \u0686\u0644\u0627\u0626\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0627\u0633\u06d2 \u06cc\u06c1 \u062c\u0627\u0646\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9\u0633\u067e\u0644\u0648\u0631\u06cc\u0634\u0646 \u06a9\u06cc \u0645\u06a9\u0645\u0644 \u062a\u0635\u0648\u06cc\u0631 \u062f\u0631\u06a9\u0627\u0631 \u06c1\u0648\u062a\u06cc \u06c1\u06d2 \u06a9\u06c1 \"\u0631\u0648\u0632\u0627\u0646\u06c1\" \u06a9\u06cc\u0627 \u0633\u0645\u062c\u06be\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p><code>clusterSessions<\/code>    \u067e\u06be\u0631 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 <code>ThreadBuilder<\/code>s\u060c \u0627\u0633\u06a9\u0648\u0631 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0641\u0644\u0679\u0631 \u06a9\u06cc\u0627 \u06af\u06cc\u0627: <code>ThreadBuilder<\/code> \u0628\u0627\u0644\u06a9\u0644 1 \u0633\u06cc\u0634\u0646 \u0627\u0648\u0631 3 \u0633\u06d2 \u06a9\u0645 \u0648\u0627\u0642\u0639\u0627\u062a \u062a\u0642\u0631\u06cc\u0628\u0627\u064b \u06c1\u0645\u06cc\u0634\u06c1 \u06c1\u06cc \u06af\u0645\u0631\u0627\u06c1 \u0635\u0641\u062d\u06c1 \u06a9\u06d2 \u0628\u0648\u062c\u06be \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0648 \u06a9\u0633\u06cc \u0628\u06be\u06cc \u0686\u06cc\u0632 \u0645\u06cc\u06ba \u0636\u0645 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u0627\u0646\u06c1\u06cc\u06ba \u062a\u0642\u0631\u06cc\u0628\u0627\u064b \u0635\u0641\u0631 \u0627\u0639\u062a\u0628\u0627\u0631 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062a\u06be\u0631\u06cc\u0688\u0632 \u0628\u0646\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0636\u0627\u0626\u0639 \u06a9\u0631 \u062f\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0632\u0646\u062f\u06c1 \u0631\u06c1\u0646\u06d2 \u0648\u0627\u0644\u06cc \u06c1\u0631 \u0686\u06cc\u0632 \u06a9\u06d2 \u0627\u0633\u06a9\u0648\u0631 \u06cc\u06c1 \u06c1\u06cc\u06ba: <code>scoreThread<\/code>\u06cc\u06c1 \u0628\u0631\u0642\u0631\u0627\u0631 \u0631\u06c1\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0633 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u067e\u0631\u0646\u0679 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2: <code>console.table<\/code>\u06cc\u06c1 \u0679\u06cc\u0648\u0646\u0646\u06af \u0627\u0633\u0633\u0679\u0646\u0633 \u0641\u0646\u06a9\u0634\u0646 \u06c1\u06d2 \u062c\u0633 \u06a9\u0627 \u067e\u06c1\u0644\u06d2 \u0630\u06a9\u0631 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4 \u0627\u0633\u06d2 \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f\u060c \u0627\u06af\u0631 \u0622\u067e \u0633\u0631\u0648\u0633 \u0648\u0631\u06a9\u0631 \u06a9\u0627 \u06a9\u0646\u0633\u0648\u0644 \u06a9\u06be\u0648\u0644\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u062a\u0645\u0627\u0645 \u062a\u06be\u0631\u06cc\u0688\u0632 \u06a9\u0648 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0679\u06cc\u0628\u0644 \u0645\u06cc\u06ba \u0631\u06a9\u06be\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4 \u06cc\u06c1 \u062a\u06cc\u0632 \u062a\u0631\u06cc\u0646 \u0637\u0631\u06cc\u0642\u06c1 \u06c1\u06d2\u06d4 <code>SIMILARITY_THRESHOLD<\/code> \u0628\u06c1\u062a \u0632\u06cc\u0627\u062f\u06c1 \u06cc\u0627 \u0628\u06c1\u062a \u06a9\u0645\u06d4<\/p>\n<h3 id=\"heading-checkpoint\">\u0686\u0648\u06a9\u06cc<\/h3>\n<p>\u067e\u0686\u06be\u0644\u06d2 \u062f\u0648 \u062d\u0635\u0648\u06ba \u06a9\u06cc \u0637\u0631\u062d\u060c <code>buildThreads<\/code> \u0627\u0628\u06be\u06cc \u062a\u06a9 \u06a9\u0648\u0626\u06cc UI \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u0628\u0639\u062f \u0645\u06cc\u06ba \u0627\u0633 \u06af\u0627\u0626\u06cc\u0688 \u0645\u06cc\u06ba \u0622\u067e \u06a9\u06d2 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u06a9\u0648 \u0688\u06cc\u0632\u0627\u0626\u0646 \u06a9\u0631\u062a\u06d2 \u0648\u0642\u062a \u0627\u0633\u06d2 \u062f\u0648 \u062f\u06cc\u06af\u0631 \u0628\u0679\u0646\u0648\u06ba \u06a9\u06d2 \u0633\u0627\u062a\u06be \"Create Intent Map\" \u0628\u0679\u0646 \u0633\u06d2 \u0645\u0646\u0633\u0644\u06a9 \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4<\/p>\n<p>\u0627\u0628\u06be\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u062f\u0631\u062c \u0630\u06cc\u0644 \u06a9\u0648 \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba: <code>src\/pipeline\/ambient.ts<\/code>\u0627\u067e \u0688\u06cc\u0679 <code>src\/db\/index.ts<\/code>\u0627\u0648\u0631 <code>src\/pipeline\/threads.ts<\/code> \u06c1\u0631 \u0686\u06cc\u0632 \u063a\u0644\u0637\u06cc\u0648\u06ba \u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u0628\u0646\u062a\u06cc \u06c1\u06d2\u06d4 <code>getDB()<\/code> \u0627\u06af\u0644\u06cc \u0628\u0627\u0631 \u0627\u06cc\u06a9\u0633\u0679\u06cc\u0646\u0634\u0646 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0644\u0648\u0688 \u06c1\u0648\u0646\u06d2 \u067e\u0631\u060c \u06cc\u06c1 \u0648\u0631\u0698\u0646 3 \u06a9\u06cc \u0627\u0637\u0644\u0627\u0639 \u062f\u06d2 \u06af\u06cc\u06d4 <code>intent_threads<\/code> \u0627\u0646\u06c1\u06cc\u06ba \u0627\u0628 \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u062f\u0631\u062c \u06a9\u06cc\u0627 \u062c\u0627\u0646\u0627 \u0686\u0627\u06c1\u0626\u06d2\u06d4 <code>raw_events<\/code> \u0627\u0648\u0631 <code>sessions<\/code> DevTools \u0645\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u0633 \u0645\u0642\u0627\u0645 \u067e\u0631\u060c \u067e\u0648\u0631\u06cc \u0628\u0646\u06cc\u0627\u062f\u06cc \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0628\u063a\u06cc\u0631 \u06a9\u0633\u06cc API \u06a9\u0644\u06cc\u062f \u06a9\u06d2 \u0645\u0642\u0627\u0645\u06cc \u0637\u0648\u0631 \u067e\u0631\u060c \u0622\u062e\u0631 \u0633\u06d2 \u0622\u062e\u0631 \u062a\u06a9 \u0686\u0644\u062a\u06cc \u06c1\u06d2\u06d4 \u062a\u0644\u0627\u0634 \u06a9\u06cc \u0633\u0631\u06af\u0632\u0634\u062a \u062e\u0627\u0645 \u0648\u0627\u0642\u0639\u0627\u062a \u0628\u0646 \u062c\u0627\u062a\u06cc \u06c1\u06d2\u060c \u062e\u0627\u0645 \u0648\u0627\u0642\u0639\u0627\u062a \u0633\u06cc\u0634\u0646 \u0628\u0646 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0633\u06cc\u0634\u0646\u0632 \u0627\u0633\u06a9\u0648\u0631 \u06a9\u06cc\u06d2 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0646\u0679\u06cc\u0646\u0679 \u062a\u06be\u0631\u06cc\u0688\u0632 \u06a9\u06cc \u062f\u0631\u062c\u06c1 \u0628\u0646\u062f\u06cc \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u06cc\u06c1\u0627\u06ba \u0633\u06d2\u060c \u0633\u0628 \u06a9\u0686\u06be \u0627\u062e\u062a\u06cc\u0627\u0631\u06cc \u0627\u0648\u0631 \u0627\u0636\u0627\u0641\u06cc \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0627\u06cc\u06a9 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u06c1\u06d2 \u062c\u0648 \u062e\u0648\u062f \u062d\u0648\u0627\u0644\u06c1 \u0634\u0648\u0631 \u06a9\u06d2 \u0630\u0631\u0627\u0626\u0639 \u06a9\u0648 \u0635\u0627\u0641 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0646 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0646\u06d2 \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u0646\u0645\u0679\u0627 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 (\u062c\u0633 \u06a9\u0648 \u0622\u067e \u0634\u0627\u06cc\u062f \u062f\u06cc\u06a9\u06be\u0646\u0627 \u0627\u0648\u0631 \u0627\u0646\u0679\u06cc\u06af\u0631\u06cc\u0679 \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba)\u060c \u0627\u0648\u0631 \u067e\u06be\u0631 AI \u0644\u06cc\u0628\u0644\u0646\u06af\u060c \u0628\u0631\u0627\u0646\u0688 \u06af\u0631\u0627\u0624\u0646\u0688\u0646\u06af\u060c \u0627\u0648\u0631 \u0627\u0646 \u0633\u0628 \u06a9\u0648 \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u0628\u0627\u0646\u062f\u06be\u0646\u0627\u06d4<\/p>\n<h2 id=\"heading-how-to-clean-up-self-referential-noise\">\u062e\u0648\u062f \u062d\u0648\u0627\u0644\u06c1 \u0634\u0648\u0631 \u06a9\u0648 \u06a9\u06cc\u0633\u06d2 \u0635\u0627\u0641 \u06a9\u0631\u06cc\u06ba\u06d4<\/h2>\n<p>\u062c\u0628 \u0622\u067e \u062e\u0648\u062f \u0627\u067e\u0646\u06cc \u0628\u0631\u0627\u0624\u0632\u0646\u06af \u06a9\u06d2 \u0644\u06cc\u06d2 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u0648 \u0686\u0646\u062f \u0628\u0627\u0631 \u0686\u0644\u0627\u062a\u06d2 \u06c1\u06cc\u06ba \u062a\u0648 \u0639\u062c\u06cc\u0628 \u0642\u0633\u0645 \u06a9\u06d2 \u062f\u06be\u0627\u06af\u06d2 \u0646\u0645\u0648\u062f\u0627\u0631 \u06c1\u0648\u0646\u06d2 \u0644\u06af\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u06cc\u06a9 \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u06a9\u06be\u0644\u06cc \u0644\u0648\u067e \u067e\u0631 \u0645\u0634\u062a\u0645\u0644 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0686\u0648\u0646\u06a9\u06c1 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u0627\u06cc\u06a9 \u0648\u06cc\u0628 \u0635\u0641\u062d\u06c1 \u06c1\u06d2\u060c \u062c\u0628 \u0628\u06be\u06cc \u0622\u067e \u062f\u06be\u0627\u06af\u0648\u06ba \u06a9\u0648 \u0686\u06cc\u06a9 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u06a9\u0648 \u06a9\u06be\u0648\u0644\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0627\u0633 \u0635\u0641\u062d\u06c1 \u06a9\u0627 \u0628\u0648\u062c\u06be \u0627\u06cc\u06a9 \u0627\u06cc\u0648\u0646\u0679 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u067e\u06a9\u0691\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0622\u067e \u0628\u06be\u06cc \u0627\u06cc\u06a9\u0633\u0679\u06cc\u0646\u0634\u0646 \u062a\u06cc\u0627\u0631 \u06a9\u0631 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>localhost<\/code> \u0688\u06cc\u0679\u0627 \u0645\u06cc\u06ba \u062a\u0631\u0642\u06cc\u0627\u062a\u06cc \u0633\u0631\u0648\u0631\u0632 \u0627\u0648\u0631 \u06a9\u0633\u06cc \u0628\u06be\u06cc \u0646\u062c\u06cc \u0646\u06cc\u0679 \u0648\u0631\u06a9 \u06a9\u06d2 \u067e\u062a\u06d2 \u0628\u06be\u06cc \u0634\u0627\u0645\u0644 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0679\u0648\u0644\u0632 \u0628\u0627\u0644\u0622\u062e\u0631 \u0627\u067e\u0646\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0627 \u0645\u0634\u0627\u06c1\u062f\u06c1 \u06a9\u0631\u06cc\u06ba \u06af\u06d2\u060c \u0627\u0648\u0631 \u062e\u0648\u062f \u062d\u0648\u0627\u0644\u06c1 \u062c\u0627\u062a \u0627\u0631\u0627\u062f\u06d2 \u06a9\u06d2 \u0646\u0642\u0634\u06d2 \u06a9\u0648 \u062f\u0648 \u0627\u0644\u06af \u0627\u0644\u06af \u0637\u0631\u06cc\u0642\u0648\u06ba \u0633\u06d2 \u0622\u0644\u0648\u062f\u06c1 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0648 \u0627\u0644\u06af \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-the-two-problems\">\u062f\u0648 \u0645\u0633\u0627\u0626\u0644<\/h3>\n<p>\u067e\u06c1\u0644\u0627 \u0645\u0633\u0626\u0644\u06c1 \u0627\u06cc\u06a9\u0633\u0679\u06cc\u0646\u0634\u0646 \u06a9\u0627 \u0627\u067e\u0646\u0627 \u0635\u0641\u062d\u06c1 \u06c1\u06d2\u06d4 \u06a9\u0631\u0648\u0645 \u0627\u06cc\u06a9\u0633\u0679\u06cc\u0646\u0634\u0646 \u06a9\u0627 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u0627\u0633 \u0633\u06d2 \u0644\u0648\u0688 \u06c1\u0648\u062a\u0627 \u06c1\u06d2: <code>chrome-extension:\/\/<\/code> \u06cc\u0648 \u0622\u0631 \u0627\u06cc\u0644 \u0627\u0648\u0631 \u06a9\u0631\u0648\u0645 \u06a9\u06d2 \u0627\u067e\u0646\u06d2 \u0627\u0646\u062f\u0631\u0648\u0646\u06cc \u0635\u0641\u062d\u0627\u062a \u06c1\u06cc\u06ba\u06d4 <code>chrome:\/\/<\/code>. \u0627\u06af\u0631 \u0622\u067e \u0627\u0648\u067e\u0646 \u0644\u0648\u067e\u0633 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u06a9\u0648 \u0628\u063a\u06cc\u0631 \u0641\u0644\u0679\u0631 \u06a9\u06cc\u06d2 \u0627\u06cc\u06a9 \u062f\u0648\u067e\u06c1\u0631 \u0645\u06cc\u06ba 10 \u0628\u0627\u0631 \u06a9\u06be\u0648\u0644\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0627\u06cc\u06a9 \u0648\u0642\u062a \u0645\u06cc\u06ba 10 \u0627\u06cc\u0648\u0646\u0679\u0633 \u062a\u06cc\u0627\u0631 \u06c1\u0648\u06ba \u06af\u06d2\u06d4 <code>chrome-extension:\/\/<\/code> \u06cc\u06c1 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0627\u06cc\u06a9 \u0627\u0635\u0644 \u06c1\u06d2 \u062c\u0648 \u062e\u0648\u0634\u06cc \u0633\u06d2 \u0627\u0633 \u062f\u06be\u0627\u06af\u06d2 \u0645\u06cc\u06ba \u062c\u0645\u0639 \u06c1\u0648 \u062c\u0627\u062a\u06cc \u06c1\u06d2 \u062c\u0633\u06d2 \u0648\u06c1 \u062f\u06cc\u06a9\u06be \u0631\u06c1\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u06cc\u06c1 \u0633\u0631\u06a9\u0644\u0631 \u0627\u0648\u0631 \u0628\u06cc\u06a9\u0627\u0631 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u062a\u0644\u0627\u0634 \u06a9\u0627 \u0628\u0642\u06cc\u06c1 \u0648\u0642\u062a \u067e\u0631\u0633\u06a9\u0648\u0646 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u0686\u0648\u0646\u06a9\u06c1 \u06c1\u0645 \u0627\u06a9\u062b\u0631 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u06a9\u06be\u0648\u0644\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u06cc\u06c1 \u0633\u06cc\u0644\u0641 \u062a\u06be\u0631\u06cc\u0688 \u062a\u0627\u0632\u06af\u06cc \u0627\u0648\u0631 \u0633\u06cc\u0634\u0646 \u06a9\u06cc \u062a\u0639\u062f\u0627\u062f \u0645\u06cc\u06ba \u0646\u0627\u0642\u0627\u0628\u0644 \u06cc\u0642\u06cc\u0646 \u062d\u062f \u062a\u06a9 \u0632\u06cc\u0627\u062f\u06c1 \u0633\u06a9\u0648\u0631 \u06a9\u0631 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u062f\u0648\u0633\u0631\u0627 \u0645\u0633\u0626\u0644\u06c1 \u0639\u0644\u0627\u0642\u0627\u0626\u06cc \u062a\u0631\u0642\u06cc \u06a9\u06d2 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0688\u06be\u0627\u0646\u0686\u06d2 \u06a9\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0622\u067e \u0627\u06cc\u06a9\u0633\u0679\u06cc\u0646\u0634\u0646 \u06cc\u0627 \u0645\u0642\u0627\u0645\u06cc \u067e\u0631\u0648\u062c\u06cc\u06a9\u0679 \u0628\u0646\u0627 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0627\u0633 \u06a9\u06cc \u062a\u0627\u0631\u06cc\u062e \u062f\u0631\u062c \u0630\u06cc\u0644 \u06c1\u0648 \u06af\u06cc: <code>localhost:5173<\/code>, <code>127.0.0.1:8080<\/code>\u0627\u0648\u0631 \u0627\u0633 \u0637\u0631\u062d \u06a9\u06d2 LAN \u0627\u06cc\u0688\u0631\u06cc\u0633 \u0628\u06be\u06cc \u06c1\u0648 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba: <code>192.168.1.40<\/code>. \u062c\u06c1\u0627\u06ba \u062a\u06a9 \u06a9\u0631\u0648\u0645 \u06a9\u0627 \u062a\u0639\u0644\u0642 \u06c1\u06d2\u060c \u06cc\u06c1 \u0627\u06cc\u06a9 \u062d\u0642\u06cc\u0642\u06cc \u0635\u0641\u062d\u06c1 \u06a9\u0627 \u062f\u0648\u0631\u06c1 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u0627\u0633 \u0645\u0639\u0646\u06cc \u0645\u06cc\u06ba \u0646\u06cc\u0648\u06cc\u06af\u06cc\u0634\u0646 \u06a9\u0627 \u06a9\u0648\u0626\u06cc \u0627\u0631\u0627\u062f\u06c1 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 \u062c\u0633 \u06a9\u06cc \u0627\u0648\u067e\u0646 \u0644\u0648\u067e\u0633 \u06a9\u06cc \u067e\u0631\u0648\u0627\u06c1 \u06c1\u06d2\u06d4 \u0633\u0628 \u0633\u06d2 \u0628\u0631\u06cc \u0628\u0627\u062a \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u06cc\u06c1 \u0628\u0631\u0627\u0646\u0688 \u06a9\u06cc \u0627\u0641\u0632\u0648\u062f\u06af\u06cc \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646 \u0628\u0639\u062f \u0645\u06cc\u06ba context.dev \u067e\u0631 \u0628\u06be\u06cc\u062c\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062c\u0633 \u0633\u06d2 \u06a9\u0686\u06be \u0628\u06be\u06cc \u062d\u0644 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u0627 \u0627\u0648\u0631 \u0635\u0631\u0641 \u0622\u067e \u06a9\u06d2 API \u06a9\u0631\u06cc\u0688\u0679 \u0636\u0627\u0626\u0639 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u062f\u0648\u0646\u0648\u06ba \u0645\u0633\u0627\u0626\u0644 \u06a9\u06cc \u0627\u06cc\u06a9 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0648\u062c\u06c1 \u06c1\u06d2\u06d4 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0627\u0646 URLs \u06a9\u0648 \u067e\u06a9\u0691\u062a\u06cc \u06c1\u06d2 \u062c\u0648 \u0627\u0635\u0644 \u0645\u06cc\u06ba \u0646\u06cc\u0648\u06cc\u06af\u06cc\u0634\u0646 \u06a9\u0627 \u062d\u0635\u06c1 \u0646\u06c1\u06cc\u06ba \u06c1\u06cc\u06ba\u06d4 \u062d\u0644 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u0627\u0633 \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u06cc \u062c\u0627\u0626\u06d2 \u062c\u0633\u06d2 \u0627\u06cc\u06a9 \u062d\u0642\u06cc\u0642\u06cc \u0628\u06cc\u0631\u0648\u0646\u06cc \u0648\u06cc\u0628 \u0635\u0641\u062d\u06c1 \u0633\u0645\u062c\u06be\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u062c\u06c1\u0627\u06ba \u0628\u06be\u06cc \u06cc\u0648 \u0622\u0631 \u0627\u06cc\u0644 \u06cc\u0627 \u0688\u0648\u0645\u06cc\u0646 \u0633\u0633\u0679\u0645 \u0645\u06cc\u06ba \u062f\u0627\u062e\u0644 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u0648\u06c1\u0627\u06ba \u0627\u0633 \u062a\u0639\u0631\u06cc\u0641 \u06a9\u0648 \u0644\u0627\u06af\u0648 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-one-definition-applied-everywhere\">\u0627\u06cc\u06a9 \u062a\u0639\u0631\u06cc\u0641\u060c \u06c1\u0631 \u062c\u06af\u06c1 \u0644\u0627\u06af\u0648 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4<\/h3>\n<p>\u0627\u0633 \u06a9\u0627\u0645 \u0645\u06cc\u06ba \u0645\u062f\u062f \u06a9\u06d2 \u0644\u06cc\u06d2 \u062f\u0648 \u0645\u062f\u062f\u06af\u0627\u0631\u060c <code>isHttpUrl<\/code> \u0627\u0648\u0631 <code>isLocalHost<\/code>\u0627\u0633\u06d2 \u067e\u06c1\u0644\u06cc \u062a\u0639\u0645\u06cc\u0631 \u067e\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0644\u06a9\u06be\u0627 \u06af\u06cc\u0627 \u062a\u06be\u0627\u06d4 <code>src\/lib\/util.ts<\/code>. \u06c1\u0645 \u0646\u06d2 \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u0627\u0633\u06d2 \u0627\u0633\u06cc \u0644\u0645\u062d\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062c\u0644\u062f \u0645\u062a\u0639\u0627\u0631\u0641 \u06a9\u0631\u0627\u06cc\u0627\u06d4<\/p>\n<p><code>isHttpUrl<\/code>    \u0635\u0631\u0641 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062f\u0631\u0633\u062a \u0644\u0648\u0679\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>http:\/\/<\/code> \u0627\u0648\u0631 <code>https:\/\/<\/code> \u062e\u0627\u0631\u062c \u06a9\u0631\u062f\u06c1 URLs <code>chrome-extension:\/\/<\/code>, <code>chrome:\/\/<\/code>, <code>about:<\/code>\u0627\u0648\u0631 <code>file:\/\/<\/code> \u0633\u0628 \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be\u06d4 <code>isLocalHost<\/code> \u0627\u0633 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062f\u0631\u0633\u062a \u0644\u0648\u0679\u0627\u062a\u0627 \u06c1\u06d2: <code>localhost<\/code>\u0644\u0648\u067e \u0628\u06cc\u06a9 \u0627\u0648\u0631 \u0646\u062c\u06cc IP \u0631\u06cc\u0646\u062c\u0632 <code>.local<\/code> \u0645\u06cc\u0632\u0628\u0627\u0646 \u06a9\u0627 \u0646\u0627\u0645\u06d4<\/p>\n<p>\u062c\u0648 \u0686\u06cc\u0632 \u0627\u0633\u06d2 \u0645\u0648\u062b\u0631 \u0628\u0646\u0627\u062a\u06cc \u06c1\u06d2 \u0648\u06c1 \u0645\u0633\u062a\u0642\u0644 \u0645\u0632\u0627\u062c\u06cc \u06c1\u06d2\u06d4 \u0648\u06c1\u06cc \u062f\u0648 \u062e\u0635\u0648\u0635\u06cc\u0627\u062a \u062a\u0645\u0627\u0645 \u0627\u0646\u0679\u0631\u06cc \u067e\u0648\u0627\u0626\u0646\u0679\u0633 \u06a9\u06cc \u062d\u0641\u0627\u0638\u062a \u06a9\u0631\u062a\u06cc \u06c1\u06cc\u06ba\u060c \u0627\u0633 \u0644\u06cc\u06d2 \"\u062d\u0642\u06cc\u0642\u06cc \u0635\u0641\u062d\u06c1\" \u06a9\u06cc \u062a\u0639\u0631\u06cc\u0641 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u06d2 \u0627\u06cc\u06a9 \u062d\u0635\u06d2 \u0627\u0648\u0631 \u062f\u0648\u0633\u0631\u06d2 \u062d\u0635\u06d2 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0645\u0646\u062a\u0642\u0644 \u0646\u06c1\u06cc\u06ba \u06c1\u0648 \u0633\u06a9\u062a\u06cc\u06d4 \u0627\u0633 \u0637\u0631\u062d \u06a9\u06d2 \u062f\u0627\u062e\u0644\u06d2 \u06a9\u06d2 \u062a\u06cc\u0646 \u0645\u0642\u0627\u0645\u0627\u062a \u06c1\u06cc\u06ba:<\/p>\n<p>\u0644\u0627\u0626\u06cc\u0648 \u06a9\u06cc\u067e\u0686\u0631\u060c <code>src\/background.ts<\/code>\u0641\u0648\u0646 \u06a9\u0627\u0644 <code>isHttpUrl<\/code> \u0631\u06cc\u06a9\u0627\u0631\u0688\u0646\u06af \u0633\u06d2 \u067e\u06c1\u0644\u06d2:<\/p>\n<pre><code class=\"language-typescript\">if (!isHttpUrl(url)) return;\n<\/code><\/pre>\n<p>\u0628\u06cc\u06a9 \u0641\u0644\u060c <code>src\/pipeline\/backfill.ts<\/code>\u0648\u0632\u0679 \u0627\u0645\u067e\u0648\u0631\u0679 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u062a\u0627\u0631\u06cc\u062e \u06a9\u06d2 \u062a\u0645\u0627\u0645 \u0627\u0646\u062f\u0631\u0627\u062c\u0627\u062a \u067e\u0631 \u0627\u06cc\u06a9 \u06c1\u06cc \u06af\u0627\u0631\u0688 \u0644\u06af\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-typescript\">if (!item.url) return [];\nif (!isHttpUrl(item.url)) return [];\n<\/code><\/pre>\n<p>\u0627\u0648\u0631 \u0634\u0648\u0631 \u0641\u0644\u0679\u0631 \u06c1\u06d2 <code>src\/pipeline\/noise.ts<\/code>\u0633\u0628 \u0633\u06d2 \u0627\u0648\u067e\u0631 \u062f\u0648\u0646\u0648\u06ba \u0645\u062f\u062f\u06af\u0627\u0631\u0648\u06ba \u06a9\u0648 \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4 <code>isNoise<\/code>\u0688\u0648\u0645\u06cc\u0646 \u06cc\u0627 \u0679\u0627\u0626\u0679\u0644 \u0631\u0648\u0644 \u0686\u0644\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2:<\/p>\n<pre><code class=\"language-typescript\">export function isNoise(event: RawEvent): boolean {\n  if (!isHttpUrl(event.url)) return true;\n  if (isLocalHost(event.domain)) return true;\n  return domainIsBlocked(event.domain) || titleIsGeneric(event.title, event.domain);\n}\n<\/code><\/pre>\n<p>\u06a9\u06cc\u067e\u0686\u0631 \u0627\u0648\u0631 \u0628\u06cc\u06a9 \u0641\u0644 \u06a9\u0648 \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u06cc\u06c1 \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u063a\u06cc\u0631 \u0648\u06cc\u0628 \u06cc\u0648 \u0622\u0631 \u0627\u06cc\u0644 \u06a9\u0648 \u0631\u0648\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 <code>isHttpUrl<\/code> \u062a\u06cc\u0633\u0631\u06cc \u0628\u0627\u0631 \u0645\u06cc\u06ba <code>isNoise<\/code> \u06cc\u06c1 \u0628\u06d2 \u06a9\u0627\u0631 \u0644\u06af \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u0639\u0627\u0645 \u0622\u067e\u0631\u06cc\u0634\u0646 \u06a9\u06d2 \u062a\u062d\u062a \u06cc\u06c1 \u06c1\u06d2. \u062a\u06cc\u0633\u0631\u0627 \u0686\u06cc\u06a9 \u06af\u0627\u0631\u0646\u0679\u06cc \u06c1\u06d2\u06d4 \u062c\u0628 \u06a9\u0648\u0626\u06cc \u0646\u0627\u0646 \u0648\u06cc\u0628 \u0648\u06cc\u0628 \u0627\u06cc\u0648\u0646\u0679 \u0622\u062a\u0627 \u06c1\u06d2\u06d4 <code>raw_events<\/code> \u06cc\u06c1 \u0627\u0628 \u0628\u06be\u06cc \u063a\u06cc\u0631 \u0645\u062a\u0648\u0642\u0639 \u0631\u0627\u0633\u062a\u0648\u06ba \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0633\u06cc\u0634\u0646 \u0645\u06cc\u06ba \u0632\u0646\u062f\u06c1 \u0646\u06c1\u06cc\u06ba \u0631\u06c1 \u0633\u06a9\u062a\u0627 \u06c1\u06d2 (\u0645\u062b\u0644\u0627\u064b \u0645\u0633\u062a\u0642\u0628\u0644 \u06a9\u06cc \u06af\u0631\u0641\u062a\u0627\u0631\u06cc \u06a9\u06d2 \u0637\u0631\u06cc\u0642\u06c1 \u06a9\u0627\u0631\u060c \u062f\u0631\u0622\u0645\u062f \u0634\u062f\u06c1 \u0688\u06cc\u0679\u0627\u060c \u06cc\u0627 \u06a9\u06cc\u0691\u06d2)\u06d4<\/p>\n<p>\u06c1\u0631 \u0642\u062f\u0645 \u0627\u067e\u0646\u06d2 \u0627\u0646 \u067e\u0679 \u06a9\u0627 \u062f\u0641\u0627\u0639 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0627\u0633 \u067e\u0631 \u0628\u06be\u0631\u0648\u0633\u06c1 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u06a9\u06c1 \u067e\u0686\u06be\u0644\u06d2 \u0645\u0631\u062d\u0644\u06d2 \u0646\u06d2 \u0627\u067e\u0646\u0627 \u06a9\u0627\u0645 \u06a9\u06cc\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0627\u06cc\u06a9 \u06af\u0645\u0634\u062f\u06c1 \u06a9\u06cc\u0633 \u06a9\u0648 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u0627\u0631\u0627\u062f\u06d2 \u06a9\u06d2 \u0646\u0642\u0634\u06d2 \u067e\u0631 \u067e\u06be\u06cc\u0644\u0627\u0646\u06d2 \u0633\u06d2 \u0631\u0648\u06a9\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-defending-the-enrichment-boundary-too\">\u0627\u0631\u062a\u06a9\u0627\u0632 \u0633\u0631\u062d\u062f\u06cc \u062f\u0641\u0627\u0639<\/h3>\n<p>\u0627\u06cc\u06a9 \u06c1\u06cc <code>isLocalHost<\/code> \u062c\u0628 \u0622\u067e \u06a9\u0627 \u0688\u0648\u0645\u06cc\u0646 context.dev \u067e\u0631 \u0645\u0646\u062a\u0642\u0644 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u0627 \u062a\u0648 \u0622\u067e \u06a9\u0648 \u0627\u06af\u0644\u06d2 \u0628\u0644\u0688 \u0622\u0624\u0679 \u0628\u0631\u0627\u0646\u0688 \u0628\u0691\u06be\u0627\u0646\u06d2 \u06a9\u06d2 \u0645\u0631\u062d\u0644\u06d2 \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646 \u0627\u06cc\u06a9 \u0627\u0648\u0631 \u062a\u0635\u062f\u06cc\u0642 \u0646\u0638\u0631 \u0622\u0626\u06d2 \u06af\u06cc\u06d4 \u06cc\u06c1\u0627\u06ba \u062a\u06a9 \u06a9\u06c1 \u0627\u06af\u0631 \u06cc\u06c1 \u06c1\u06d2 <code>isNoise<\/code> \u0645\u0642\u0627\u0645\u06cc \u067e\u062a\u06d2 \u0633\u06cc\u0634\u0646\u0627\u0626\u0632\u06cc\u0634\u0646 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u06c1\u0679\u0627 \u062f\u06cc\u06d2 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0646\u06cc\u0679 \u0648\u0631\u06a9 \u06a9\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0633\u062e\u062a\u06cc \u0627\u0646\u06c1\u06cc\u06ba \u062f\u0648\u0628\u0627\u0631\u06c1 \u0641\u0644\u0679\u0631 \u06a9\u0631 \u062f\u06cc\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-typescript\">const unique = [...new Set(domains)].filter((d) => !isLocalHost(d));\n<\/code><\/pre>\n<p>Heuristics \u0648\u06c1\u06cc \u062f\u0641\u0627\u0639\u06cc \u06af\u06c1\u0631\u0627\u0626\u06cc \u0648\u0627\u0644\u06d2 \u0622\u0626\u06cc\u0688\u06cc\u0627\u0632 \u06c1\u06cc\u06ba \u062c\u0648 \u062f\u0627\u0626\u0631\u06c1 \u0645\u06cc\u06ba \u0644\u0627\u06af\u0648 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u06c1\u0627\u06ba \u063a\u0644\u0637\u06cc \u06a9\u06cc \u0642\u06cc\u0645\u062a \u0632\u06cc\u0627\u062f\u06c1 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 \u0627\u06cc\u06a9 \u0645\u0642\u0627\u0645\u06cc \u067e\u062a\u06c1 \u062c\u0648 \u06a9\u0633\u06cc \u0646\u06c1 \u06a9\u0633\u06cc \u0637\u0631\u062d \u062a\u06be\u0631\u06cc\u0688 \u06a9\u06cc \u0688\u0648\u0645\u06cc\u0646 \u0644\u0633\u0679 \u0645\u06cc\u06ba \u0622\u062a\u0627 \u06c1\u06d2 UI \u0645\u06cc\u06ba \u0628\u06cc\u06a9\u0627\u0631 \u0634\u0648\u0631 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u06d4 \u0622\u067e \u06a9\u0648 \u0627\u067e\u0646\u06d2 \u06a9\u0645\u067e\u06cc\u0648\u0679\u0631 \u06a9\u0648 API \u06a9\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u06d2 \u062d\u0635\u06d2 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u06a9\u0628\u06be\u06cc \u0646\u06c1\u06cc\u06ba \u0686\u06be\u0648\u0691\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u06d4 \u0641\u0644\u0679\u0631\u0632 \u06a9\u0648 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u0646\u06cc\u0679 \u0648\u0631\u06a9 \u06a9\u06d2 \u06a9\u0646\u0627\u0631\u06d2 \u067e\u0631 \u0631\u06a9\u06be\u0646\u06d2 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u06af\u0627\u0631\u0646\u0679\u06cc \u0628\u0631\u0642\u0631\u0627\u0631 \u0631\u06a9\u06be\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06d2 \u0627\u0633 \u0633\u06d2 \u0642\u0637\u0639 \u0646\u0638\u0631 \u06a9\u06c1 \u0627\u0648\u067e\u0631 \u06a9\u06cc \u0637\u0631\u0641 \u06a9\u06cc\u0627 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-checkpoint\">\u0686\u0648\u06a9\u06cc<\/h3>\n<p>\u0627\u067e \u0688\u06cc\u0679 \u0634\u062f\u06c1 \u0628\u0644\u0688 \u06a9\u0648 \u0644\u0648\u0688 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f\u060c \u0627\u0648\u067e\u0646 \u0644\u0648\u067e\u0633 \u0627\u067e\u0646\u06d2 \u0627\u0631\u0627\u062f\u06d2 \u06a9\u06d2 \u0646\u0642\u0634\u06d2 \u0645\u06cc\u06ba \u0645\u0632\u06cc\u062f \u0638\u0627\u06c1\u0631 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u06ba \u06af\u06d2\u06d4 \u0686\u06cc\u06a9 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u06a9\u0648 \u06a9\u0626\u06cc \u0628\u0627\u0631 \u06a9\u06be\u0648\u0644\u06cc\u06ba\u060c \u0627\u0635\u0644 \u0635\u0641\u062d\u0627\u062a \u06a9\u0648 \u0628\u0631\u0627\u0624\u0632 \u06a9\u0631\u06cc\u06ba\u060c \u0627\u0648\u0631 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4 <code>chrome-extension:\/\/<\/code> \u0627\u0633 \u06a9\u0627 \u0627\u067e\u0646\u0627 \u062f\u06be\u0627\u06af\u06c1 \u063a\u0627\u0626\u0628 \u06c1\u0648\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u060c <code>localhost<\/code> \u0645\u062a\u0628\u0627\u062f\u0644 \u0637\u0648\u0631 \u067e\u0631\u060c \u0646\u062c\u06cc IP \u0688\u0648\u0645\u06cc\u0646 \u06a9\u0648 \u062a\u0645\u0627\u0645 \u062a\u06be\u0631\u06cc\u0688\u0632 \u06a9\u06cc \u0688\u0648\u0645\u06cc\u0646 \u0641\u06c1\u0631\u0633\u062a \u0645\u06cc\u06ba \u0638\u0627\u06c1\u0631 \u06c1\u0648\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u06d4<\/p>\n<p>\u0627\u06af\u0631 \u0622\u067e \u0679\u06cc\u0633\u0679 \u06a9\u0631\u0648\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>raw_events<\/code> DevTools \u0645\u06cc\u06ba\u060c \u0628\u06cc\u06a9 \u0641\u0644 \u0627\u06cc\u0648\u0646\u0679\u0633 \u06a9\u0648 \u0635\u0627\u0641 \u0627\u0648\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0644\u06a9\u06be\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u0644\u0627\u0626\u06cc\u0648 \u06a9\u06cc\u067e\u0686\u0631 \u0634\u0627\u0645\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06c1\u0630\u0627 \u0622\u067e \u0627\u0633 \u062a\u0631\u0645\u06cc\u0645 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0628\u06be\u06cc \u0644\u0627\u0626\u06cc\u0648 \u06a9\u06cc\u067e\u0686\u0631 \u0627\u06cc\u0648\u0646\u0679\u0633 \u062f\u06cc\u06a9\u06be \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u06af\u0631 \u0622\u067e \u0627\u06cc\u06a9 \u0646\u06cc\u0627 \"\u0645\u06cc\u0631\u06cc \u0633\u0631\u06af\u0632\u0634\u062a \u062a\u0644\u0627\u0634 \u06a9\u0631\u06cc\u06ba\" \u0686\u0644\u0627\u062a\u06d2 \u06c1\u06cc\u06ba \u062a\u0648 \u0627\u0633\u06d2 \u062d\u0630\u0641 \u06a9\u0631 \u062f\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627 \u0627\u0648\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0622\u0628\u0627\u062f \u06a9\u0631 \u062f\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4 <code>raw_events<\/code> \u0635\u0627\u0641 \u0633\u062a\u06be\u0631\u0627 \u0646\u0626\u06d2 \u0642\u0648\u0627\u0646\u06cc\u0646 \u06a9\u06d2 \u0645\u0637\u0627\u0628\u0642\u06d4<\/p>\n<p>\u0627\u0628 \u062c\u0628 \u06a9\u06c1 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u062d\u0642\u06cc\u0642\u06cc \u0628\u06cc\u0631\u0648\u0646\u06cc \u0646\u06cc\u0648\u06cc\u06af\u06cc\u0634\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0648\u0627\u0636\u062d \u0627\u0631\u0627\u062f\u06d2 \u06a9\u0627 \u0646\u0642\u0634\u06c1 \u0628\u0646\u0627\u062a\u06cc \u06c1\u06d2\u060c \u0627\u0633 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u0648 \u0645\u0632\u06cc\u062f \u067e\u0691\u06be\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u0628\u0646\u0627\u0646\u0627 \u0627\u0686\u06be\u0627 \u062e\u06cc\u0627\u0644 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0628 \u062a\u06a9\u060c \u06c1\u0631 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u0627 \u0639\u0646\u0648\u0627\u0646 \u0635\u0631\u0641 \u062a\u06cc\u0646 \u0679\u0627\u067e \u06a9\u0644\u06cc\u062f\u06cc \u0627\u0644\u0641\u0627\u0638 \u06a9\u06cc \u0627\u06cc\u06a9 \u062a\u0627\u0631 \u06c1\u06d2\u060c \u062c\u0633 \u0645\u06cc\u06ba \u06a9\u0648\u0626\u06cc \u062e\u0644\u0627\u0635\u06c1 \u06cc\u0627 \u062a\u062c\u0648\u06cc\u0632 \u06a9\u0631\u062f\u06c1 \u0627\u06af\u0644\u06d2 \u0627\u0642\u062f\u0627\u0645\u0627\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06cc\u06ba\u06d4 \u0627\u06af\u0644\u06d2 \u062d\u0635\u06d2 \u0645\u06cc\u06ba\u060c \u06c1\u0645 \u06a9\u0644\u0627\u0688 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u067e\u06c1\u0644\u06cc \u0627\u062e\u062a\u06cc\u0627\u0631\u06cc \u06a9\u0644\u06cc\u062f\u06cc \u06af\u06cc\u0679 \u067e\u0631\u062a\u060c AI \u0644\u06cc\u0628\u0644\u0646\u06af \u0634\u0627\u0645\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h2 id=\"heading-how-to-label-threads-with-claude\">\u06a9\u0644\u0627\u0688 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062a\u06be\u0631\u06cc\u0688\u0632 \u06a9\u0648 \u0644\u06cc\u0628\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0637\u0631\u06cc\u0642\u06c1<\/h2>\n<p>\"Typescript Generics Handbook\" \u06a9\u06d2 \u0639\u0646\u0648\u0627\u0646 \u0633\u06d2 \u062a\u06be\u0631\u06cc\u0688 \u067e\u0691\u06be\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u06cc\u06c1 \u06a9\u0644\u06cc\u062f\u06cc \u0627\u0644\u0641\u0627\u0638 \u06a9\u06cc \u062a\u0641\u0635\u06cc\u0644 \u06c1\u06d2\u060c \u0648\u06c1 \u0646\u06c1\u06cc\u06ba \u062c\u0648 \u0622\u067e \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u06a9\u0648\u0634\u0634 \u06a9\u0631 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba\u06d4 \"Learning Advanced Type Systems in TypeScript\" \u0648\u06c1 \u0642\u0633\u0645 \u06a9\u06d2 \u0644\u06cc\u0628\u0644 \u06c1\u06cc\u06ba \u062c\u0646\u06c1\u06cc\u06ba \u0644\u0648\u06af \u062f\u0631\u0627\u0635\u0644 \u0644\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0648\u0631 \u062f\u0648\u0646\u0648\u06ba \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0641\u0631\u0642 \u0648\u06c1 \u062e\u0644\u0627 \u06c1\u06d2 \u062c\u0633\u06d2 \u06cc\u06c1 \u062d\u0635\u06c1 \u067e\u064f\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>Claude \u06c1\u0631 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u06d2 \u06a9\u0644\u06cc\u062f\u06cc \u0627\u0644\u0641\u0627\u0638\u060c \u0688\u0648\u0645\u06cc\u0646\u0632\u060c \u0627\u0648\u0631 \u0646\u0645\u0648\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0635\u0641\u062d\u06c1 \u06a9\u06d2 \u0639\u0646\u0648\u0627\u0646\u0627\u062a \u06a9\u0648 \u067e\u0691\u06be\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0635\u0644 \u0639\u0646\u0648\u0627\u0646\u060c \u0627\u06cc\u06a9 \u062c\u0645\u0644\u06d2 \u06a9\u0627 \u062e\u0644\u0627\u0635\u06c1\u060c \u0627\u06cc\u06a9 \u062e\u0631\u0627\u0628\u06cc\u060c \u0627\u0648\u0631 \u0645\u062e\u0635\u0648\u0635 \u0627\u06af\u0644\u06d2 \u0645\u0631\u0627\u062d\u0644 \u0648\u0627\u067e\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u06cc\u06c1 \u0627\u0648\u067e\u0646 \u0644\u0648\u067e\u0633 \u06a9\u0627 \u067e\u06c1\u0644\u0627 \u062d\u0635\u06c1 \u06c1\u06d2 \u062c\u0648 \u0627\u06cc\u06a9 \u0628\u06cc\u0631\u0648\u0646\u06cc API \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0633\u06d2 \u06a9\u0644\u06cc\u062f \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 \u0688\u06cc\u0632\u0627\u0626\u0646 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u06c1\u0631 \u0686\u06cc\u0632 \u06a9\u0648 \u0627\u06cc\u06a9 \u0631\u06a9\u0627\u0648\u0679 \u06a9\u06cc \u0634\u06a9\u0644 \u062f\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06d2\u06d4 \u0627\u0633 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u062f\u0631\u062e\u0648\u0627\u0633\u062a\u0648\u06ba \u06a9\u0627 \u062d\u0642\u06cc\u0642\u06cc \u0688\u06cc\u0679\u0627 \u06c1\u0648\u0646\u0627 \u0636\u0631\u0648\u0631\u06cc \u06c1\u06d2\u060c \u0627\u0648\u0631 30 \u200b\u200b\u0633\u06d2 \u200b\u200b40 \u062a\u06be\u0631\u06cc\u0688\u0632 \u06c1\u0648 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u06c1\u0631 \u062a\u06be\u0631\u06cc\u0688 \u0645\u06cc\u06ba 12 \u0635\u0641\u062d\u0627\u062a \u06a9\u06d2 \u0639\u0646\u0648\u0627\u0646\u0627\u062a \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u0633 \u06a9\u0627 \u0627\u06cc\u06a9 \u0633\u0627\u062f\u06c1 \u0648\u0631\u0698\u0646 \u06cc\u06c1 \u06c1\u0648\u06af\u0627 \u06a9\u06c1 \u062a\u0645\u0627\u0645 \u062a\u06be\u0631\u06cc\u0688\u0632 \u06a9\u0648 \u0627\u06cc\u06a9 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u0645\u06cc\u06ba \u0628\u06be\u06cc\u062c\u06cc\u06ba \u0627\u0648\u0631 \u062a\u0645\u0627\u0645 \u0644\u06cc\u0628\u0644\u0632 \u06a9\u06cc \u062f\u0648\u0628\u0627\u0631\u06c1 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u0631\u06cc\u06ba\u06d4 \u06cc\u06c1 \u0628\u0627\u0644\u06a9\u0644 \u0648\u06c1\u06cc \u06c1\u06d2 \u062c\u0648 \u067e\u06c1\u0644\u06d2 \u0646\u0641\u0627\u0630 \u0646\u06d2 \u06a9\u06cc\u0627\u06d4 \u0644\u06cc\u06a9\u0646 \u0641\u06a9\u0633 \u0627\u0633 \u0637\u0631\u062d \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u062f\u06cc\u06a9\u06be\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u06cc\u06c1 \u067e\u0648\u0631\u06d2 \u0633\u06cc\u06a9\u0634\u0646 \u06a9\u0627 \u0633\u0628 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0645\u0639\u0644\u0648\u0645\u0627\u062a\u06cc \u062d\u0635\u06c1 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-storing-keys-locally\">\u06a9\u0644\u06cc\u062f \u06a9\u0648 \u0645\u0642\u0627\u0645\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0645\u062d\u0641\u0648\u0638 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<p>API \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2\u060c \u06c1\u0645\u06cc\u06ba \u0632\u0646\u062f\u06c1 \u0631\u06c1\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0633\u06cc \u062c\u06af\u06c1 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4 openloops \u0627\u0633\u06d2 \u0631\u06a9\u06be\u062a\u0627 \u06c1\u06d2 <code>chrome.storage.local<\/code>\u06cc\u06c1 \u06a9\u06c1\u06cc\u06ba \u0628\u06be\u06cc \u0645\u0637\u0627\u0628\u0642\u062a \u067e\u0630\u06cc\u0631 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0622\u067e \u06a9\u06d2 \u0622\u0644\u06d2 \u06a9\u0648 \u06a9\u0628\u06be\u06cc \u0646\u06c1\u06cc\u06ba \u0686\u06be\u0648\u0691\u062a\u0627 \u06c1\u06d2\u06d4 \u0628\u0646\u0627\u0646\u0627 <code>src\/lib\/settings.ts<\/code>:<\/p>\n<pre><code class=\"language-typescript\">export async function getApiKey(): Promise<string null=\"\"> {\n  const result = await chrome.storage.local.get(\"anthropicApiKey\");\n  return (result.anthropicApiKey as string) ?? null;\n}\n\nexport async function setApiKey(key: string): Promise<void> {\n  await chrome.storage.local.set({ anthropicApiKey: key });\n}\n<\/void><\/string><\/code><\/pre>\n<p>\u0648\u06c1\u06cc \u0641\u0627\u0626\u0644 \u0628\u0639\u062f \u0645\u06cc\u06ba context.dev \u06a9\u0644\u06cc\u062f \u0627\u0648\u0631 \u0627\u0633\u0633\u0679\u0646\u0679 \u06a9\u06d2 \u0645\u0627\u0688\u0644 \u0627\u0648\u0631 \u06a9\u0648\u0634\u0634 \u06a9\u06cc \u062a\u0631\u062c\u06cc\u062d\u0627\u062a \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u062a\u0648\u0627\u0632\u06cc \u06af\u06cc\u0679\u0631\u0632 \u0627\u0648\u0631 \u0633\u06cc\u0679\u0631\u0632 \u06a9\u0648 \u0628\u0691\u06be\u0627\u062a\u06cc \u06c1\u06d2\u060c \u06cc\u06c1 \u0633\u0628 \u0627\u0633\u06cc \u0634\u06a9\u0644 \u06a9\u06cc \u067e\u06cc\u0631\u0648\u06cc \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u062a\u0648 \u0628\u0633 \u0627\u0633 \u062c\u0648\u0691\u06d2 \u06a9\u0648 \u0633\u0645\u062c\u06be \u0644\u06cc\u0646\u0627 \u06c1\u06cc \u06a9\u0627\u0641\u06cc \u06c1\u06d2 \u0633\u0628 \u06a9\u0686\u06be \u0633\u0645\u062c\u06be\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2\u06d4<\/p>\n<h3 id=\"heading-the-first-version-and-how-it-broke\">\u067e\u06c1\u0644\u0627 \u0648\u0631\u0698\u0646 \u0627\u0648\u0631 \u06cc\u06c1 \u06a9\u06cc\u0648\u06ba \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648\u0627\u06d4<\/h3>\n<p>\u067e\u06c1\u0644\u06d2 \u0644\u06cc\u0628\u0644\u0646\u06af \u06a9\u06d2 \u0646\u0641\u0627\u0630 \u0646\u06d2 \u062a\u0645\u0627\u0645 \u062a\u06be\u0631\u06cc\u0688\u0632 \u06a9\u0648 \u0627\u06cc\u06a9 \u06c1\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u0645\u06cc\u06ba \u06a9\u0644\u0627\u0688 \u06a9\u0648 \u0628\u06be\u06cc\u062c \u062f\u06cc\u0627\u06d4 \u062a\u0645\u0627\u0645 40 \u062a\u06be\u0631\u06cc\u0688\u0632 \u06a9\u0648 \u0627\u06cc\u06a9 JSON \u067e\u06d2 \u0644\u0648\u0688 \u0645\u06cc\u06ba \u0633\u06cc\u0631\u06cc\u0644\u0627\u0626\u0632 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0627\u0633 \u06a9\u06d2 \u0628\u062f\u0644\u06d2 \u0645\u06cc\u06ba 40 \u0644\u06cc\u0628\u0644\u0632 \u06a9\u06cc JSON \u0633\u0631\u0646\u06cc \u06a9\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a\u06cc\u06ba\u060c \u062a\u062c\u0632\u06cc\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0648\u0627\u067e\u0633 \u0644\u06a9\u06be\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0628\u062a\u062f\u0627\u0626\u06cc \u062c\u0627\u0646\u0686 \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646 \u0627\u0633 \u0646\u06d2 5-6 \u062f\u06be\u0627\u06af\u0648\u06ba \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0628\u0627\u0644\u06a9\u0644 \u06a9\u0627\u0645 \u06a9\u06cc\u0627\u060c \u0644\u06cc\u06a9\u0646 30+ \u062f\u06be\u0627\u06af\u0648\u06ba \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062d\u0642\u06cc\u0642\u06cc \u0631\u06cc\u06a9\u0627\u0631\u0688 \u067e\u0627\u0633 \u06c1\u0648\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f\u060c \u06a9\u0686\u06be \u0628\u06be\u06cc \u062a\u06cc\u0627\u0631 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u0627\u06d4 \u06a9\u0648\u0626\u06cc \u063a\u0644\u0637\u06cc \u06cc\u0627 \u0627\u0633\u062a\u062b\u0646\u0627\u0621 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u0627\u060c \u0635\u0631\u0641 \u062f\u06be\u0627\u06af\u06c1 \u067e\u0686\u06be\u0644\u06d2 \u0645\u0637\u0644\u0648\u0628\u06c1 \u0627\u0644\u0641\u0627\u0638 \u06a9\u06d2 \u0639\u0646\u0648\u0627\u0646 \u06a9\u0648 \u0628\u0631\u0642\u0631\u0627\u0631 \u0631\u06a9\u06be\u062a\u0627 \u06c1\u06d2 \u06af\u0648\u06cc\u0627 \u06a9\u0648\u0626\u06cc \u0644\u06cc\u0628\u0644\u0646\u06af \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u0626\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u0648\u062c\u06c1 \u0622\u0624\u0679 \u067e\u0679 \u0679\u0648\u06a9\u0646 \u0679\u0631\u0646\u06a9\u06cc\u0634\u0646 \u062a\u06be\u06cc\u06d4 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u0628\u06cc\u0627\u0646 \u06a9\u0631\u062a\u06cc \u06c1\u06d2: <code>max_tokens<\/code>\u062c\u0648\u0627\u0628 \u0645\u06cc\u06ba \u0645\u0627\u0688\u0644 \u06a9\u062a\u0646\u0627 \u067e\u06cc\u062f\u0627 \u06a9\u0631 \u0633\u06a9\u062a\u0627 \u06c1\u06d2 \u0627\u0633 \u06a9\u06cc \u0627\u06cc\u06a9 \u0628\u0627\u0644\u0627\u0626\u06cc \u062d\u062f \u06c1\u06d2\u060c 40 \u062f\u06be\u0627\u06af\u0648\u06ba \u06a9\u06d2 \u0639\u0646\u0648\u0627\u0646\u0627\u062a\u060c \u062e\u0644\u0627\u0635\u06d2 \u0627\u0648\u0631 \u0627\u06af\u0644\u06d2 \u0627\u0642\u062f\u0627\u0645\u0627\u062a \u0628\u06c1\u062a \u0632\u06cc\u0627\u062f\u06c1 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u06c1\u06cc\u06ba\u06d4 \u062c\u0628 \u0631\u0633\u067e\u0627\u0646\u0633 \u0648\u0633\u0637 \u062c\u0646\u0631\u06cc\u0634\u0646 \u06a9\u06cc \u062d\u062f \u062a\u06a9 \u067e\u06c1\u0646\u0686 \u06af\u06cc\u0627\u060c JSON \u0633\u0631\u0646\u06cc \u06a9\u06be\u0644\u0646\u06d2 \u06a9\u06d2 \u0622\u062f\u06be\u06d2 \u0631\u0627\u0633\u062a\u06d2 \u067e\u0631 \u0679\u0648\u0679 \u06af\u0626\u06cc\u06d4 <code>[<\/code> and thirty complete objects followed by half of the thirty-first and no closing <code>]<\/code>. <code>JSON.parse<\/code> \u0627\u0633 \u062a\u06be\u0631\u0648 \u067e\u0631\u060c \u06a9\u06cc\u0686 \u0628\u0644\u0627\u06a9 \u0646\u06d2 \u0627\u0633\u06d2 \u0644\u0627\u06af \u06a9\u06cc\u0627 \u0627\u0648\u0631 \u06a9\u0686\u06be \u0628\u06be\u06cc \u0648\u0627\u067e\u0633 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627\u060c \u0627\u0648\u0631 \u0644\u06cc\u0628\u0644\u0646\u06af \u06a9\u0648 \u062e\u0648\u0628\u0635\u0648\u0631\u062a\u06cc \u0633\u06d2 \u0646\u0627\u06a9\u0627\u0645 \u06a9\u0631\u0646\u06d2 \u0627\u0648\u0631 \u0645\u0648\u062c\u0648\u062f\u06c1 \u0639\u0646\u0648\u0627\u0646 \u06a9\u0648 \u0628\u0631\u0642\u0631\u0627\u0631 \u0631\u06a9\u06be\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0688\u06cc\u0632\u0627\u0626\u0646 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u062a\u06be\u0627\u060c \u0644\u06c1\u0630\u0627 \u0646\u0627\u06a9\u0627\u0645\u06cc UI \u06a9\u06d2 \u0644\u06cc\u06d2 \u067e\u0648\u0634\u06cc\u062f\u06c1 \u062a\u06be\u06cc\u06d4<\/p>\n<p>\u0688\u06cc\u0632\u0627\u0626\u0646 \u0645\u06cc\u06ba \u062f\u0648 \u062a\u0628\u062f\u06cc\u0644\u06cc\u0627\u06ba \u06a9\u06cc \u06af\u0626\u06cc\u06ba \u0627\u0648\u0631 \u062f\u0648\u0646\u0648\u06ba \u062d\u062a\u0645\u06cc \u06a9\u0648\u0688 \u0645\u06cc\u06ba \u06c1\u06cc\u06ba\u06d4 \u06a9\u0627\u0645 \u06a9\u0648 \u0686\u06be\u0648\u0679\u06d2 \u0628\u06cc\u0686\u0648\u06ba \u0645\u06cc\u06ba \u062a\u0642\u0633\u06cc\u0645 \u06a9\u0631\u0646\u0627 \u0627\u0633 \u0628\u0627\u062a \u06a9\u0648 \u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u0631\u062f\u0639\u0645\u0644 \u0627\u062a\u0646\u0627 \u0628\u0691\u0627 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 \u06a9\u06c1 \u0627\u0633\u06d2 \u0686\u06be\u0648\u0679\u0627 \u06a9\u06cc\u0627 \u062c\u0627 \u0633\u06a9\u06d2\u060c \u0627\u0648\u0631 \u067e\u0627\u0631\u0633\u0646\u06af \u06a9\u0648 \u0627\u062a\u0646\u0627 \u0644\u0686\u06a9\u062f\u0627\u0631 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0627\u06cc\u06a9 \u0628\u0631\u0627 \u0628\u06cc\u0686 \u067e\u0648\u0631\u06cc \u0639\u0645\u0644 \u062f\u0631\u0622\u0645\u062f \u06a9\u0648 \u0646\u06c1\u06cc\u06ba \u0631\u0648\u06a9 \u0633\u06a9\u062a\u0627\u06d4<\/p>\n<h3 id=\"heading-batching-the-requests\">\u0628\u06cc\u0686 \u067e\u0631\u0648\u0633\u06cc\u0633\u0646\u06af \u06a9\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<p>\u0628\u0646\u0627\u0646\u0627 <code>src\/pipeline\/label.ts<\/code>\u06c1\u0645 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u06d2 \u0644\u062d\u0627\u0638 \u0633\u06d2 \u0628\u06cc\u0686 \u06a9\u06cc \u062e\u0635\u0648\u0635\u06cc\u062a \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0634\u0631\u0648\u0639 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-typescript\">import { getAllThreads, putThreads, getAllBrands } from \"..\/db\/index\";\nimport type { IntentThread } from \"..\/types\";\n\ninterface ThreadDescriptor {\n  id: string;\n  keywords: string[];\n  domains: string[];\n  sampleTitles: string[];\n  domainContext: string[];\n}\n\ninterface LabelResult {\n  id: string;\n  title: string;\n  summary: string;\n  type: string;\n  nextStep: string;\n}\n\nconst VALID_TYPES: ReadonlySet<intentthread> = new Set([\n  \"buying\",\n  \"research\",\n  \"learning\",\n  \"planning\",\n  \"unclassified\",\n]);\n\nconst BATCH_SIZE = 10;\nconst MAX_TOKENS_PER_BATCH = 4000;\n\nasync function callClaudeBatch(\n  apiKey: string,\n  systemPrompt: string,\n  batch: ThreadDescriptor[],\n): Promise<labelresult null=\"\"> {\n  const response = await fetch(\"https:\/\/api.anthropic.com\/v1\/messages\", {\n    method: \"POST\",\n    headers: {\n      \"content-type\": \"application\/json\",\n      \"x-api-key\": apiKey,\n      \"anthropic-version\": \"2023-06-01\",\n      \"anthropic-dangerous-direct-browser-access\": \"true\",\n    },\n    body: JSON.stringify({\n      model: \"claude-haiku-4-5-20251001\",\n      max_tokens: MAX_TOKENS_PER_BATCH,\n      system: systemPrompt,\n      messages: [\n        {\n          role: \"user\",\n          content: JSON.stringify(batch),\n        },\n      ],\n    }),\n  });\n\n  if (!response.ok) {\n    let body = \"\";\n    try { body = (await response.text()).slice(0, 400); } catch { }\n    console.error(\n      `[openloops] label: API request failedn` +\n      `  \u2192 HTTP ({response.status} ){response.statusText}n` +\n      `  body: ${body || \"(empty)\"}`,\n    );\n    if (response.status === 401) {\n      throw new Error(\"Invalid API key. Check your Anthropic API key and try again.\");\n    }\n    throw new Error(`API request failed: ({response.status} ){response.statusText}`);\n  }\n\n  const data = await response.json();\n  const raw: string = data.content[0].text;\n\n  const cleaned = raw\n    .trim()\n    .replace(\/^```(?:json)?s*\/, \"\")\n    .replace(\/```s*$\/, \"\")\n    .trim();\n\n  try {\n    return JSON.parse(cleaned);\n  } catch (err) {\n    console.error(`[openloops] label: parse error: ${err instanceof Error ? err.message : String(err)}`);\n    console.error(`[openloops] label: raw tail (last 400 chars):n${raw.slice(-400)}`);\n    return null;\n  }\n}\n<\/labelresult><\/intentthread><\/code><\/pre>\n<p><code>BATCH_SIZE<\/code>    10 \u0645\u06cc\u06ba \u0633\u06d2 <code>MAX_TOKENS_PER_BATCH<\/code> 4000 \u06a9\u0679\u0648\u062a\u06cc \u06a9\u06d2 \u0645\u0633\u0626\u0644\u06d2 \u06a9\u0627 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u062c\u0648\u0627\u0628 \u06c1\u06d2\u06d4 10 \u062f\u06be\u0627\u06af\u0648\u06ba \u06a9\u06cc \u0645\u0627\u0644\u06cc\u062a \u06a9\u06d2 \u0644\u06cc\u0628\u0644 4000 \u0622\u0624\u0679 \u067e\u0679 \u0679\u0648\u06a9\u0646\u0632 \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u0622\u0631\u0627\u0645 \u0633\u06d2 \u0641\u0679 \u06c1\u0648\u06ba \u06af\u06d2 \u062c\u0633 \u0645\u06cc\u06ba \u06af\u0646\u062c\u0627\u0626\u0634 \u0628\u0627\u0642\u06cc \u06c1\u06d2\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u0628\u06cc\u0686 \u0627\u067e\u0646\u06cc \u062d\u062f \u062a\u06a9 \u0646\u06c1\u06cc\u06ba \u067e\u06c1\u0646\u0686\u06d2 \u06af\u0627 \u0627\u0648\u0631 \u0627\u0633\u06d2 \u0686\u06be\u0648\u0679\u0627 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4 40 \u062a\u06be\u0631\u06cc\u0688\u0632 \u0648\u0627\u0644\u0627 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u0627\u06cc\u06a9 \u0628\u0691\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0686\u0627\u0631 \u0622\u0632\u0627\u062f \u062f\u0631\u062e\u0648\u0627\u0633\u062a\u06cc\u06ba \u06c1\u0648\u06ba \u06af\u06cc\u06d4<\/p>\n<p>\u062f\u0631\u062e\u0648\u0627\u0633\u062a \u062e\u0648\u062f \u062e\u0627\u0645 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2. <code>fetch<\/code> \u06cc\u06c1 Anthropic \u06a9\u06d2 TypeScript SDK \u0646\u06c1 \u06c1\u0648\u0646\u06d2 \u06a9\u06cc \u0648\u062c\u06c1 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 SDK \u06a9\u0633\u06cc \u0628\u0631\u0627\u0624\u0632\u0631 \u06cc\u0627 \u0627\u06cc\u06a9\u0633\u0679\u06cc\u0646\u0634\u0646 \u0633\u06cc\u0627\u0642 \u0648 \u0633\u0628\u0627\u0642 \u0645\u06cc\u06ba \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0646\u06c1\u06cc\u06ba \u0628\u0646\u0627\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0628\u0631\u0627\u0624\u0632\u0631 \u0633\u06d2 \u0634\u0631\u0648\u0639 \u06a9\u06cc \u062c\u0627\u0646\u06d2 \u0648\u0627\u0644\u06cc \u0627\u0646\u062a\u06be\u0631\u0648\u067e\u06a9 API \u06a9\u0627\u0644\u0632 \u06a9\u06cc \u0628\u06be\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2: <code>anthropic-dangerous-direct-browser-access<\/code> \u06c1\u06cc\u0688\u0631 \u0648\u06c1\u06cc \u06c1\u06d2 \u062c\u0648 \u0627\u0633 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06d2 \u067e\u06cc\u0679\u0631\u0646 \u06a9\u0648 \u0627\u0679\u06be\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0645\u0627\u0688\u0644 \u06a9\u0644\u0627\u0688 \u06c1\u0627\u0626\u06cc\u06a9\u0648 \u06c1\u06d2\u060c \u062c\u0648 \u0644\u0627\u0626\u0646 \u0627\u067e \u0645\u06cc\u06ba \u0633\u0628 \u0633\u06d2 \u062a\u06cc\u0632 \u0627\u0648\u0631 \u0633\u0633\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0627\u0633 \u0637\u0631\u062d \u06a9\u06cc \u0628\u0691\u06cc\u060c \u0633\u0679\u0631\u06a9\u0686\u0631\u0688 \u0622\u0624\u0679 \u067e\u0679 \u062c\u0627\u0628\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0686\u06be\u06cc \u0637\u0631\u062d \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u06a9\u0627\u0644\u0632 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0633 \u067e\u0631 \u062a\u06cc\u0632\u06cc \u0633\u06d2 \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc \u06a9\u06cc \u062c\u0627\u0646\u06cc \u0686\u0627\u06c1\u06cc\u06d2\u06d4<\/p>\n<p>\u063a\u0644\u0637\u06cc \u0633\u06d2 \u0646\u0645\u0679\u0646\u06d2 \u06a9\u0648 \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u062f\u0648 \u0645\u062e\u062a\u0644\u0641 \u0637\u0631\u0632 \u0639\u0645\u0644 \u0645\u06cc\u06ba \u062a\u0642\u0633\u06cc\u0645 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2: HTTP \u0633\u0637\u062d \u06a9\u06cc \u0646\u0627\u06a9\u0627\u0645\u06cc \u06c1\u0648\u062a\u06cc \u06c1\u06d2 (\u062e\u0631\u0627\u0628 \u06a9\u0644\u06cc\u062f \u06a9\u06d2 \u0644\u06cc\u06d2 401\u060c \u0634\u0631\u062d \u0645\u062d\u062f\u0648\u062f \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 429)\u06d4 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0627\u0633 \u06a9\u06d2 \u0628\u0639\u062f \u06a9\u06d2 \u062a\u0645\u0627\u0645 \u0628\u06cc\u0686 \u0627\u0633\u06cc \u0637\u0631\u062d \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u0626\u06cc\u06ba \u06af\u06d2 \u0627\u0648\u0631 \u0622\u067e \u0645\u0632\u06cc\u062f \u062c\u0627\u0631\u06cc \u0646\u06c1\u06cc\u06ba \u0631\u06c1 \u0633\u06a9\u062a\u06d2\u06d4 \u06a9\u0648\u0626\u06cc \u0631\u0627\u0633\u062a\u06c1 \u0646\u06c1\u06cc\u06ba <em>\u062a\u062c\u0632\u06cc\u06c1<\/em> \u0627\u0633 \u06a9\u06d2 \u0628\u0631\u0639\u06a9\u0633\u060c \u0646\u0627\u06a9\u0627\u0645\u06cc \u0648\u0627\u067e\u0633 \u0622\u062a\u06cc \u06c1\u06d2\u06d4 <code>null<\/code> \u067e\u06be\u06cc\u0646\u06a9\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2\u060c \u06a9\u0627\u0644\u0631 \u0627\u0633 \u0627\u06cc\u06a9 \u0628\u06cc\u0686 \u06a9\u0648 \u0686\u06be\u0648\u0691 \u0633\u06a9\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0628\u0627\u0642\u06cc \u0628\u06cc\u0686\u0648\u06ba \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062c\u0627\u0631\u06cc \u0631\u06a9\u06be \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0628\u0627\u0691 \u06c1\u0679\u0627\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 <code>JSON.parse<\/code> \u0639\u0627\u0645 \u0639\u0645\u0644\u06cc \u0645\u0633\u0627\u0626\u0644 \u06a9\u0648 \u06c1\u06cc\u0646\u0688\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0645\u0627\u0688\u0644 \u0628\u0639\u0636 \u0627\u0648\u0642\u0627\u062a \u0627\u067e\u0646\u06d2 JSON \u0622\u0624\u0679 \u067e\u0679 \u06a9\u0648 \u0645\u0627\u0631\u06a9 \u0688\u0627\u0624\u0646 \u06a9\u0648\u0688 \u06a9\u06cc \u0628\u0627\u0691 \u0633\u06d2 \u0644\u067e\u06cc\u0679 \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba (<code>```json<\/code>)\u060c \u0686\u0627\u06c1\u06d2 \u0622\u067e \u062e\u0627\u0645 JSON \u06a9\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u0631 \u0631\u06c1\u06d2 \u06c1\u0648\u06ba\u06d4 \u062f\u0648 <code>.replace<\/code> \u06a9\u0627\u0644 \u0645\u0639\u0631\u0648\u0641 \u0627\u0648\u0631 \u067e\u0686\u06be\u0644\u06cc \u0628\u0627\u0691 \u06a9\u0648 \u06c1\u0679\u0627 \u06a9\u0631 \u0622\u0633 \u067e\u0627\u0633 \u06a9\u06cc \u0633\u0641\u06cc\u062f \u062c\u06af\u06c1 \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u062a\u06cc \u06c1\u06d2\u060c \u0627\u06af\u0631 \u06a9\u0648\u0626\u06cc \u06c1\u06d2\u060c \u062a\u0648 \u062c\u0648\u0627\u0628 \u062f\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u0642\u0637\u0639 \u0646\u0638\u0631 \u0627\u0633 \u06a9\u06d2 \u06a9\u06c1 \u06cc\u06c1 \u0644\u067e\u06cc\u0679 \u06a9\u0631 \u0622\u06cc\u0627 \u06c1\u06d2 \u06cc\u0627 \u0646\u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u06af\u0631 \u062a\u062c\u0632\u06cc\u06c1 \u0627\u0628 \u0628\u06be\u06cc \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u062a\u0648\u060c \u06a9\u06cc\u0686 \u062e\u0627\u0645 \u062c\u0648\u0627\u0628 \u06a9\u06d2 \u0622\u062e\u0631\u06cc 400 \u062d\u0631\u0648\u0641 \u06a9\u0648 \u0644\u0627\u06af \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0648\u06c1 \u062c\u06af\u06c1 \u06c1\u06d2 \u062c\u06c1\u0627\u06ba \u0622\u067e \u06a9\u0679 \u0622\u0641 \u0633\u0631\u0646\u06cc \u06a9\u06d2 \u062a\u0631\u0627\u0634\u06d2 \u06c1\u0648\u0626\u06d2 \u062f\u0633\u062a\u062e\u0637 \u062f\u06cc\u06a9\u06be \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u06cc\u06a9 \u0627\u06cc\u0633\u0627 \u062a\u0634\u062e\u06cc\u0635\u06cc \u062c\u0648 \u0627\u0635\u0644 \u0628\u06af \u06a9\u0648 \u0645\u0646\u0679\u0648\u06ba \u0645\u06cc\u06ba \u0638\u0627\u06c1\u0631 \u06a9\u0631 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-building-the-prompt-and-merging-results\">\u0627\u0634\u0627\u0631\u06d2 \u0628\u0646\u0627\u0626\u06cc\u06ba \u0627\u0648\u0631 \u0646\u062a\u0627\u0626\u062c \u06a9\u0648 \u0636\u0645 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<p>\u0639\u0648\u0627\u0645 <code>labelThreads<\/code> \u0641\u0646\u06a9\u0634\u0646 \u0627\u06cc\u06a9 \u0688\u0633\u06a9\u0631\u067e\u0679\u0631 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0628\u06cc\u0686 \u06a9\u0648 \u0639\u0645\u0644 \u0645\u06cc\u06ba \u0644\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0644\u0648\u0679\u06d2 \u06c1\u0648\u0626\u06d2 \u0645\u0648\u0627\u062f \u06a9\u0648 \u0636\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-typescript\">export async function labelThreads(apiKey: string): Promise<{ labeled: number }> {\n  const threads = await getAllThreads();\n  if (threads.length === 0) return { labeled: 0 };\n\n  const allBrands = await getAllBrands();\n  const brandMap = new Map(allBrands.map((b) => [b.domain, b]));\n\n  const descriptors: ThreadDescriptor[] = threads.map(\n    const keywords = [...new Set(t.sessions.flatMap((s) => s.keywords))].slice(0, 8);\n    const domains  = [...new Set(t.sessions.flatMap((s) => s.domains))].slice(0, 5);\n    const titles   = [...new Set(t.sessions.flatMap((s) => s.events.map((e) => e.title)))].slice(0, 20);\n\n    const domainContext = domains\n      .map((d) => {\n        const brand = brandMap.get(d);\n        if (!brand || !brand.name) return null;\n        let line = `({d}: ){brand.name}`;\n        if (brand.description) line += ` \u2014 ${brand.description}`;\n        if (brand.industry)    line += ` (${brand.industry})`;\n        return line;\n      })\n      .filter((s): s is string => s !== null);\n\n    return { id: t.id, keywords, domains, sampleTitles: titles, domainContext };\n  });\n\n  const systemPrompt = `You label browsing intent threads. Return ONLY a JSON array \u2014 no markdown fences, no explanation.\nEach element: { \"id\": \"<thread id=\"\">\", \"title\": \"<3-6 word title>\", \"summary\": \"<1 sentence>\", \"type\": \"<buying>\", \"nextStep\": \"<one concrete=\"\" specific=\"\" action=\"\" to=\"\" move=\"\" this=\"\" thread=\"\" forward=\"\" or=\"\" close=\"\" the=\"\" loop=\"\">\" }\nThe nextStep must be grounded in what the person was actually looking at. Be specific \u2014 name the actual decision, comparison, or action (e.g. \"Decide between MacBook Pro and Dell XPS \u2014 your open question was battery life\") rather than generic advice (\"continue researching\"). Use the sampleTitles and domainContext to ground it.\nEach thread descriptor may include a \"domainContext\" array of company descriptions for the sites visited. When present, use these to produce sharper, more specific titles, summaries, and next steps grounded in what each company actually does.\nRespond with exactly one array covering every thread in the request.`;\n\n  const allResults: LabelResult[] = [];\n  let failedBatches = 0;\n  for (let i = 0; i < descriptors.length; i += BATCH_SIZE) {\n    const batch = descriptors.slice(i, i + BATCH_SIZE);\n    const results = await callClaudeBatch(apiKey, systemPrompt, batch);\n    if (results === null) {\n      failedBatches++;\n      continue;\n    }\n    allResults.push(...results);\n  }\n\n  const byId = new Map(allResults.map((r) => [r.id, r]));\n\n  let labeled = 0;\n  const updated = threads.map(\n    const label = byId.get(t.id);\n    if (!label) return t;\n\n    const type = VALID_TYPES.has(label.type as IntentThread[\"type\"])\n      ? (label.type as IntentThread[\"type\"])\n      : t.type;\n\n    labeled++;\n    return {\n      ...t,\n      title:    label.title    || t.title,\n      summary:  label.summary  || undefined,\n      nextStep: label.nextStep || undefined,\n      type,\n    };\n  });\n\n  await putThreads(updated);\n  return { labeled };\n}\n<\/one><\/buying><\/thread><\/code><\/pre>\n<p>\u06c1\u0631 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u0648 \u0627\u0633 \u0637\u0631\u062d \u06a9\u0645\u067e\u0631\u06cc\u0633 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2: <code>ThreadDescriptor<\/code> \u06a9\u0644\u0627\u0688 \u0635\u0631\u0641 \u0648\u06c1\u06cc \u0628\u062a\u0627\u062a\u0627 \u06c1\u06d2 \u062c\u0633 \u06a9\u06cc \u0627\u0633\u06d2 \u0644\u06cc\u0628\u0644 \u0644\u06af\u0627\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4 8 \u0645\u0637\u0644\u0648\u0628\u06c1 \u0627\u0644\u0641\u0627\u0638\u060c 5 \u0688\u0648\u0645\u06cc\u0646\u0632\u060c 20 \u0646\u0645\u0648\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0635\u0641\u062d\u06c1 \u06a9\u06d2 \u0639\u0646\u0648\u0627\u0646\u0627\u062a\u060c \u0627\u0648\u0631 \u0633\u06cc\u0646\u06a9\u0691\u0648\u06ba \u0648\u0627\u0642\u0639\u0627\u062a \u0648\u0627\u0644\u06d2 \u062a\u06be\u0631\u06cc\u0688\u0632 \u067e\u06d2 \u0644\u0648\u0688 \u06a9\u0648 \u067e\u06be\u0648\u0644\u0646\u06d2 \u0633\u06d2 \u0628\u0686\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u062d\u062f\u0648\u062f \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u06a9\u06c1 <code>domainContext<\/code> \u0627\u06af\u0644\u06d2 \u062d\u0635\u06d2 \u0645\u06cc\u06ba \u0634\u0627\u0645\u0644 \u0628\u0631\u0627\u0646\u0688 \u0641\u0627\u0624\u0646\u0688\u06cc\u0634\u0646 \u06a9\u06cc \u062a\u0639\u0645\u06cc\u0631 \u06a9\u06d2 \u0645\u0631\u062d\u0644\u06d2 \u0645\u06cc\u06ba \u0641\u06cc\u0644\u0688\u0632 \u0645\u0631\u06a9\u0632\u06cc \u062d\u06cc\u062b\u06cc\u062a \u0631\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06cc\u06c1 \u0641\u06cc \u0627\u0644\u062d\u0627\u0644 \u062e\u0627\u0644\u06cc \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0627\u0628\u06be\u06cc \u062a\u06a9 \u06a9\u0648\u0626\u06cc \u0628\u0631\u0627\u0646\u0688 \u062f\u0631\u0622\u0645\u062f \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1\u06cc \u0648\u062c\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u0644\u06cc\u0628\u0644\u0646\u06af \u0627\u067e\u0646\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0627\u0686\u06be\u06cc \u0637\u0631\u062d \u06a9\u0627\u0645 \u06a9\u0631\u062a\u06cc \u06c1\u06d2 \u0627\u0648\u0631 \u062c\u0628 \u0632\u0645\u06cc\u0646 \u06a9\u0648 \u0634\u0627\u0645\u0644 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u062a\u0648 \u0648\u0627\u0636\u062d \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0646\u0636\u0645\u0627\u0645 \u06a9\u06d2 \u0645\u0631\u062d\u0644\u06d2 \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646\u060c \u0646\u0627\u06a9\u0627\u0645 \u0628\u06cc\u0686\u0648\u06ba \u06a9\u0648 \u0635\u0631\u0641 \u0627\u067e\u0646\u06d2 \u062f\u06be\u0627\u06af\u0648\u06ba \u0645\u06cc\u06ba \u0644\u0627\u06af\u062a \u0622\u062a\u06cc \u06c1\u06d2\u06d4 \u0646\u062a\u0627\u0626\u062c \u062a\u0645\u0627\u0645 \u06a9\u0627\u0645\u06cc\u0627\u0628 \u062a\u0639\u06cc\u0646\u0627\u062a\u06cc\u0648\u06ba \u06a9\u06cc \u0627\u06cc\u06a9 \u0633\u0627\u062f\u06c1 \u0641\u06c1\u0631\u0633\u062a \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0648\u0627\u067e\u0633 \u0622\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062c\u0648 \u062a\u06be\u0631\u06cc\u0688 ID \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06c1 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc \u06af\u0626\u06cc \u06c1\u06d2\u06d4 <code>byId<\/code>.<\/p>\n<p>\u0627\u0633 \u06a9\u06d2 \u0628\u0639\u062f \u06cc\u06c1 \u062a\u0645\u0627\u0645 \u062f\u06be\u0627\u06af\u0648\u06ba \u06a9\u0648 \u0639\u0628\u0648\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u0627 \u0644\u06cc\u0628\u0644 \u0648\u0627\u067e\u0633 \u0622\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f\u060c AI \u0679\u0627\u0626\u0679\u0644\u060c \u0633\u0645\u0631\u06cc\u060c \u0627\u06af\u0644\u06d2 \u0645\u0631\u0627\u062d\u0644 \u0627\u0648\u0631 \u0642\u0633\u0645 \u06a9\u0648 \u0648\u0627\u067e\u0633 \u06a9\u06cc\u06d2 \u06af\u0626\u06d2 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0645\u0644\u0627 \u062f\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>type<\/code> \u062a\u0635\u062f\u06cc\u0642 \u0634\u062f\u06c1 <code>VALID_TYPES<\/code> \u0627\u06af\u0631 \u0645\u0627\u0688\u0644 \u063a\u06cc\u0631 \u0645\u062a\u0648\u0642\u0639 \u0646\u062a\u0627\u0626\u062c \u0644\u0648\u0679\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u06cc\u06c1 \u06c1\u0648\u0631\u0633\u0679\u06a9 \u0642\u0633\u0645 \u06a9\u06cc \u0637\u0631\u0641 \u0644\u0648\u0679 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u06a9\u0648\u0626\u06cc \u0644\u06cc\u0628\u0644 \u0648\u0627\u067e\u0633 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0627\u0633 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0628\u06cc\u0686 \u067e\u0627\u0631\u0633 \u06a9\u0631\u0646\u0627 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u062f\u06be\u0627\u06af\u06c1 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u0645\u0648\u062c\u0648\u062f \u0645\u0637\u0644\u0648\u0628\u06c1 \u0627\u0644\u0641\u0627\u0638 \u06a9\u06d2 \u0639\u0646\u0648\u0627\u0646\u0627\u062a \u0627\u0648\u0631 \u06c1\u06cc\u0648\u0631\u0633\u0679\u06a9\u0633 \u06a9\u0648 \u0628\u0631\u0642\u0631\u0627\u0631 \u0631\u06a9\u06be\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0627\u0633\u06cc \u0637\u0631\u062d \u0644\u0648\u0679\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u06cc\u06a9 \u0646\u0627\u06a9\u0627\u0645 \u0628\u06cc\u0686 \u06a9\u06d2 \u0646\u062a\u06cc\u062c\u06d2 \u0645\u06cc\u06ba \u0645\u06a9\u0645\u0644 \u0631\u0646 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 10 \u062f\u06be\u0627\u06af\u0648\u06ba \u06a9\u06d2 \u0628\u0631\u0627\u0628\u0631 \u067e\u06cc\u0633\u0646\u06d2 \u06a9\u06cc \u0644\u0627\u06af\u062a \u0622\u0626\u06d2 \u06af\u06cc\u060c \u0627\u0648\u0631 \u06a9\u0648\u0626\u06cc \u062a\u06be\u0631\u06cc\u0688 \u062e\u0631\u0627\u0628 \u0688\u06cc\u0679\u0627 \u0633\u06d2 \u062e\u0631\u0627\u0628 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u06af\u0627\u06d4<\/p>\n<p>\u062a\u0648\u062c\u06c1 \u0641\u0631\u0645\u0627\u0626\u06cc\u06ba <code>title<\/code>, <code>summary<\/code>\u0627\u0648\u0631 <code>nextStep<\/code> \u062e\u0627\u0644\u06cc \u062a\u0627\u0631\u0648\u06ba \u06a9\u06d2 \u062e\u0644\u0627\u0641 \u062a\u0645\u0627\u0645 \u062a\u062d\u0641\u0638 <code>|| t.title<\/code> \u0627\u0648\u0631 <code>|| undefined<\/code>. \u06cc\u06c1\u0627\u06ba \u062a\u06a9 \u06a9\u06c1 \u0627\u06af\u0631 \u0645\u0627\u0688\u0644 \u0627\u06cc\u06a9 \u062e\u0627\u0644\u06cc \u0639\u0646\u0648\u0627\u0646 \u0644\u0648\u0679\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062f\u06be\u0627\u06af\u06d2 \u0645\u06cc\u06ba \u06c1\u0645\u06cc\u0634\u06c1 \u0627\u06cc\u06a9 \u0639\u0646\u0648\u0627\u0646 \u062f\u0633\u062a\u06cc\u0627\u0628 \u06c1\u0648\u06af\u0627\u06d4 <code>summary<\/code> \u0627\u0648\u0631 <code>nextStep<\/code> \u0631\u06c1\u0646\u0627 <code>undefined<\/code> \u0627\u06cc\u06a9 \u062e\u0627\u0644\u06cc \u062a\u0627\u0631 \u06c1\u0648\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2\u06d4 \u0627\u0633 \u0633\u06d2 \"\u06a9\u06cc\u0627 \u0627\u0633 \u062a\u06be\u0631\u06cc\u0688 \u0645\u06cc\u06ba \u06a9\u0648\u0626\u06cc \u062e\u0644\u0627\u0635\u06c1 \u06c1\u06d2\u061f\" \u0645\u062d\u0641\u0648\u0638 \u0631\u06c1\u06d2 \u06af\u0627\u06d4 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u0627\u06cc\u0645\u0627\u0646\u062f\u0627\u0631\u06cc \u0633\u06d2 \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-checkpoint\">\u0686\u0648\u06a9\u06cc<\/h3>\n<p>\u0644\u06cc\u0628\u0644\u0646\u06af \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0644\u06cc\u062f\u0648\u06ba \u0627\u0648\u0631 \u0628\u0679\u0646\u0648\u06ba \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u060c \u062c\u0648 \u062f\u0648\u0646\u0648\u06ba \u06a9\u0648 \u0628\u0639\u062f \u0645\u06cc\u06ba \u0627\u0633 \u06af\u0627\u0626\u06cc\u0688 \u0645\u06cc\u06ba \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0641\u0631\u0627\u06c1\u0645 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06c1\u0630\u0627 \u0645\u06a9\u0645\u0644 \u0627\u06cc\u0646\u0688 \u0679\u0648 \u0627\u06cc\u0646\u0688 \u0679\u06cc\u0633\u0679\u0646\u06af \u0627\u0633 \u0648\u0642\u062a \u062a\u06a9 \u0627\u0646\u062a\u0638\u0627\u0631 \u06a9\u0631\u06d2 \u06af\u06cc\u06d4<\/p>\n<p>\u062c\u0648 \u0622\u067e \u0627\u0628\u06be\u06cc \u0686\u06cc\u06a9 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>src\/lib\/settings.ts<\/code> \u0627\u0648\u0631 <code>src\/pipeline\/label.ts<\/code> \u0627\u0633 \u0628\u0627\u062a \u06a9\u0648 \u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u06c1 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u0627\u0686\u06be\u06cc \u0637\u0631\u062d \u0633\u06d2 \u062a\u0634\u06a9\u06cc\u0644 \u062f\u06cc \u06af\u0626\u06cc \u06c1\u06d2\u060c \u0645\u0631\u062a\u0628 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u06a9\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 <code>labelThreads<\/code> \u0627\u06af\u0631 \u0622\u067e \u0641\u0648\u0631\u06cc \u0641\u06cc\u0688 \u0628\u06cc\u06a9 \u0686\u0627\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba \u062a\u0648 \u0627\u06cc\u06a9 \u0639\u0627\u0631\u0636\u06cc \u0679\u06cc\u0633\u0679 \u0679\u0648\u0644 \u0645\u06cc\u06ba \u0627\u0635\u0644\u06cc \u06a9\u0644\u06cc\u062f\u06cc\u06ba \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 \u062c\u0628 \u06a9\u0633\u06cc \u0628\u0646\u06d2 \u06c1\u0648\u0626\u06d2 \u062f\u06be\u0627\u06af\u06d2 \u06a9\u06d2 \u062e\u0644\u0627\u0641 \u0686\u0644\u0627\u06cc\u0627 \u062c\u0627\u0626\u06d2\u060c <code>console<\/code> \u0622\u067e \u0627\u067e\u0646\u06cc \u062a\u0639\u06cc\u0646\u0627\u062a\u06cc \u06a9\u06cc \u067e\u06cc\u0634\u0631\u0641\u062a \u062f\u06cc\u06a9\u06be\u06cc\u06ba \u06af\u06d2\u060c \u0627\u0648\u0631 IndexedDB \u0645\u06cc\u06ba \u062a\u06be\u0631\u06cc\u0688 \u06a9\u0627 \u0639\u0646\u0648\u0627\u0646 \u06a9\u0644\u06cc\u062f\u06cc \u0627\u0644\u0641\u0627\u0638 \u06a9\u06d2 \u0679\u06a9\u0691\u0648\u06ba \u0633\u06d2 \u067e\u0691\u06be\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u0641\u0642\u0631\u06d2 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4 <code>summary<\/code> \u0627\u0648\u0631 <code>nextStep<\/code> \u067e\u06c1\u0644\u0627 \u0641\u06cc\u0644\u0688 \u062c\u0648 \u0638\u0627\u06c1\u0631 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0644\u06cc\u0628\u0644\u0632 \u06a9\u0648 \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u0628\u06c1\u062a \u0628\u06c1\u062a\u0631 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u0648\u06c1 \u0627\u0628 \u0628\u06be\u06cc \u06a9\u0644\u06cc\u062f\u06cc \u0627\u0644\u0641\u0627\u0638 \u0627\u0648\u0631 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0688\u0648\u0645\u06cc\u0646 \u0646\u0627\u0645\u0648\u06ba \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u0633 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2 \u06a9\u06c1 \u0627\u0633 \u06a9\u06d2 \u0627\u0631\u062f \u06af\u0631\u062f \u0627\u06cc\u06a9 \u062f\u06be\u0627\u06af\u06c1 \u0628\u0646\u0627 \u06c1\u0648\u0627 \u06c1\u06d2\u06d4 <code>mastra.ai<\/code> \u0627\u0648\u0631 <code>langchain.com<\/code> \u0645\u062c\u06be\u06d2 \u0646\u06c1\u06cc\u06ba \u0645\u0639\u0644\u0648\u0645 \u06a9\u06c1 \u06cc\u06c1 AI \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0627 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u06c1\u06d2\u06d4 \u0635\u0631\u0641 \u062f\u0648 \u0688\u0648\u0645\u06cc\u0646 \u0633\u0679\u0631\u0646\u06af\u0632 \u062f\u06a9\u06be\u0627\u0626\u06d2 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u06af\u0644\u0627 \u0633\u06cc\u06a9\u0634\u0646 \u0688\u0648\u0645\u06cc\u0646\u0632 \u06a9\u0648 \u0644\u06cc\u0628\u0644 \u0644\u06af\u0627\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u06a9\u0645\u067e\u0646\u06cc \u06a9\u06cc \u0627\u0635\u0644 \u062a\u0641\u0635\u06cc\u0644 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u0646 \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u06a9\u06d2 \u0627\u0633 \u062e\u0644\u0627 \u06a9\u0648 \u062f\u0648\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0627\u06cc\u06a9 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0642\u062f\u0645 \u06c1\u06d2 \u062c\u0648 AI \u06a9\u0648 \u0627\u0633\u062a\u062f\u0644\u0627\u0644 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0679\u06be\u0648\u0633 \u0645\u0648\u0627\u062f \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h2 id=\"heading-how-to-ground-labels-with-contextdev\">context.dev \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0644\u06cc\u0628\u0644 \u06a9\u0648 \u06af\u0631\u0627\u0624\u0646\u0688 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0637\u0631\u06cc\u0642\u06c1<\/h2>\n<p>\u06cc\u06c1 \u0627\u0648\u067e\u0646 \u0644\u0648\u067e\u0633 \u06a9\u0627 \u0633\u0628 \u0633\u06d2 \u0645\u0646\u0641\u0631\u062f \u062e\u06cc\u0627\u0644 \u06c1\u06d2\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u06a9\u0648\u0688 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0648\u0627\u0636\u062d \u0637\u0648\u0631 \u067e\u0631 \u0627\u0633 \u06a9\u0627 \u0630\u06a9\u0631 \u06a9\u0631\u0646\u0627 \u0636\u0631\u0648\u0631\u06cc \u06c1\u06d2\u06d4 \u0645\u0627\u0688\u0644 \u06a9\u0648 \u0645\u0637\u0644\u0648\u0628\u06c1 \u0627\u0644\u0641\u0627\u0638 \u0627\u0648\u0631 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0688\u0648\u0645\u06cc\u0646 \u0646\u0627\u0645\u0648\u06ba \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062a\u06be\u0631\u06cc\u0688\u0632 \u06a9\u0648 \u0644\u06cc\u0628\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u06c1\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2\u060c \u0627\u0648\u067e\u0646 \u0644\u0648\u067e\u0633 \u067e\u06c1\u0644\u06d2 \u06c1\u0631 \u0688\u0648\u0645\u06cc\u0646 \u06a9\u06cc \u0627\u0635\u0644 \u06a9\u0645\u067e\u0646\u06cc \u06a9\u06cc \u062a\u0641\u0635\u06cc\u0644 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 (\u06a9\u0645\u067e\u0646\u06cc \u06a9\u06cc\u0627 \u06c1\u06d2\u060c \u06cc\u06c1 \u06a9\u0633 \u0635\u0646\u0639\u062a \u0645\u06cc\u06ba \u06c1\u06d2\u060c \u06cc\u06c1 \u0627\u0635\u0644 \u0645\u06cc\u06ba \u06a9\u06cc\u0627 \u06a9\u0631\u062a\u06cc \u06c1\u06d2) \u0627\u0648\u0631 \u0627\u0633 \u062a\u0641\u0635\u06cc\u0644 \u06a9\u0648 \u0644\u06cc\u0628\u0644\u0646\u06af \u067e\u0631\u0627\u0645\u067e\u0679 \u0645\u06cc\u06ba \u0641\u06cc\u0688 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4 \u0645\u0627\u0688\u0644 \u062a\u06be\u0631\u06cc\u0688\u0632 \u06a9\u0648 \u06cc\u06c1 \u062c\u0627\u0646\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0644\u06cc\u0628\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1: <code>mastra.ai<\/code> \u0627\u0648\u0631 <code>langchain.com<\/code> \u062f\u0648 \u0645\u0628\u06c1\u0645 \u062a\u0627\u0631\u0648\u06ba \u06a9\u0648 \u062f\u06cc\u06a9\u06be\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u062c\u0646 \u06a9\u0627 \u0622\u067e \u06a9\u0648 \u0627\u0646\u062f\u0627\u0632\u06c1 \u0644\u06af\u0627\u0646\u0627 \u06c1\u06d2\u060c \u0648\u06c1 \u062f\u0648\u0646\u0648\u06ba AI \u0627\u06cc\u062c\u0646\u0679 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u06a9\u0644\u06cc\u062f\u06cc \u0644\u0641\u0638 \"mastra langchain sholajegede\" \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u06cc\u06a9 \u062f\u06be\u0627\u06af\u06c1 \"Mastra Langchain Sholajegede\" \u062c\u06cc\u0633\u0627 \u0639\u0646\u0648\u0627\u0646 \u067e\u06cc\u062f\u0627 \u06a9\u0631\u06d2 \u06af\u0627 \u062c\u0648 \u0628\u063a\u06cc\u0631 \u06a9\u0633\u06cc \u0628\u0646\u06cc\u0627\u062f \u06a9\u06d2 \u06a9\u0644\u06cc\u062f\u06cc \u0644\u0641\u0638 \u06a9\u06cc \u0639\u06a9\u0627\u0633\u06cc \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633 \u0639\u0644\u0645 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u06a9\u06c1 \u0688\u0648\u0645\u06cc\u0646 \u0627\u06cc\u06a9 \u0645\u0633\u0627\u0628\u0642\u062a\u06cc \u0627\u06cc\u062c\u0646\u0679 \u06a9\u0627 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u06c1\u06d2\u060c \u0648\u06c1\u06cc \u062f\u06be\u0627\u06af\u06c1 \"LangChain \u06a9\u06d2 \u062e\u0644\u0627\u0641 \u0628\u06cc\u0646\u0686 \u0645\u0627\u0631\u06a9\u0646\u06af \u0645\u0627\u0633\u0679\u0631\u0627\" \u06a9\u06d2 \u0639\u0646\u0648\u0627\u0646 \u0633\u06d2 \u0627\u0635\u0644 \u0627\u0631\u0627\u062f\u06d2 \u06a9\u0627 \u0646\u0627\u0645 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0686\u06be\u06d2 \u0644\u06cc\u0628\u0644 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062e\u0627\u0645 \u0645\u0627\u0644 \u06c1\u0645\u06cc\u0634\u06c1 \u062a\u0644\u0627\u0634 \u0645\u06cc\u06ba \u0645\u0648\u062c\u0648\u062f \u0631\u06c1\u0627 \u06c1\u06d2\u06d4 \u062c\u0648 \u063a\u0627\u0626\u0628 \u062a\u06be\u0627 \u0648\u06c1 \u0627\u0633 \u06a9\u06cc \u062a\u0634\u0631\u06cc\u062d \u06a9\u06d2 \u0644\u06cc\u06d2 \u0633\u06cc\u0627\u0642 \u0648 \u0633\u0628\u0627\u0642 \u062a\u06be\u0627\u060c \u0627\u0648\u0631 \u06cc\u06c1 \u0648\u06c1\u06cc \u06c1\u06d2 \u062c\u0648 \u0628\u0631\u0627\u0646\u0688 \u0627\u0646\u0679\u06cc\u0644\u06cc \u062c\u0646\u0633 API \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-what-the-api-returns\">API \u06a9\u06cc\u0627 \u0648\u0627\u067e\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/h3>\n<p>openloops context.dev \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062c\u0648 \u0688\u0648\u0645\u06cc\u0646\u0632 \u06a9\u0648 \u0633\u0679\u0631\u06a9\u0686\u0631\u0688 \u0628\u0631\u0627\u0646\u0688 \u0631\u06cc\u06a9\u0627\u0631\u0688\u0632 \u0645\u06cc\u06ba \u062a\u0631\u062c\u0645\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u06cc\u0633\u06d2 \u06a9\u0645\u067e\u0646\u06cc \u06a9\u0627 \u0646\u0627\u0645\u060c \u0627\u06cc\u06a9 \u0644\u0627\u0626\u0646 \u06a9\u06cc \u062a\u0641\u0635\u06cc\u0644\u060c \u0635\u0646\u0639\u062a \u06a9\u06cc \u062f\u0631\u062c\u06c1 \u0628\u0646\u062f\u06cc\u060c \u0628\u0631\u0627\u0646\u0688 \u06a9\u06d2 \u0631\u0646\u06af\u060c \u0627\u0648\u0631 \u0644\u0648\u06af\u0648 URL\u06d4 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0645\u0631\u0627\u062d\u0644 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0646\u0627\u0645\u060c \u062a\u0641\u0635\u06cc\u0644 \u0627\u0648\u0631 \u0635\u0646\u0639\u062a \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u060c \u062c\u0628\u06a9\u06c1 \u0644\u0648\u06af\u0648 \u0627\u0648\u0631 \u0631\u0646\u06af\u0648\u06ba \u06a9\u0648 \u0628\u0639\u062f \u0645\u06cc\u06ba \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u0645\u06cc\u06ba \u0688\u0648\u0645\u06cc\u0646 \u0686\u067e \u067e\u06cc\u0634 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4<\/p>\n<p>\u06cc\u06c1 \u0645\u0631\u062d\u0644\u06c1 \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u0627\u062e\u062a\u06cc\u0627\u0631\u06cc \u06c1\u06d2\u06d4 \u067e\u0686\u06be\u0644\u06d2 \u062d\u0635\u06d2 \u0645\u06cc\u06ba \u0644\u06cc\u0628\u0644\u0646\u06af \u0627\u0633 \u0642\u062f\u0645 \u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u060c \u0627\u0648\u0631 context.dev \u06a9\u0644\u06cc\u062f \u0645\u0648\u062c\u0648\u062f \u06c1\u0648\u0646\u06d2 \u067e\u0631 \u06af\u0631\u0627\u0624\u0646\u0688 \u0622\u0624\u0679 \u067e\u0679 \u06a9\u0648 \u0648\u0627\u0636\u062d \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>Anthropic \u06a9\u0644\u06cc\u062f \u06a9\u06cc \u0637\u0631\u062d\u060c context.dev \u06a9\u0644\u06cc\u062f \u0628\u06be\u06cc \u06c1\u06d2\u06d4 <code>chrome.storage.local<\/code>\u0627\u0633\u06cc \u06af\u06cc\u0679\u0631\/\u0633\u06cc\u0679\u0631 \u067e\u06cc\u0679\u0631\u0646 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 <code>src\/lib\/settings.ts<\/code>:<\/p>\n<pre><code class=\"language-typescript\">export async function getContextKey(): Promise<string null=\"\"> {\n  const result = await chrome.storage.local.get(\"contextDevApiKey\");\n  return (result.contextDevApiKey as string) ?? null;\n}\n\nexport async function setContextKey(key: string): Promise<void> {\n  await chrome.storage.local.set({ contextDevApiKey: key });\n}\n<\/void><\/string><\/code><\/pre>\n<p>\u0686\u0648\u0646\u06a9\u06c1 \u0627\u06cc\u06a9 \u06c1\u06cc \u0688\u0648\u0645\u06cc\u0646 \u06a9\u06cc \u062f\u0648 \u0628\u0627\u0631 \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u0646\u0627 \u0641\u0636\u0648\u0644 \u06c1\u06d2 \u0627\u0648\u0631 API \u06a9\u0631\u06cc\u0688\u0679\u0633 \u06a9\u06cc \u0644\u0627\u06af\u062a \u0622\u062a\u06cc \u06c1\u06d2\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u0622\u067e \u06a9\u0648 \u0627\u067e\u0646\u06d2 \u0628\u0631\u0627\u0646\u0688 \u0631\u06cc\u06a9\u0627\u0631\u0688\u0632 \u06a9\u0648 \u06a9\u06cc\u0634 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u062c\u06af\u06c1 \u06a9\u06cc \u0628\u06be\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4 \u06a9\u0631\u06cc\u0634 <code>DB_VERSION<\/code> 4 \u0627\u0648\u0631 \u0645\u06cc\u06ba \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 <code>domain_brands<\/code> \u0688\u0648\u0645\u06cc\u0646 \u06a9\u0644\u06cc\u062f \u0630\u062e\u06cc\u0631\u06d2:<\/p>\n<pre><code class=\"language-typescript\">import type { RawEvent, Session, IntentThread, Brand } from \"..\/types\";\n\ninterface OpenloopsDB extends DBSchema {\n  raw_events: { key: string; value: RawEvent; indexes: { by_visitedAt: number } };\n  sessions: { key: string; value: Session; indexes: { by_startedAt: number } };\n  intent_threads: { key: string; value: IntentThread; indexes: { by_lastSeen: number } };\n  domain_brands: {\n    key: string;\n    value: Brand;\n  };\n}\n\nconst DB_VERSION = 4;\n<\/code><\/pre>\n<p>\u0627\u0646\u062f\u0631\u0648\u0646\u06cc <code>upgrade<\/code> \u06a9\u0627\u0644 \u0628\u06cc\u06a9 \u06a9\u0648 \u0627\u0646\u062c\u0627\u0645 \u062f\u06cc\u0646\u06d2 \u0633\u06d2 \u0646\u0626\u06d2 \u0631\u06cc\u067e\u0648\u0632\u0679\u0631\u06cc \u0645\u06cc\u06ba \u0648\u06c1\u06cc \u06af\u0627\u0631\u0688\u0632 \u0634\u0627\u0645\u0644 \u06c1\u0648 \u062c\u0627\u0626\u06cc\u06ba \u06af\u06d2 \u062c\u06cc\u0633\u06d2 \u062f\u06cc\u06af\u0631 \u0631\u06cc\u067e\u0648\u0632\u0679\u0631\u06cc\u0632\u06d4 <code>domain_brands<\/code> \u0686\u0627\u0628\u06cc \u0622\u0646 \u06c1\u06d2 <code>domain<\/code> \u0628\u0644\u06a9\u06c1 <code>id<\/code> \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0688\u0648\u0645\u06cc\u0646 \u0627\u06cc\u06a9 \u0645\u0646\u0641\u0631\u062f\u060c \u0645\u0646\u0641\u0631\u062f \u06a9\u0644\u06cc\u062f \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-typescript\">if (!db.objectStoreNames.contains(\"domain_brands\")) {\n  db.createObjectStore(\"domain_brands\", { keyPath: \"domain\" });\n}\n<\/code><\/pre>\n<p>\u0645\u0645\u0627\u062b\u0644 \u0645\u062f\u062f\u06af\u0627\u0631 \u06a9\u06cc\u0634\u0646\u06af \u0633\u06d2 \u0645\u062a\u0639\u0644\u0642 \u0645\u062f\u062f\u06af\u0627\u0631 \u0634\u0627\u0645\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>getCachedDomains<\/code>. \u06cc\u06c1 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u062a\u0635\u062f\u06cc\u0642 \u0634\u062f\u06c1 \u0688\u0648\u0645\u06cc\u0646\u0632 \u06a9\u0627 \u0627\u06cc\u06a9 \u0633\u06cc\u0679 \u0648\u0627\u067e\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062a\u0627\u06a9\u06c1 \u06c1\u0645 \u0627\u0646\u06c1\u06cc\u06ba \u0633\u062e\u062a\u06cc \u06a9\u06d2 \u0645\u0631\u062d\u0644\u06d2 \u0645\u06cc\u06ba \u0686\u06be\u0648\u0691 \u0633\u06a9\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-typescript\">export async function getBrand(domain: string): Promise<brand undefined=\"\"> {\n  const db = await getDB();\n  return db.get(\"domain_brands\", domain);\n}\n\nexport async function putBrands(brands: Brand[]): Promise<void> {\n  if (brands.length === 0) return;\n  const db = await getDB();\n  const tx = db.transaction(\"domain_brands\", \"readwrite\");\n  await Promise.all([...brands.map((b) => tx.store.put(b)), tx.done]);\n}\n\nexport async function getAllBrands(): Promise<brand> {\n  const db = await getDB();\n  return db.getAll(\"domain_brands\");\n}\n\nexport async function getCachedDomains(): Promise<set>> {\n  const db = await getDB();\n  const keys = await db.getAllKeys(\"domain_brands\");\n  return new Set(keys);\n}\n<\/set><\/brand><\/void><\/brand><\/code><\/pre>\n<h3 id=\"heading-fetching-one-brand\">\u0627\u06cc\u06a9 \u0628\u0631\u0627\u0646\u0688 \u062f\u0631\u0622\u0645\u062f \u06a9\u0631\u0646\u0627<\/h3>\n<p>\u0628\u0646\u0627\u0646\u0627 <code>src\/pipeline\/enrich.ts<\/code>. \u06a9\u0644\u06cc\u062f \u0627\u06cc\u06a9 \u0688\u0648\u0645\u06cc\u0646 \u06a9\u0648 \u062d\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0635\u0644\u0627\u062d\u06cc\u062a \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0627\u0633 \u06a9\u06cc \u0632\u06cc\u0627\u062f\u06c1 \u062a\u0631 \u0644\u0645\u0628\u0627\u0626\u06cc \u0627\u0633 \u0628\u0627\u062a \u06a9\u0648 \u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u0648\u062c\u0648\u062f \u06c1\u06d2 \u06a9\u06c1 \u0633\u0633\u062a \u06cc\u0627 \u0646\u0627\u06a9\u0627\u0645 \u062a\u0644\u0627\u0634 \u06a9\u06cc \u0648\u062c\u06c1 \u0633\u06d2 \u067e\u0648\u0631\u0627 \u0645\u0631\u062d\u0644\u06c1 \u0644\u0679\u06a9 \u062c\u0627\u0626\u06d2 \u06cc\u0627 \u06a9\u0631\u06cc\u0634 \u0646\u06c1 \u06c1\u0648\u06d4<\/p>\n<pre><code class=\"language-typescript\">import { getCachedDomains, putBrands } from \"..\/db\/index\";\nimport { isLocalHost } from \"..\/lib\/util\";\nimport type { Brand } from \"..\/types\";\n\nconst API_BASE        = \"https:\/\/api.context.dev\/v1\";\nconst LOGO_LINK_BASE  = \"https:\/\/logos.context.dev\";\n\nconst REQUEST_TIMEOUT_MS = 15_000;\nconst BATCH_SIZE     = 3;\nconst BATCH_DELAY_MS = 2_000;\n\ninterface FetchResult {\n  brand: Brand | null;\n  errorCode?: string;\n}\n\nasync function fetchBrand(domain: string, contextKey: string): Promise<fetchresult> {\n  const url = `({API_BASE}\/brand\/retrieve?domain=){encodeURIComponent(domain)}`;\n  const headers = { Authorization: `Bearer ${contextKey}` };\n\n  async function attempt(): Promise<response> {\n    const ctrl = new AbortController();\n    const tid  = setTimeout(() => ctrl.abort(), REQUEST_TIMEOUT_MS);\n    try {\n      return await fetch(url, { headers, signal: ctrl.signal });\n    } finally {\n      clearTimeout(tid);\n    }\n  }\n\n  try {\n    let res = await attempt();\n\n    if (res.status === 408) {\n      res = await attempt();\n    }\n\n    if (!res.ok) {\n      let body = \"\";\n      try { body = (await res.text()).slice(0, 400); } catch { }\n      console.error(`[openloops] enrich: HTTP ({res.status} for \"){domain}\" \u2014 ${body}`);\n      return { brand: null, errorCode: String(res.status) };\n    }\n\n    let data: { status?: string; brand?: Record<string unknown=\"\"> };\n    try {\n      data = await res.json();\n    } catch (e) {\n      return { brand: null, errorCode: \"parse\" };\n    }\n\n    if (data.status !== \"ok\" || !data.brand) {\n      return { brand: null, errorCode: \"shape\" };\n    }\n\n    const b = data.brand as {\n      title?:        string;\n      description?:  string;\n      colors?:       { hex?: string }[];\n      logos?:        { url?: string }[];\n      industries?:   { eic?: { industry?: string; subindustry?: string }[] };\n    };\n\n    const logoUrl =\n      b.logos?.[0]?.url ||\n      `({LOGO_LINK_BASE}?domain=){encodeURIComponent(domain)}`;\n\n    return {\n      brand: {\n        domain,\n        name:        b.title                          ?? domain,\n        description: b.description                    ?? \"\",\n        industry:    b.industries?.eic?.[0]?.industry ?? \"\",\n        logoUrl,\n        brandColor:  b.colors?.[0]?.hex               ?? \"\",\n      },\n    };\n\n  } catch (err) {\n    if (err instanceof Error && err.name === \"AbortError\") {\n      return { brand: null, errorCode: \"timeout\" };\n    }\n    return { brand: null, errorCode: \"network\" };\n  }\n}\n<\/string><\/response><\/fetchresult><\/code><\/pre>\n<p>\u062f\u0631\u062e\u0648\u0627\u0633\u062a \u0628\u06cc\u0626\u0631\u0631 \u0679\u0648\u06a9\u0646 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062a\u0635\u062f\u06cc\u0642 \u0634\u062f\u06c1 \u06c1\u06d2 \u0627\u0648\u0631 \u06c1\u06d2\u06d4 <code>brand\/retrieve<\/code> \u0627\u062e\u062a\u062a\u0627\u0645\u06cc \u0646\u0642\u0637\u06c1 \u06a9\u06c1 <code>attempt<\/code> \u0627\u0646\u062f\u0631\u0648\u0646\u06cc \u0641\u0646\u06a9\u0634\u0646 \u06c1\u0631 \u06a9\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>AbortController<\/code> \u06c1\u0645 15 \u0633\u06cc\u06a9\u0646\u0688 \u06a9\u0627 \u0679\u0627\u0626\u0645 \u0622\u0624\u0679 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0644\u06c1\u0670\u0630\u0627 \u0627\u0633\u0642\u0627\u0637 \u0634\u062f\u06c1 \u06a9\u0646\u06a9\u0634\u0646 \u0633\u062e\u062a\u06cc \u06a9\u06d2 \u0645\u0631\u062d\u0644\u06d2 \u06a9\u0648 \u063a\u06cc\u0631 \u0645\u0639\u06cc\u0646\u06c1 \u0645\u062f\u062a \u062a\u06a9 \u0645\u0639\u0637\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u062e\u0648\u062f \u06c1\u06cc \u0627\u0633\u0642\u0627\u0637 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4<\/p>\n<p>\u06a9\u06c1 <code>finally<\/code> \u0679\u0627\u0626\u0645\u0631 \u06a9\u0648 \u0627\u0633 \u0628\u0646\u06cc\u0627\u062f \u067e\u0631 \u0635\u0627\u0641 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0622\u06cc\u0627 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u0627\u0645\u06cc\u0627\u0628 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u060c \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648\u062c\u0627\u062a\u06cc \u06c1\u06d2\u060c \u06cc\u0627 \u0627\u0633\u0642\u0627\u0637 \u06c1\u0648\u062c\u0627\u062a\u06cc \u06c1\u06d2\u06d4 \u06a9\u0648\u0626\u06cc \u0631\u0627\u0633\u062a\u06c1 \u0646\u06c1\u06cc\u06ba <code>408<\/code> context.dev \u06a9\u06cc \u0637\u0631\u0641 \u0633\u06d2 \u062c\u0648\u0627\u0628 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2 \u0627\u0633 \u0637\u0631\u0641 \u0627\u06cc\u06a9 \u06a9\u0648\u0644\u0688 \u06a9\u06cc\u0634 \u0645\u0633\u06d4 \u062f\u0633\u062a\u0627\u0648\u06cc\u0632\u0627\u062a \u0645\u06cc\u06ba \u06a9\u06c1\u0627 \u06af\u06cc\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u06cc\u06ba\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u0645\u06cc\u06ba \u06c1\u0627\u0631 \u0645\u0627\u0646\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u062a\u0627 \u06c1\u0648\u06ba\u06d4<\/p>\n<p>\u0631\u062f\u0639\u0645\u0644 \u06c1\u0631 \u0633\u0637\u062d \u067e\u0631 \u062f\u0641\u0627\u0639\u06cc \u06c1\u06d2\u06d4 \u0648\u06c1 \u0631\u06cc\u0627\u0633\u062a \u062c\u0648 \u0679\u06be\u06cc\u06a9 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 <code>FetchResult<\/code> \u0627\u06af\u0631 \u0622\u067e HTTP \u06a9\u0648\u0688 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0648\u06c1 \u0628\u0627\u0688\u06cc \u06c1\u0648\u06af\u06cc \u062c\u0633\u06d2 \u0622\u067e \u067e\u0627\u0631\u0633 \u0646\u06c1\u06cc\u06ba \u06a9\u0631 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>\"parse\"<\/code> \u0627\u06af\u0631 \u06a9\u0648\u0626\u06cc \u063a\u0644\u0637\u06cc \u06c1\u0648\u062a\u06cc \u06c1\u06d2 \u0627\u0648\u0631 \u062c\u0648\u0627\u0628 \u062a\u0648\u0642\u0639 \u0633\u06d2 \u0645\u062e\u062a\u0644\u0641 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u06cc\u06c1 \u0648\u0627\u067e\u0633 \u0622\u062a\u0627 \u06c1\u06d2: <code>\"shape\"<\/code> \u063a\u0644\u0637\u06cc<\/p>\n<p>\u062c\u0628 \u0627\u06cc\u06a9 \u0628\u0631\u0627\u0646\u0688 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u067e\u0627\u0633 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u06c1\u0631 \u0641\u06cc\u0644\u0688 \u0627\u06cc\u06a9 \u0645\u0646\u0627\u0633\u0628 \u0688\u06cc\u0641\u0627\u0644\u0679 \u067e\u0631 \u0648\u0627\u067e\u0633 \u0622\u062c\u0627\u0626\u06d2 \u06af\u0627 \u0627\u06af\u0631 \u063a\u0627\u0626\u0628 \u06c1\u0648 \u062c\u0627\u0626\u06d2\u060c \u06a9\u0645\u067e\u0646\u06cc \u06a9\u0627 \u0646\u0627\u0645 \u062e\u0648\u062f \u0688\u0648\u0645\u06cc\u0646 \u0645\u06cc\u06ba \u0648\u0627\u067e\u0633 \u0622\u062c\u0627\u0626\u06d2 \u06af\u0627\u060c \u062a\u0641\u0635\u06cc\u0644 \u0627\u0648\u0631 \u0635\u0646\u0639\u062a \u0627\u06cc\u06a9 \u062e\u0627\u0644\u06cc \u0633\u0679\u0631\u0646\u06af \u067e\u0631 \u0648\u0627\u067e\u0633 \u0622\u062c\u0627\u0626\u06d2 \u06af\u06cc\u060c \u0627\u0648\u0631 \u0627\u06af\u0631 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u0645\u06cc\u06ba \u06a9\u0648\u0626\u06cc \u0644\u0648\u06af\u0648 URL \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u060c \u062a\u0648 \u0644\u0648\u06af\u0648 context.dev \u0645\u06cc\u06ba \u06a9\u0644\u06cc\u062f\u06cc \u0644\u0648\u06af\u0648 CDN \u067e\u0631 \u0648\u0627\u067e\u0633 \u0622\u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4<\/p>\n<p>\u062a\u0645\u0627\u0645 \u0646\u0627\u06a9\u0627\u0645 \u0631\u0627\u0633\u062a\u06d2 \u0648\u0627\u067e\u0633 \u0622 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>{ brand: null, errorCode }<\/code> \u06cc\u06c1 \u0627\u0633 \u0644\u06cc\u06d2 \u06c1\u06d2 \u06a9\u06c1 \u0645\u0646\u062f\u0631\u062c\u06c1 \u0628\u0627\u0644\u0627 \u0628\u06cc\u0686 \u0688\u0631\u0627\u0626\u06cc\u0648\u0631 \u06a9\u0633\u06cc \u0627\u06cc\u06a9 \u0688\u0648\u0645\u06cc\u0646 \u06a9\u06cc \u0646\u0627\u06a9\u0627\u0645\u06cc \u06a9\u0648 \u06a9\u0631\u06cc\u0634 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0627\u0633\u06a9\u06cc\u067e \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0633\u0646\u0628\u06be\u0627\u0644 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-enriching-domains-in-batches\">\u0628\u06cc\u0686\u0648\u06ba \u0645\u06cc\u06ba \u0688\u0648\u0645\u06cc\u0646\u0632 \u06a9\u0648 \u0645\u0636\u0628\u0648\u0637 \u0628\u0646\u0627\u0626\u06cc\u06ba<\/h3>\n<p>\u0639\u0648\u0627\u0645 <code>enrichDomains<\/code> \u0641\u0646\u06a9\u0634\u0646 \u0688\u0648\u0645\u06cc\u0646\u0632 \u06a9\u06cc \u0641\u06c1\u0631\u0633\u062a \u06a9\u0648 \u0686\u06cc\u06a9 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0688\u0648\u0645\u06cc\u0646\u0632 \u06a9\u0648 \u0686\u06be\u0648\u0691\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u06a9\u06cc\u0634 \u0634\u062f\u06c1 \u06c1\u06cc\u06ba \u0627\u0648\u0631 API \u06a9\u06cc \u0634\u0631\u062d \u06a9\u06cc \u062d\u062f\u0648\u062f \u06a9\u0627 \u0627\u062d\u062a\u0631\u0627\u0645 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-typescript\">export async function enrichDomains(\n  contextKey: string,\n  domains: string[],\n): Promise<{ enriched: number; failed: number; error?: string }> {\n  const unique = [...new Set(domains)].filter((d) => !isLocalHost(d));\n\n  let cached: Set<string>;\n  try {\n    cached = await getCachedDomains();\n  } catch (err) {\n    return { enriched: 0, failed: 0, error: \"DB error\" };\n  }\n\n  const toFetch = unique.filter((d) => !cached.has(d));\n  if (toFetch.length === 0) return { enriched: 0, failed: 0 };\n\n  let enriched = 0;\n  let failed   = 0;\n  let firstErrorCode: string | undefined;\n\n  for (let i = 0; i < toFetch.length; i += BATCH_SIZE) {\n    const batch   = toFetch.slice(i, i + BATCH_SIZE);\n    const results = await Promise.all(batch.map((d) => fetchBrand(d, contextKey)));\n\n    const brands = results.map((r) => r.brand).filter((b): b is Brand => b !== null);\n\n    for (const r of results) {\n      if (!r.brand) {\n        failed += 1;\n        if (!firstErrorCode) firstErrorCode = r.errorCode;\n      }\n    }\n\n    if (brands.length > 0) {\n      try {\n        await putBrands(brands);\n        enriched += brands.length;\n      } catch (err) {\n        failed += brands.length;\n      }\n    }\n\n    if (i + BATCH_SIZE < toFetch.length) {\n      await new Promise<void>((resolve) => setTimeout(resolve, BATCH_DELAY_MS));\n    }\n  }\n\n  let error: string | undefined;\n  if (firstErrorCode) {\n    const map: Record<string string=\"\"> = {\n      \"401\":     \"401 \u2014 invalid key\",\n      \"403\":     \"403 \u2014 check key permissions\",\n      \"429\":     \"429 \u2014 rate limited, try again later\",\n      \"timeout\": \"request timeout (15 s)\",\n      \"network\": \"unreachable \u2014 check network\/CORS\",\n    };\n    error = map[firstErrorCode] ?? firstErrorCode;\n  }\n\n  return { enriched, failed, error };\n}\n<\/string><\/void><\/string><\/code><\/pre>\n<p>\u06cc\u06c1 \u0641\u0646\u06a9\u0634\u0646 \u0645\u0646\u062f\u0631\u062c\u06c1 \u0630\u06cc\u0644 \u0645\u0642\u0627\u0645\u06cc \u0627\u06cc\u0688\u0631\u06cc\u0633 \u06a9\u0648 \u0627\u062a\u0627\u0631 \u06a9\u0631 \u06a9\u06be\u0648\u0644\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2: <code>isLocalHost<\/code>\u0627\u0641\u0632\u0648\u062f\u06c1 \u0628\u0627\u0624\u0646\u0688\u0631\u06cc \u06af\u0627\u0631\u0688 \u067e\u0631 \u062e\u0648\u062f \u062d\u0648\u0627\u0644\u06c1 \u0634\u0648\u0631 \u0648\u0627\u0644\u06d2 \u062d\u0635\u06d2 \u0645\u06cc\u06ba \u062a\u0628\u0627\u062f\u0644\u06c1 \u062e\u06cc\u0627\u0644 \u06a9\u06cc\u0627 \u06af\u06cc\u0627\u06d4 \u0627\u0633 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2 \u06a9\u06c1 \u0627\u06af\u0631 \u0688\u0648\u06cc\u0644\u067e\u0645\u0646\u0679 \u0633\u0631\u0648\u0631 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u06cc \u0688\u0648\u0645\u06cc\u0646 \u0644\u0633\u0679 \u0645\u06cc\u06ba \u062f\u0627\u062e\u0644 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u062a\u0648 \u0628\u06be\u06cc \u0627\u0633\u06d2 context.dev \u067e\u0631 \u0646\u06c1\u06cc\u06ba \u0628\u06be\u06cc\u062c\u0627 \u062c\u0627 \u0633\u06a9\u062a\u0627\u06d4 \u067e\u06be\u0631 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u06a9\u06cc\u0634 \u0634\u062f\u06c1 \u0688\u0648\u0645\u06cc\u0646\u0632 \u06a9\u0648 \u0628\u0630\u0631\u06cc\u0639\u06c1 \u06c1\u0679\u0627\u0626\u06cc\u06ba: <code>getCachedDomains<\/code>\u0644\u06c1\u0630\u0627\u060c \u0627\u06af\u0631 \u0622\u067e \u062f\u0648\u0628\u0627\u0631\u06c1 \u0627\u0641\u0632\u0648\u062f\u06af\u06cc \u0686\u0644\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0622\u067e \u06a9\u0648 \u0635\u0631\u0641 \u0648\u06c1 \u0688\u0648\u0645\u06cc\u0646 \u0645\u0644\u06cc\u06ba \u06af\u06d2 \u062c\u0648 \u0622\u067e \u0646\u06d2 \u0646\u06c1\u06cc\u06ba \u062f\u06cc\u06a9\u06be\u06d2 \u06c1\u0648\u06ba \u06af\u06d2\u06d4 \u06cc\u06c1 \u0622\u067e \u06a9\u06d2 \u06a9\u0631\u06cc\u0688\u0679 \u06a9\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0648 \u06a9\u0644 \u062a\u0644\u0627\u0634\u0648\u06ba \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0646\u0626\u06cc \u062a\u0644\u0627\u0634\u0648\u06ba \u06a9\u06d2 \u0645\u062a\u0646\u0627\u0633\u0628 \u0631\u06a9\u06be\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0628\u0642\u06cc\u06c1 \u0688\u0648\u0645\u06cc\u0646\u0632 \u0628\u06cc\u0686\u0648\u06ba \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 2 \u0633\u06cc\u06a9\u0646\u0688 \u06a9\u06d2 \u0648\u0642\u0641\u06d2 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u06cc\u06a9 \u0648\u0642\u062a \u0645\u06cc\u06ba 3 \u062f\u0631\u0622\u0645\u062f \u06a9\u06cc\u06d2 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06cc\u06c1 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u06cc \u0634\u0631\u062d\u0648\u06ba \u06a9\u0648 API \u06a9\u06cc \u062d\u062f \u0633\u06d2 \u0646\u06cc\u0686\u06d2 \u0631\u06a9\u06be\u062a\u0627 \u06c1\u06d2 \u0628\u063a\u06cc\u0631 \u0635\u0627\u0631\u0641\u06cc\u0646 \u06a9\u0648 \u0637\u0648\u06cc\u0644 \u0633\u06cc\u0631\u06cc\u0644 \u0642\u0637\u0627\u0631\u0648\u06ba \u0645\u06cc\u06ba \u0627\u0646\u062a\u0638\u0627\u0631 \u06a9\u0631\u0646\u0627 \u067e\u0691\u06d2\u06d4<\/p>\n<p>\u0646\u0627\u06a9\u0627\u0645\u06cc\u0627\u06ba \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u06ba \u06af\u06cc \u0627\u0648\u0631 \u0644\u0627\u06af \u0627\u0646 \u06c1\u0648\u06ba \u06af\u06cc\u06d4 \u0688\u0648\u0645\u06cc\u0646\u0632 \u062c\u0648 \u0627\u0636\u0627\u0641\u06c1 \u06a9\u0648 \u062d\u0644 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>failed<\/code> \u06cc\u06c1 \u0627\u06cc\u06a9 \u0627\u06cc\u0631\u0631 \u06a9\u0648\u0688 \u06a9\u0648 \u0644\u0627\u06af \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u0644\u0648\u067e \u062c\u0627\u0631\u06cc \u0631\u06c1\u062a\u0627 \u06c1\u06d2\u06d4 \u0633\u0627\u0645\u0646\u06d2 \u0622\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u067e\u06c1\u0644\u06d2 \u0627\u06cc\u0631\u0631 \u06a9\u0648\u0688 \u06a9\u0648 \u0622\u062e\u0631 \u0645\u06cc\u06ba \u0627\u0646\u0633\u0627\u0646\u06cc \u067e\u0691\u06be\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u067e\u06cc\u063a\u0627\u0645 \u0645\u06cc\u06ba \u0645\u06cc\u067e \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062c\u0633 \u0633\u06d2 UI \u0645\u0641\u06cc\u062f \u0645\u0639\u0644\u0648\u0645\u0627\u062a \u062c\u06cc\u0633\u06d2 \u063a\u0644\u0637 \u06a9\u0644\u06cc\u062f \u06cc\u0627 \u0634\u0631\u062d \u06a9\u06cc \u062d\u062f \u06a9\u06cc \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u0638\u0627\u06c1\u0631 \u06a9\u0631 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u067e\u0648\u0631\u0627 \u0641\u0646\u06a9\u0634\u0646 \u0627\u0633 \u0645\u06cc\u06ba \u0627\u0636\u0627\u0641\u06c1 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u06af\u0646\u062a\u06cc \u0644\u0648\u0679\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0636\u0631\u0648\u0631\u06cc \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u0644\u06cc\u0628\u0644 \u0644\u06af\u0627\u0646\u06d2 \u0633\u06d2 \u0679\u06be\u06cc\u06a9 \u067e\u06c1\u0644\u06d2 \u0627\u0641\u0632\u0648\u062f\u06af\u06cc \u0686\u0644\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0627\u0633 \u06a9\u06d2 \u0628\u0639\u062f \u0644\u06cc\u0628\u0644 \u0644\u06af\u0627\u0646\u06d2 \u0645\u06cc\u06ba \u0628\u0631\u0627\u0646\u0688\u0646\u06af \u06a9\u06d2 \u0645\u0633\u0627\u0626\u0644 \u06a9\u06cc \u0648\u062c\u06c1 \u0633\u06d2 \u0631\u06a9\u0627\u0648\u0679 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u0646\u06cc \u0686\u0627\u06c1\u06cc\u06d2\u06d4<\/p>\n<h3 id=\"heading-how-grounding-feeds-back-into-labeling\">\u06a9\u0633 \u0637\u0631\u062d \u06af\u0631\u0627\u0624\u0646\u0688\u0646\u06af \u0644\u06cc\u0628\u0644\u0646\u06af \u067e\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0644\u0627\u06af\u0648 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4<\/h3>\n<p>\u0632\u0645\u06cc\u0646 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u062c\u0648\u0691 \u062f\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4 <code>labelThreads<\/code> \u067e\u0686\u06be\u0644\u06d2 \u062d\u0635\u06d2 \u0645\u06cc\u06ba \u06c1\u0645 \u0646\u06d2 \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u062a\u0639\u0645\u06cc\u0631 \u06a9\u06cc\u0627 <code>domainContext<\/code> \u0628\u0631\u0627\u0646\u0688 \u06a9\u06cc\u0634\u06d2 \u0645\u06cc\u06ba \u062a\u0645\u0627\u0645 \u0688\u0648\u0645\u06cc\u0646\u0632 \u06a9\u0648 \u0628\u0627\u0632\u06cc\u0627\u0641\u062a \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u06c1\u0631 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2:<\/p>\n<pre><code class=\"language-typescript\">const domainContext = domains\n  .map((d) => {\n    const brand = brandMap.get(d);\n    if (!brand || !brand.name) return null;\n    let line = `({d}: ){brand.name}`;\n    if (brand.description) line += ` \u2014 ${brand.description}`;\n    if (brand.industry)    line += ` (${brand.industry})`;\n    return line;\n  })\n  .filter((s): s is string => s !== null);\n<\/code><\/pre>\n<p>\u0627\u0641\u0632\u0648\u062f\u06af\u06cc \u06a9\u06d2 \u0686\u0644\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2\u060c \u0628\u0631\u0627\u0646\u0688 \u06a9\u06cc\u0634 \u062e\u0627\u0644\u06cc \u06c1\u06d2 \u0627\u0648\u0631 \u062a\u0645\u0627\u0645 \u06c1\u0679 \u06a9\u0686\u06be \u0628\u06be\u06cc \u0646\u06c1\u06cc\u06ba \u0644\u0648\u0679\u0627\u062a\u06d2\u06d4 <code>domainContext<\/code> \u06cc\u06c1 \u0627\u06cc\u06a9 \u062e\u0627\u0644\u06cc \u0635\u0641 \u06c1\u06d2 \u0627\u0648\u0631 \u067e\u0631\u0627\u0645\u067e\u0679 \u06a9\u0648 \u0635\u0631\u0641 \u0645\u0637\u0644\u0648\u0628\u06c1 \u0627\u0644\u0641\u0627\u0638 \u0627\u0648\u0631 \u0688\u0648\u0645\u06cc\u0646 \u0646\u0627\u0645 \u0633\u06d2 \u0628\u062f\u0644 \u062f\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0633\u062e\u062a \u06c1\u0648\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f\u060c \u0648\u06c1\u06cc \u06a9\u0648\u0688 \u0627\u0633 \u0637\u0631\u062d \u06a9\u06cc \u0644\u0627\u0626\u0646\u06cc\u06ba \u062a\u06cc\u0627\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2: <code>mastra.ai: Mastra \u2014 TypeScript framework for building AI agents (Developer Tools)<\/code>\u0644\u06cc\u0628\u0644\u0646\u06af \u067e\u0631\u0627\u0645\u067e\u0679\u0633 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06c1\u062f\u0627\u06cc\u0627\u062a <code>domainContext<\/code> \u0622\u062e\u0631 \u06a9\u0627\u0631 \u0645\u06cc\u0631\u06d2 \u067e\u0627\u0633 \u06a9\u0627\u0645 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0686\u06be \u062a\u06be\u0627\u060c \"\u0648\u0627\u0636\u062d \u0627\u0648\u0631 \u0632\u06cc\u0627\u062f\u06c1 \u0645\u062e\u0635\u0648\u0635 \u0639\u0646\u0648\u0627\u0646\u0627\u062a\u060c \u062e\u0644\u0627\u0635\u06d2\u060c \u0627\u0648\u0631 \u0627\u06af\u0644\u06d2 \u0645\u0631\u0627\u062d\u0644 \u0628\u0646\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2\u06d4\"<\/p>\n<p>\u062f\u0648\u0646\u0648\u06ba \u0645\u0631\u0627\u062d\u0644 \u06a9\u0648 \u0688\u06cc\u0632\u0627\u0626\u0646 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0627\u0644\u06af \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0631\u0686\u06c1 \u0644\u06cc\u0628\u0644\u0646\u06af \u06a9\u06d2 \u0644\u06cc\u06d2 \u06af\u0631\u0627\u0624\u0646\u0688\u0646\u06af \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u06af\u0631\u0627\u0624\u0646\u0688\u0646\u06af \u0644\u06cc\u0628\u0644\u0646\u06af \u06a9\u0648 \u0646\u0645\u0627\u06cc\u0627\u06ba \u0637\u0648\u0631 \u067e\u0631 \u0628\u06c1\u062a\u0631 \u0628\u0646\u0627\u062a\u06cc \u06c1\u06d2\u06d4 \u06cc\u06c1\u06cc \u0648\u062c\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u0627\u0646\u06c1\u06cc\u06ba \u0627\u06cc\u06a9 \u06c1\u06cc \"\u0627\u06cc\u0646\u0631\u0634 \u0627\u0648\u0631 \u0644\u06cc\u0628\u0644\" \u06a9\u0627\u0645 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u062a\u0631\u062a\u06cc\u0628 \u0648\u0627\u0631 \u0686\u0644\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-checkpoint\">\u0686\u0648\u06a9\u06cc<\/h3>\n<p>\u0644\u06cc\u0628\u0644\u0646\u06af \u06a9\u06d2 \u0645\u0631\u062d\u0644\u06d2 \u06a9\u06cc \u0637\u0631\u062d\u060c \u0627\u0641\u0632\u0648\u062f\u06af\u06cc \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u06a9\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06d2\u060c \u0644\u06c1\u0630\u0627 \u0645\u06a9\u0645\u0644 \u0631\u0627\u0633\u062a\u06c1 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u0633\u06cc\u06a9\u0634\u0646 \u06a9\u0627 \u0645\u0646\u062a\u0638\u0631 \u06c1\u06d2\u06d4 \u0627\u0628\u06be\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u062f\u0631\u062c \u0630\u06cc\u0644 \u06a9\u0648 \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba: <code>src\/pipeline\/enrich.ts<\/code> \u0627\u0648\u0631 \u0627\u067e \u0688\u06cc\u0679 <code>src\/db\/index.ts<\/code> \u0627\u0633\u06d2 \u0645\u0631\u062a\u0628 \u06a9\u0631\u06cc\u06ba\u060c \u0627\u0648\u0631 <code>getDB()<\/code> \u0631\u067e\u0648\u0631\u0679 \u0648\u0631\u0698\u0646 4\u06d4 <code>domain_brands<\/code> \u06cc\u06c1 DevTools \u0645\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<p>\u062c\u0628 context.dev \u06a9\u0644\u06cc\u062f \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u06a9\u0633\u06cc \u062d\u0642\u06cc\u0642\u06cc \u062f\u06be\u0627\u06af\u06d2 \u06a9\u06d2 \u062e\u0644\u0627\u0641 \u0686\u0644\u0627\u06cc\u0627 \u062c\u0627\u0626\u06d2\u060c <code>domain_brands<\/code> \u0627\u0633\u0679\u0648\u0631 \u06a9\u06cc\u0634 \u0634\u062f\u06c1 \u0631\u06cc\u06a9\u0627\u0631\u0688\u0632 \u0633\u06d2 \u0628\u06be\u0631 \u062c\u0627\u0626\u06d2 \u06af\u0627\u060c \u0627\u0648\u0631 \u062a\u06be\u0631\u06cc\u0688 \u0644\u06cc\u0628\u0644 \u0646\u0645\u0627\u06cc\u0627\u06ba \u0637\u0648\u0631 \u067e\u0631 \u0648\u0627\u0636\u062d \u06c1\u0648 \u062c\u0627\u0626\u06cc\u06ba \u06af\u06d2\u06d4 \u0633\u0628 \u0633\u06d2 \u0648\u0627\u0636\u062d \u0648\u0627\u062d\u062f \u0645\u0638\u0627\u06c1\u0631\u06c1 \u0627\u06cc\u06a9 \u0637\u0627\u0642 \u06cc\u0627 \u0679\u06cc\u06a9\u0646\u0627\u0644\u0648\u062c\u06cc \u0688\u0648\u0645\u06cc\u0646 \u06a9\u06d2 \u0627\u0631\u062f \u06af\u0631\u062f \u0628\u0646\u0627\u06cc\u0627 \u06af\u06cc\u0627 \u0627\u06cc\u06a9 \u062f\u06be\u0627\u06af\u06c1 \u06c1\u0648\u06af\u0627 \u062c\u0633 \u06a9\u0627 \u0646\u0627\u0645 \u062e\u0648\u062f \u0638\u0627\u06c1\u0631 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u0627 \u06a9\u06c1 \u06cc\u06c1 \u06a9\u06cc\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0646\u062c\u0646 \u06a9\u06d2 \u062a\u0645\u0627\u0645 \u062d\u0635\u06d2 \u0627\u0628 \u0645\u0648\u062c\u0648\u062f \u06c1\u06cc\u06ba: \u06a9\u06cc\u067e\u0686\u0631\u060c \u0633\u06cc\u0634\u0646\u0632\u060c \u06a9\u0644\u0633\u0679\u0631\u0646\u06af\u060c \u0627\u0633\u06a9\u0648\u0631\u0646\u06af\u060c \u0644\u06cc\u0628\u0644\u0646\u06af\u060c \u0627\u0648\u0631 \u06af\u0631\u0627\u0624\u0646\u0688\u0646\u06af\u06d4 \u062c\u0648 \u0686\u06cc\u0632 \u063a\u0627\u0626\u0628 \u06c1\u06d2 \u0648\u06c1 \u0627\u06cc\u06a9 \u0633\u0637\u062d \u06c1\u06d2 \u062c\u0648 \u0627\u0633\u06d2 \u0686\u0644\u0627\u062a\u06cc \u06c1\u06d2 \u0627\u0648\u0631 \u0646\u062a\u0627\u0626\u062c \u062f\u06a9\u06be\u0627\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u06af\u0644\u06d2 \u062d\u0635\u06d2 \u0645\u06cc\u06ba\u060c \u06c1\u0645 \u0627\u06cc\u06a9 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688\u060c \u0627\u06cc\u06a9 \u0622\u0646 \u0628\u0648\u0631\u0688\u0646\u06af \u0641\u0644\u0648 \u0627\u0648\u0631 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0633\u0679\u06cc\u0679 \u0645\u0634\u06cc\u0646 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062a\u06cc\u0646 \u06a9\u0627\u0644\u0645 \u0631\u06cc \u0627\u06cc\u06a9\u0679 \u0627\u0646\u0679\u0631\u0641\u06cc\u0633 \u0628\u0646\u0627 \u06a9\u0631 \u0627\u0633 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u0648 \u0627\u0646\u0633\u0627\u0646\u06cc \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062d\u0642\u06cc\u0642\u06cc \u0686\u06cc\u0632 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631 \u062f\u06cc\u06ba \u06af\u06d2\u06d4<\/p>\n<h2 id=\"heading-how-to-design-the-dashboard\">\u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u06a9\u0648 \u06a9\u06cc\u0633\u06d2 \u0688\u06cc\u0632\u0627\u0626\u0646 \u06a9\u0631\u06cc\u06ba\u06d4<\/h2>\n<p>\u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u0631\u06cc \u0627\u06cc\u06a9\u0679 \u0627\u062c\u0632\u0627\u0621 \u06a9\u0627 \u0627\u06cc\u06a9 \u0648\u0627\u062d\u062f \u062f\u0631\u062e\u062a \u06c1\u06d2 \u062c\u0633\u06d2 \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u0679\u06cc\u0628 \u0634\u062f\u06c1 \u0635\u0641\u062d\u06c1 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u067e\u06cc\u0634 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062c\u0633 \u0633\u06d2 \u0622\u067e \u0627\u0628\u062a\u062f\u0627\u0626\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0633\u06cc\u0679 \u0627\u067e \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646 \u0645\u0646\u0633\u0644\u06a9 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>options_page<\/code> \u0638\u0627\u06c1\u0631 \u0645\u06cc\u06ba\u06d4<\/p>\n<p>\u06cc\u06c1 \u062a\u06cc\u0646 \u0686\u06cc\u0632\u06cc\u06ba \u06a9\u0631\u062a\u0627 \u06c1\u06d2: \u06cc\u06c1 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0686\u0644\u0627\u062a\u0627 \u06c1\u06d2 (\u0628\u0679\u0646 \u062c\u0648 \u0627\u0633\u06a9\u06cc\u0646 \u0686\u0644\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0633\u06cc\u0634\u0646 \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u06be\u0631\u06cc\u0688\u0632 \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0627\u0646 \u067e\u0631 \u0644\u06cc\u0628\u0644 \u0644\u06af\u0627\u062a\u06d2 \u06c1\u06cc\u06ba)\u060c \u0646\u062a\u06cc\u062c\u06d2 \u0645\u06cc\u06ba \u0622\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0627\u0631\u0627\u062f\u06d2 \u06a9\u0627 \u0646\u0642\u0634\u06c1 \u062f\u06a9\u06be\u0627\u062a\u0627 \u06c1\u06d2 (\u0631\u06cc\u0627\u0633\u062a \u06a9\u06d2 \u0644\u062d\u0627\u0638 \u0633\u06d2 \u062f\u06be\u0627\u06af\u0648\u06ba \u06a9\u0648 \u06af\u0631\u0648\u067e \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2)\u060c \u0627\u0648\u0631 \u0627\u06af\u0644\u06d2 \u062d\u0635\u06d2 \u0645\u06cc\u06ba \u06a9\u0648\u0631 \u06a9\u06cc\u06d2 \u06af\u0626\u06d2 \u0645\u062f\u062f\u06af\u0627\u0631\u0648\u06ba \u06a9\u06cc \u0645\u06cc\u0632\u0628\u0627\u0646\u06cc \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u06cc\u06c1 \u0633\u06cc\u06a9\u0634\u0646 \u0633\u0627\u062e\u062a \u0627\u0648\u0631 \u0645\u0646\u0637\u0642 \u06a9\u06d2 \u0648\u0627\u0642\u0639\u06cc \u062f\u0644\u0686\u0633\u067e \u0679\u06a9\u0691\u0648\u06ba \u0645\u06cc\u06ba \u0633\u06d2 \u0627\u06cc\u06a9 \u067e\u0631 \u062a\u0648\u062c\u06c1 \u0645\u0631\u06a9\u0648\u0632 \u06a9\u0631\u062a\u0627 \u06c1\u06d2: \u0631\u06cc\u0627\u0633\u062a\u06cc \u0645\u0634\u06cc\u0646 \u062c\u0648 \u06cc\u06c1 \u0637\u06d2 \u06a9\u0631\u062a\u06cc \u06c1\u06d2 \u06a9\u06c1 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u0627 \u06a9\u0648\u0646 \u0633\u0627 \u0628\u0679\u0646 \u06a9\u0633\u06cc \u0628\u06be\u06cc \u0648\u0642\u062a \u0641\u0639\u0627\u0644 \u06c1\u06d2\u06d4 \u0637\u0631\u0632\u06cc\u06ba \u0632\u06cc\u0627\u062f\u06c1 \u062a\u0631 \u0633\u0627\u062f\u06c1 \u0633\u06cc \u0627\u06cc\u0633 \u0627\u06cc\u0633 \u06c1\u0648\u062a\u06cc \u06c1\u06cc\u06ba\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u0645\u06cc\u06ba \u0627\u0646\u06c1\u06cc\u06ba \u06cc\u06c1\u0627\u06ba \u0633\u0645\u0631\u06cc \u0644\u06cc\u0648\u0644 \u067e\u0631 \u06a9\u0648\u0631 \u06a9\u0631\u0648\u06ba \u06af\u0627\u06d4<\/p>\n<h3 id=\"heading-the-three-column-layout\">3 \u06a9\u0627\u0644\u0645 \u0644\u06d2 \u0622\u0624\u0679<\/h3>\n<p><code>src\/dashboard\/App.tsx<\/code>    \u0641\u0644\u06cc\u06a9\u0633 \u0634\u06cc\u0644 \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u062a\u06cc\u0646 \u06a9\u0627\u0644\u0645 \u0631\u06a9\u06be\u06cc\u06ba\u06d4 \u0628\u0627\u0626\u06cc\u06ba \u0631\u06cc\u0644 \u0645\u06cc\u06ba \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u0646\u0679\u0631\u0648\u0644\u0632\u060c API \u06a9\u0644\u06cc\u062f\u06cc \u0627\u0646 \u067e\u0679\u060c \u0627\u0648\u0631 \u0627\u0633\u0679\u06cc\u0679\u0633 \u0641\u0644\u0679\u0631\u0632 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0645\u0631\u06a9\u0632\u06cc \u06a9\u0627\u0644\u0645 \u0645\u0631\u06a9\u0632\u06cc \u0645\u0648\u0627\u062f \u06c1\u06d2\u060c \u062c\u06cc\u0633\u06d2 \u0622\u0646 \u0628\u0648\u0631\u0688\u0646\u06af \u0633\u067e\u0644\u06cc\u0634 \u0627\u0633\u06a9\u0631\u06cc\u0646 \u06cc\u0627 \u062f\u06be\u0627\u06af\u06d2 \u06a9\u0627 \u0627\u0631\u0627\u062f\u06c1 \u0646\u0642\u0634\u06c1\u06d4 \u062f\u0627\u0626\u06cc\u06ba \u06a9\u0627\u0644\u0645 \u0645\u06cc\u06ba \u0645\u062c\u0645\u0648\u0639\u06cc \u0627\u0639\u062f\u0627\u062f \u0648 \u0634\u0645\u0627\u0631 \u0627\u0648\u0631 \u062b\u0627\u0646\u0648\u06cc \u0686\u06cc\u0679 \u0634\u0627\u0645\u0644 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-plaintext\">\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502  LEFT RAIL   \u2502       MAIN COLUMN         \u2502  RIGHT COLUMN    \u2502\n\u2502              \u2502                           \u2502                  \u2502\n\u2502  Pipeline    \u2502  Welcome screen           \u2502  Overview stats  \u2502\n\u2502   \u00b7 Scan     \u2502    \u2014 or \u2014                 \u2502                  \u2502\n\u2502   \u00b7 Sessions \u2502  Intent map:              \u2502  Assistant chat  \u2502\n\u2502   \u00b7 Threads  \u2502   ACTIVE   threads        \u2502   \u00b7 messages     \u2502\n\u2502              \u2502   STALLED  threads        \u2502   \u00b7 composer     \u2502\n\u2502  Keys        \u2502   DORMANT  threads        \u2502   \u00b7 model\/effort \u2502\n\u2502  Filter      \u2502                           \u2502                  \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n<\/code><\/pre>\n<p>\u06c1\u0631 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u0648 \u0627\u06cc\u06a9 \u06a9\u0627\u0631\u0688 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u067e\u06cc\u0634 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u062c\u0633 \u0645\u06cc\u06ba \u0679\u0627\u0626\u0679\u0644\u060c \u0679\u0627\u0626\u067e \u0627\u0648\u0631 \u0633\u0679\u06cc\u0679\u0633 \u06a9\u06cc \u06af\u0648\u0644\u06cc\u0627\u06ba\u060c AI \u0633\u0645\u0631\u06cc\u060c \u0631\u06cc\u0632\u06cc\u0648\u0645\u06d2 \u0628\u0679\u0646 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u06af\u0644\u06cc \u0633\u0679\u06cc\u067e \u0642\u0637\u0627\u0631\u060c \u06a9\u0646\u0641\u06cc\u0688\u06cc\u0646\u0633 \u0628\u0627\u0631\u060c \u0688\u0648\u0645\u06cc\u0646\u060c \u06a9\u0644\u06cc\u062f\u06cc \u0627\u0644\u0641\u0627\u0638 \u0627\u0648\u0631 \u0633\u06af\u0646\u0644\u0632 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0679\u0648\u0679\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u062a\u0641\u0635\u06cc\u0644\u0627\u062a \u06a9\u0627 \u0633\u06cc\u06a9\u0634\u0646 \u062f\u06a9\u06be\u0627\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u06a9\u0627\u0631\u0688\u0632 \u06a9\u0648 ACTIVE\u060c STALLED\u060c \u0627\u0648\u0631 DORMANT \u062d\u0635\u0648\u06ba \u0645\u06cc\u06ba \u06af\u0631\u0648\u067e \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u06c1\u0631 \u06af\u0631\u0648\u067e \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u0627\u0639\u062a\u0645\u0627\u062f \u06a9\u06cc \u0633\u0637\u062d \u06a9\u06d2 \u0645\u0637\u0627\u0628\u0642 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0633\u0628 \u0633\u06d2 \u0642\u06cc\u0645\u062a\u06cc \u062f\u06be\u0627\u06af\u06d2 \u0686\u0644\u06cc\u06ba \u06af\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0648\u06c1 \u0627\u0646\u062a\u06c1\u0627\u0626\u06cc \u0636\u0631\u0648\u0631\u06cc \u06af\u0631\u0648\u067e \u06a9\u06d2 \u0627\u0648\u067e\u0631\u06cc \u062d\u0635\u06d2 \u067e\u0631 \u062c\u0627\u0626\u06cc\u06ba \u06af\u06d2\u06d4<\/p>\n<p>\u0627\u0633\u0679\u0627\u0626\u0644 \u0632\u0646\u062f\u06c1 \u06c1\u06d2\u06d4 <code>src\/dashboard\/app.css<\/code> \u0627\u0648\u0631 \u06cc\u06c1 \u0631\u0648\u0627\u06cc\u062a\u06cc \u06c1\u06d2: \u0633\u06cc\u0627\u06c1 \u062a\u06be\u06cc\u0645 (\u0642\u0631\u06cc\u0628 \u0633\u06cc\u0627\u06c1 \u067e\u0633 \u0645\u0646\u0638\u0631\u060c \u0633\u0646\u06af\u0644 \u0646\u0627\u0631\u0646\u062c\u06cc \u0644\u06c1\u062c\u06c1) \u062c\u0633 \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a CSS \u062d\u0633\u0628 \u0636\u0631\u0648\u0631\u062a \u062e\u0635\u0648\u0635\u06cc\u0627\u062a \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u06a9\u06cc \u06af\u0626\u06cc \u06c1\u06d2\u06d4 <code>--accent: #ff5c33<\/code>\u0645\u062a\u0646 \u0627\u0648\u0631 \u0628\u0627\u0631\u0688\u0631\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0686\u06be\u0648\u0679\u0627 \u06af\u0631\u06d2 \u0627\u0633\u06a9\u06cc\u0644)\u060c \u0644\u06cc\u0628\u0644\u0632 \u0627\u0648\u0631 \u0645\u06cc\u0679\u0627 \u0688\u06cc\u0679\u0627 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u0648\u0646\u0648 \u0627\u0633\u067e\u06cc\u0633\u0688 \u0641\u0648\u0646\u0679\u0633\u060c \u0627\u0648\u0631 \u0645\u0648\u0627\u062f \u06a9\u06d2 \u0644\u06cc\u06d2 sans-serif \u0641\u0648\u0646\u0679\u0633\u06d4<\/p>\n<p>\u0688\u06cc\u0632\u0627\u0626\u0646 \u06a9\u06d2 \u0627\u0646\u062a\u062e\u0627\u0628 \u062c\u0648 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06c1\u0645 \u06c1\u06cc\u06ba \u0631\u06cc\u0627\u0633\u062a\u06cc \u0628\u0646\u06cc\u0627\u062f \u067e\u0631 \u06a9\u0644\u0631 \u06a9\u0648\u0688\u0646\u06af (\u0641\u0639\u0627\u0644 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0644\u06c1\u062c\u06c1\u060c \u0645\u0639\u0637\u0644 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062e\u0627\u0645\u0648\u0634 \u0627\u0645\u0628\u0631\u060c \u063a\u06cc\u0631 \u0641\u0639\u0627\u0644 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0633\u0631\u0645\u0626\u06cc) \u0627\u0648\u0631 \u0627\u0639\u062a\u0645\u0627\u062f \u0628\u0627\u0631 \u06a9\u06cc \u0686\u0648\u0691\u0627\u0626\u06cc \u06a9\u0648 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u062f\u06be\u0627\u06af\u06d2 \u06a9\u06d2 \u0627\u0639\u062a\u0645\u0627\u062f \u06a9\u06d2 \u0633\u06a9\u0648\u0631 \u067e\u0631 \u0646\u0642\u0634 \u06a9\u0631\u0646\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>CSS \u0645\u06cc\u06ba \u0633\u06d2 \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u062a\u0639\u0645\u06cc\u0631 \u06a9\u0648 \u0633\u0645\u062c\u06be\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0628\u0648\u062c\u06be \u0628\u0631\u062f\u0627\u0634\u062a \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u0627 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u0627\u0633\u06d2 \u062f\u0648\u0628\u0627\u0631\u06c1 \u062a\u06cc\u0627\u0631 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2\u060c \u0627\u0633 \u062d\u0635\u06d2 \u06a9\u0627 \u0628\u0627\u0642\u06cc \u062d\u0635\u06c1 \u0627\u0633\u0679\u0627\u0626\u0644 \u06a9\u06cc \u0628\u0646\u06cc\u0627\u062f\u06cc \u0645\u0646\u0637\u0642 \u067e\u0631 \u062a\u0648\u062c\u06c1 \u0645\u0631\u06a9\u0648\u0632 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-the-pipeline-state-machine\">\u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0631\u06cc\u0627\u0633\u062a \u0645\u0634\u06cc\u0646<\/h3>\n<p>\u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0645\u06cc\u06ba \u0633\u062e\u062a \u062d\u06a9\u0645 \u06c1\u06d2\u06d4 \u0631\u06cc\u06a9\u0627\u0631\u0688\u0632 \u0627\u0633\u06a9\u06cc\u0646 \u06c1\u0648\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0633\u06cc\u0634\u0646\u0632 \u0646\u06c1\u06cc\u06ba \u0628\u0646\u0627\u0626\u06d2 \u062c\u0627 \u0633\u06a9\u062a\u06d2\u060c \u0627\u0648\u0631 \u0633\u06cc\u0634\u0646\u0632 \u0628\u0646\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u062a\u06be\u0631\u06cc\u0688\u0632 \u0646\u06c1\u06cc\u06ba \u0628\u0646\u0627\u0626\u06d2 \u062c\u0627 \u0633\u06a9\u062a\u06d2\u06d4 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u0627\u0633\u06d2 \u0627\u06cc\u06a9 \u0686\u06be\u0648\u0679\u06cc \u0633\u0679\u06cc\u0679 \u0645\u0634\u06cc\u0646 \u0645\u06cc\u06ba \u0627\u0646\u06a9\u0648\u0688 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0635\u062d\u06cc\u062d \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u0633\u06cc\u0679 \u0627\u067e \u06c1\u0648\u0646\u06d2 \u067e\u0631\u060c \u0627\u0646\u0679\u0631\u0641\u06cc\u0633 \u0627\u0644\u062c\u06be\u0646\u06d2 \u06a9\u06cc \u0628\u062c\u0627\u0626\u06d2 \u0631\u06c1\u0646\u0645\u0627\u0626\u06cc \u0645\u062d\u0633\u0648\u0633 \u06a9\u0631\u06d2 \u06af\u0627\u06d4 \u062a\u0645\u0627\u0645 \u0628\u0679\u0646 \u06cc\u0627 \u062a\u0648 \u063a\u06cc\u0631 \u0641\u0639\u0627\u0644 \u06c1\u06cc\u06ba (\u0627\u0646 \u067e\u0679 \u0627\u0628\u06be\u06cc \u0645\u0648\u062c\u0648\u062f \u0646\u06c1\u06cc\u06ba \u06c1\u06d2)\u060c \u0627\u06af\u0644\u06cc \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0646\u0645\u0627\u06cc\u0627\u06ba \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u060c \u06cc\u0627 \u0645\u06a9\u0645\u0644 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2 (\u062f\u0648\u0628\u0627\u0631\u06c1 \u0642\u0627\u0628\u0644\u060c \u0644\u06cc\u06a9\u0646 \u0627\u0628 \u06a9\u0648\u0626\u06cc \u0648\u0627\u0636\u062d \u0627\u06af\u0644\u0627 \u0645\u0631\u062d\u0644\u06c1 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2)\u06d4<\/p>\n<pre><code class=\"language-typescript\">type PipelineState = \"disabled\" | \"next\" | \"done\";\n\nfunction pipelineStates(\n  hasScanned: boolean,\n  eventCount: number | null,\n  sessionCount: number | null,\n  threadCount: number | null,\n): { scan: PipelineState; sessions: PipelineState; threads: PipelineState } {\n  const hasEvents   = (eventCount   ?? 0) > 0;\n  const hasSessions = (sessionCount ?? 0) > 0;\n  const hasThreads  = (threadCount  ?? 0) > 0;\n\n  if (!hasScanned)  return { scan: \"next\", sessions: \"disabled\", threads: \"disabled\" };\n  if (!hasSessions) return { scan: \"done\", sessions: hasEvents ? \"next\" : \"disabled\", threads: \"disabled\" };\n  if (!hasThreads)  return { scan: \"done\", sessions: \"done\", threads: \"next\" };\n  return { scan: \"done\", sessions: \"done\", threads: \"done\" };\n}\n<\/code><\/pre>\n<p>\u06cc\u06c1 \u0641\u0646\u06a9\u0634\u0646 \u06c1\u0631 \u0642\u062f\u0645 \u067e\u0631 \u0688\u06cc\u0679\u0627 \u06a9\u06cc \u0645\u0648\u062c\u0648\u062f\u06af\u06cc \u06cc\u0627 \u063a\u06cc\u0631 \u0645\u0648\u062c\u0648\u062f\u06af\u06cc \u06a9\u0648 \u067e\u0691\u06be\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u062a\u06cc\u0646\u0648\u06ba \u0628\u0679\u0646\u0648\u06ba \u06a9\u06cc \u062d\u06cc\u062b\u06cc\u062a \u0648\u0627\u067e\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633\u06a9\u06cc\u0646 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2\u060c \u0635\u0631\u0641 \u0627\u0633\u06a9\u06cc\u0646\u0646\u06af \u06a9\u0648 \u0641\u0639\u0627\u0644 \u0627\u0648\u0631 \u0688\u0633\u067e\u0644\u06d2 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>next<\/code>\u0628\u0627\u0642\u06cc \u062f\u0648 \u0645\u0639\u0630\u0648\u0631 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u06af\u0631 \u06a9\u0648\u0626\u06cc \u0648\u0627\u0642\u0639\u06c1 \u0645\u0648\u062c\u0648\u062f \u06c1\u06d2 \u0644\u06cc\u06a9\u0646 \u0633\u06cc\u0634\u0646 \u0645\u0648\u062c\u0648\u062f \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 \u062a\u0648 \u0627\u0633\u06a9\u06cc\u0646 \u0627\u0633 \u067e\u0631 \u0628\u062f\u0644 \u062c\u0627\u062a\u0627 \u06c1\u06d2: <code>done<\/code> \u0627\u0648\u0631 \u0633\u06cc\u0634\u0646 \u06c1\u06d2\u06d4 <code>next<\/code>. \u0627\u06af\u0631 \u0633\u06cc\u0634\u0646 \u0645\u0648\u062c\u0648\u062f \u06c1\u06d2 \u0644\u06cc\u06a9\u0646 \u062a\u06be\u0631\u06cc\u0688 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 \u062a\u0648 \u062a\u06be\u0631\u06cc\u0688 \u0628\u0646 \u062c\u0627\u062a\u0627 \u06c1\u06d2: <code>next<\/code>. \u062c\u0628 \u062a\u06cc\u0646\u0648\u06ba \u0645\u0631\u0627\u062d\u0644 \u0622\u0624\u0679 \u067e\u0679 \u067e\u06cc\u062f\u0627 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0633\u0628 \u06a9\u0686\u06be \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>done<\/code>\u062a\u0645\u0627\u0645 \u0627\u0642\u062f\u0627\u0645\u0627\u062a \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u06cc\u06d2 \u062c\u0627 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0644\u06cc\u06a9\u0646 \u06a9\u0633\u06cc \u06a9\u0648 \u0628\u06be\u06cc \u062a\u0648\u062c\u06c1 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u062c\u06be\u0631\u0646 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u062a\u0633\u0644\u0633\u0644 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062d\u0631\u06a9\u062a \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u060c \u0628\u0627\u0644\u06a9\u0644 \u0627\u06cc\u06a9 \u0631\u0648\u0634\u0646\u06cc \u06a9\u0648 \u0622\u0646 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4 <code>next<\/code> \u062e\u06cc\u0627\u0644 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u062a\u06cc\u0646 \u0628\u0679\u0646\u0648\u06ba \u06a9\u06cc \u0627\u06cc\u06a9 \u0642\u0637\u0627\u0631 \u06a9\u0648 \u06c1\u062f\u0627\u06cc\u062a \u0634\u062f\u06c1 \u062a\u0631\u062a\u06cc\u0628 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644 \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2\u06d4<\/p>\n<p>\u067e\u06c1\u0644\u0627 \u067e\u06cc\u0631\u0627\u0645\u06cc\u0679\u0631\u060c <code>hasScanned<\/code>\u06cc\u06c1 \u0627\u06cc\u06a9 \u0633\u0627\u062f\u06c1 \u0634\u0645\u0627\u0631 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0644\u0637\u06cc\u0641 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0648\u06c1 \u062c\u06af\u06c1 \u06c1\u06d2 \u062c\u06c1\u0627\u06ba \u067e\u06c1\u0644\u06d2 \u06a9\u06cc\u067e\u0686\u0631 \u0633\u06cc\u06a9\u0634\u0646 \u06a9\u06d2 \u067e\u0644\u0645\u0628\u0646\u06af \u0628\u0679\u0633 \u0627\u062f\u0627 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0622\u067e \u0635\u0631\u0641 \"\u06a9\u06cc\u0627 \u06a9\u0648\u0626\u06cc \u0648\u0627\u0642\u0639\u0627\u062a \u06c1\u06cc\u06ba\" \u06a9\u0648 \u0686\u06cc\u06a9 \u0646\u06c1\u06cc\u06ba \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0644\u0627\u0626\u06cc\u0648 \u06a9\u06cc\u067e\u0686\u0631 \u0628\u06be\u0631\u0646\u0627 \u0634\u0631\u0648\u0639 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4 <code>raw_events<\/code> \u062c\u0633 \u0644\u0645\u062d\u06d2 \u0627\u06cc\u06a9\u0633\u0679\u06cc\u0646\u0634\u0646 \u0627\u0646\u0633\u0679\u0627\u0644 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 \u0648\u06c1\u0627\u06ba \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u0627 <em>\u06c1\u0645\u06cc\u0634\u06c1<\/em> \u06cc\u06c1 \u0627\u06cc\u06a9 \u0648\u0627\u0642\u0639\u06c1 \u0628\u0646 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0622\u0646 \u0628\u0648\u0631\u0688\u0646\u06af \u0635\u0627\u0631\u0641 \u06a9\u06d2 \u0627\u0633\u06a9\u06cc\u0646 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0627\u0633\u06a9\u06cc\u0646\u0646\u06af \u06a9\u06d2 \u0645\u0631\u062d\u0644\u06d2 \u06a9\u0648 \u0686\u06be\u0648\u0691 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0679\u06be\u06cc\u06a9 \u06c1\u06d2 <code>source<\/code> \u0641\u06cc \u0641\u06cc\u0644\u0688 <code>RawEvent<\/code>\u067e\u0631 \u0633\u06cc\u0679 \u06a9\u0631\u06cc\u06ba <code>\"backfill\"<\/code> \u06cc\u0627 <code>\"live\"<\/code> \u062c\u0628 \u0622\u067e \u0627\u06cc\u06a9 \u06a9\u06cc\u067e\u0686\u0631 \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>hasScanned<\/code> \u062e\u0627\u0635 \u0637\u0648\u0631 \u067e\u0631\u060c \u06cc\u06c1 \u0627\u06cc\u06a9 \u0648\u0642\u0641 \u0634\u062f\u06c1 \u0627\u0633\u062a\u0641\u0633\u0627\u0631 \u0633\u06d2 \u0622\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u0628\u06cc\u06a9 \u0641\u0644 \u0627\u06cc\u0648\u0646\u0679\u0633 \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-typescript\">export async function hasBackfillEvents(): Promise<boolean> {\n  const db = await getDB();\n  let cursor = await db.transaction(\"raw_events\", \"readonly\").store.openCursor();\n  while (cursor) {\n    if (cursor.value.source === \"backfill\") return true;\n    cursor = await cursor.continue();\n  }\n  return false;\n}\n<\/boolean><\/code><\/pre>\n<p>\u06cc\u06c1 \u0686\u0644\u062a\u0627 \u06c1\u06d2 <code>raw_events<\/code> \u062c\u0628 \u062a\u06a9 \u06a9\u0648\u0626\u06cc \u0627\u06cc\u06a9 \u0648\u0627\u0642\u0639\u06c1 \u0646\u06c1 \u0645\u0644\u06d2 <code>source === \"backfill\"<\/code>\u0648\u06c1 \u0644\u0645\u062d\u06c1 \u062c\u0644\u062f \u0648\u0627\u067e\u0633 \u0622\u062a\u0627 \u06c1\u06d2\u06d4 \u06c1\u0645 \u0635\u0631\u0641 \u0644\u0627\u0626\u06cc\u0648 \u0627\u06cc\u0648\u0646\u0679\u0633 \u06a9\u06cc\u067e\u0686\u0631 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u06a9\u0628\u06be\u06cc \u0645\u0637\u0645\u0626\u0646 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u06d2\u060c \u0627\u0633 \u0644\u06cc\u06d2 \"\u0645\u06cc\u0631\u06cc \u0633\u0631\u06af\u0632\u0634\u062a \u062a\u0644\u0627\u0634 \u06a9\u0631\u06cc\u06ba\" \u06a9\u0648 \u067e\u06c1\u0644\u06d2 \u0642\u062f\u0645 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0622\u0646 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u062c\u0628 \u062a\u06a9 \u06a9\u06c1 \u0635\u0627\u0631\u0641 \u062d\u0642\u06cc\u0642\u062a \u0645\u06cc\u06ba \u0628\u06cc\u06a9 \u0641\u0644 \u0646\u06c1\u06cc\u06ba \u0686\u0644\u0627\u062a\u0627\u06d4 \u06cc\u06c1 \u0622\u0646 \u0628\u0648\u0631\u0688\u0646\u06af \u06a9\u0627 \u0635\u062d\u06cc\u062d \u0631\u0648\u06cc\u06c1 \u06c1\u06d2\u06d4 \u06c1\u0631 \u0648\u0627\u0642\u0639\u06c1 \u06a9\u06d2 \u0645\u0627\u062e\u0630 \u06a9\u0648 \u0679\u06cc\u06af \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0628\u0638\u0627\u06c1\u0631 \u0645\u0639\u0645\u0648\u0644\u06cc \u0641\u06cc\u0635\u0644\u06c1\u060c \u062c\u0648 \u06a9\u0626\u06cc \u062d\u0635\u06d2 \u067e\u06c1\u0644\u06d2 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u062a\u06be\u0627\u060c \u0627\u0628 \u0627\u0633 \u0641\u0631\u0642 \u06a9\u0648 \u0645\u0645\u06a9\u0646 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-driving-the-welcome-screen-from-the-same-machine\">\u0627\u0633\u06cc \u0633\u0633\u0679\u0645 \u067e\u0631 \u0627\u0633\u0679\u0627\u0631\u0679 \u0627\u067e \u0627\u0633\u06a9\u0631\u06cc\u0646 \u0686\u0644\u0627\u0646\u0627<\/h3>\n<p>\u067e\u06c1\u0644\u06cc \u0628\u0627\u0631 \u063a\u06cc\u0631 \u062a\u06be\u0631\u06cc\u0688 \u0648\u0627\u0644\u06d2 \u0635\u0627\u0631\u0641\u06cc\u0646 \u06a9\u0648 \u062e\u0627\u0644\u06cc \u0627\u0631\u0627\u062f\u06d2 \u06a9\u06d2 \u0646\u0642\u0634\u06d2 \u06a9\u06cc \u0628\u062c\u0627\u0626\u06d2 \u0633\u06cc\u0646\u0679\u0631\u0688 \u0633\u067e\u0644\u06cc\u0634 \u0627\u0633\u06a9\u0631\u06cc\u0646 \u0646\u0638\u0631 \u0622\u0626\u06d2 \u06af\u06cc\u06d4 \u062a\u0627\u06c1\u0645\u060c \u0627\u0646 \u0627\u0633\u06a9\u0631\u06cc\u0646\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0644\u06af \u0645\u0646\u0637\u0642 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2\u060c \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u0627\u0633\u06a9\u0631\u06cc\u0646\u0648\u06ba \u06a9\u0648 \u0627\u0633\u06cc \u0645\u0646\u0637\u0642 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0686\u0644\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>pipelineStates<\/code> \u062d\u0633\u0627\u0628 \u0622\u067e \u062c\u0633 \u0645\u0631\u062d\u0644\u06d2 \u0645\u06cc\u06ba \u0628\u06be\u06cc \u06c1\u0648\u06ba\u06d4 <code>next<\/code> \u0627\u06cc\u06a9 \u0648\u0627\u062d\u062f \u06a9\u0627\u0644 \u0679\u0648 \u0627\u06cc\u06a9\u0634\u0646 \u06a9\u0627 \u0641\u06cc\u0635\u0644\u06c1 \u06a9\u0631\u06cc\u06ba \u062c\u0648 \u0648\u06cc\u0644\u06a9\u0645 \u0627\u0633\u06a9\u0631\u06cc\u0646 \u067e\u0631 \u0638\u0627\u06c1\u0631 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-typescript\">let welcomeStep: 1 | 2 | 3 = 1;\nlet welcomeCtaLabel = \"Scan my history\";\nlet welcomeCtaClick = handleScan;\nif (scanState === \"next\") {\n  welcomeStep = 1;\n  welcomeCtaLabel = scanning ? \"Scanning\u2026\" : \"Scan my history\";\n  welcomeCtaClick = handleScan;\n} else if (sessionsState === \"next\") {\n  welcomeStep = 2;\n  welcomeCtaLabel = buildingSessions ? \"Building\u2026\" : \"Build sessions\";\n  welcomeCtaClick = handleBuildSessions;\n} else if (threadsState === \"next\") {\n  welcomeStep = 3;\n  welcomeCtaLabel = buildingThreads ? \"Building\u2026\" : \"Build your intent map\";\n  welcomeCtaClick = handleBuildThreads;\n}\n<\/code><\/pre>\n<p>\u0627\u0633\u0679\u0627\u0631\u0679 \u0627\u0633\u06a9\u0631\u06cc\u0646 \u067e\u0631 \u0627\u06cc\u06a9 \u0648\u0627\u062d\u062f \u0628\u0679\u0646 \u06c1\u0645\u06cc\u0634\u06c1 \u0631\u06cc\u0644\u0648\u06ba \u067e\u0631 \u0627\u06cc\u06a9 \u0628\u0679\u0646 \u06a9\u0627 \u0639\u06a9\u0633 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 <code>next<\/code> \u06cc\u06c1 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0635\u0627\u0631\u0641\u06cc\u0646 \u06a9\u0648 \u0627\u06cc\u06a9 \u0646\u0645\u0627\u06cc\u0627\u06ba \u0628\u0679\u0646 \u067e\u0631 \u062a\u06cc\u0646 \u06a9\u0644\u06a9\u0633 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0633\u06a9\u06cc\u0646\u0646\u06af\u060c \u0633\u06cc\u0634\u0646 \u0628\u0646\u0627\u0646\u06d2 \u0627\u0648\u0631 \u062a\u06be\u0631\u06cc\u0688\u0632 \u0628\u0646\u0627\u0646\u06d2 \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 \u062c\u0633 \u0644\u0645\u062d\u06d2 \u06a9\u0648\u0626\u06cc \u062f\u06be\u0627\u06af\u06c1 \u0645\u0648\u062c\u0648\u062f \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u060c \u0633\u067e\u0644\u06cc\u0634 \u0627\u0633\u06a9\u0631\u06cc\u0646 \u06a9\u0648 \u0627\u0631\u0627\u062f\u06d2 \u06a9\u06d2 \u0646\u0642\u0634\u06d2 \u0633\u06d2 \u0628\u062f\u0644 \u062f\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0631\u06cc\u0644 \u0627\u0648\u0631 \u0648\u06cc\u0644\u06a9\u0645 \u0627\u0633\u06a9\u0631\u06cc\u0646 \u06a9\u0628\u06be\u06cc \u0628\u06be\u06cc \u0627\u0633 \u0628\u0627\u062a \u067e\u0631 \u0645\u062a\u0641\u0642 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u0622\u06af\u06d2 \u06a9\u06cc\u0627 \u06a9\u0631\u0646\u0627 \u06c1\u06d2\u06d4 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u062f\u0648\u0646\u0648\u06ba \u0627\u06cc\u06a9 \u06c1\u06cc \u0630\u0631\u06cc\u0639\u06c1 \u0633\u06d2 \u067e\u0691\u06be\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-wiring-the-handlers\">\u06c1\u06cc\u0646\u0688\u0644\u0631 \u0648\u0627\u0626\u0631\u0646\u06af<\/h3>\n<p>\u0633\u0646\u0628\u06be\u0627\u0644\u0646\u06d2 \u0648\u0627\u0644\u0627 \u062e\u0648\u062f \u0627\u06cc\u06a9 \u0645\u0646\u0638\u0631 \u06c1\u06d2\u06d4 \u06c1\u0631 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u06d2 \u0645\u0631\u062d\u0644\u06d2 \u06a9\u0648 \u0627\u0646\u062c\u0627\u0645 \u062f\u06cc\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u067e\u06be\u0631 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0645\u06cc\u06ba \u0627\u062c\u0632\u0627\u0621 \u06a9\u06d2 \u0645\u0646\u0638\u0631 \u06a9\u0648 \u062a\u0627\u0632\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06af\u0631\u0627\u0624\u0646\u0688\u0646\u06af \u0627\u0648\u0631 \u0644\u06cc\u0628\u0644\u0646\u06af \u06a9\u0648 \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u0686\u0644\u0627\u0646\u0627 \u0642\u0627\u0628\u0644 \u063a\u0648\u0631 \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u06cc\u06c1 \u067e\u0686\u06be\u0644\u06d2 \u062f\u0648 \u062d\u0635\u0648\u06ba \u0645\u06cc\u06ba \u0628\u06cc\u0627\u0646 \u06a9\u0631\u062f\u06c1 \u0688\u06cc\u06a9\u067e\u0644\u0646\u06af \u06a9\u0648 \u0644\u0627\u06af\u0648 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-typescript\">async function handleEnrichAndLabel() {\n  setLabelError(null);\n  setEnrichError(null);\n\n  if (contextKey.trim() && contextKeySaved) {\n    setEnriching(true);\n    try {\n      const allDomains = [...new Set(\n        threads.flatMap(\n      )];\n      const result = await enrichDomains(contextKey.trim(), allDomains);\n      if (result.error) setEnrichError(`context.dev: ${result.error}`);\n      if (result.enriched > 0) {\n        const all = await getAllBrands();\n        setBrands(new Map(all.map((b) => [b.domain, b])));\n      }\n    } catch (err) {\n      setEnrichError(`context.dev: ${err instanceof Error ? err.message : \"unknown error\"}`);\n    } finally {\n      setEnriching(false);\n    }\n  }\n\n  setLabeling(true);\n  try {\n    await labelThreads(apiKey.trim());\n    setThreads(await getAllThreads());\n  } catch (err) {\n    setLabelError(err instanceof Error ? err.message : \"Labeling failed.\");\n  } finally {\n    setLabeling(false);\n  }\n}\n<\/code><\/pre>\n<p>\u0633\u062e\u062a\u06cc \u0635\u0631\u0641 \u0627\u0633 \u0635\u0648\u0631\u062a \u0645\u06cc\u06ba \u0686\u0644\u062a\u06cc \u06c1\u06d2 \u062c\u0628 context.dev \u06a9\u0644\u06cc\u062f \u0645\u0648\u062c\u0648\u062f \u06c1\u0648\u060c \u0627\u0648\u0631 \u0627\u0633\u06d2 \u0644\u067e\u06cc\u0679 \u062f\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u062a\u0627\u06a9\u06c1 \u062e\u0631\u0627\u0628\u06cc\u0627\u06ba (\u062c\u06cc\u0633\u06d2 \u0646\u06cc\u0679 \u0648\u0631\u06a9 \u06a9\u06cc \u063a\u0644\u0637\u06cc\u0627\u06ba\u060c \u063a\u0644\u0637 \u06a9\u0644\u06cc\u062f\u06cc\u06ba\u060c \u06cc\u0627 \u0634\u0631\u062d \u06a9\u06cc \u062d\u062f\u06cc\u06ba) \u0627\u06cc\u06a9 \u062e\u0631\u0627\u0628\u06cc \u06a9\u0627 \u067e\u06cc\u063a\u0627\u0645 \u0633\u06cc\u0679 \u06a9\u0631\u062a\u06cc \u06c1\u06cc\u06ba \u0644\u06cc\u06a9\u0646 \u0627\u0633 \u067e\u0631 \u0639\u0645\u0644 \u062f\u0631\u0622\u0645\u062f \u0646\u06c1\u06cc\u06ba \u0631\u0648\u06a9\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 \u0627\u0633 \u06a9\u06d2 \u0628\u0639\u062f \u0644\u06cc\u0628\u0644\u0646\u06af \u063a\u06cc\u0631 \u0645\u0634\u0631\u0648\u0637 \u0637\u0648\u0631 \u067e\u0631 \u06a9\u0645\u06a9 \u06a9\u06d2 \u0628\u0644\u0627\u06a9 \u0633\u06d2 \u0628\u0627\u06c1\u0631 \u0686\u0644\u062a\u06cc \u06c1\u06d2\u060c \u0644\u06c1\u0630\u0627 \u06cc\u06c1 \u0627\u0633 \u0628\u0627\u062a \u0633\u06d2 \u0642\u0637\u0639 \u0646\u0638\u0631 \u0622\u06af\u06d2 \u0628\u0691\u06be\u06d2 \u06af\u0627 \u06a9\u06c1 \u06a9\u0645\u06a9 \u06a9\u0627\u0645\u06cc\u0627\u0628 \u06c1\u0648\u0626\u06cc\u060c \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648\u0626\u06cc\u060c \u06cc\u0627 \u06a9\u0644\u06cc\u062f\u0648\u06ba \u06a9\u06cc \u06a9\u0645\u06cc \u06a9\u06cc \u0648\u062c\u06c1 \u0633\u06d2 \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u0686\u06be\u0648\u0691 \u062f\u06cc \u06af\u0626\u06cc\u06d4<\/p>\n<p>\u0633\u0627\u062e\u062a \u06a9\u0648 \u062e\u0627\u0635 \u0637\u0648\u0631 \u067e\u0631 \u0632\u0645\u06cc\u0646\u06cc \u062d\u0635\u06d2 \u0633\u06d2 \u0627\u0644\u06af \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0688\u06cc\u0632\u0627\u0626\u0646 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4 \u06af\u0631\u0627\u0624\u0646\u0688\u0646\u06af \u0644\u06cc\u0628\u0644\u0646\u06af \u06a9\u0648 \u0628\u06c1\u062a\u0631 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2 \u062c\u0628 \u06cc\u06c1 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u062c\u0628 \u06cc\u06c1 \u06a9\u0627\u0645 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u0628\u0644\u0646\u06af \u06a9\u0644\u06cc\u062f\u06cc \u0627\u0644\u0641\u0627\u0638 \u0627\u0648\u0631 \u0688\u0648\u0645\u06cc\u0646 \u06a9\u06d2 \u0633\u06cc\u0627\u0642 \u0648 \u0633\u0628\u0627\u0642 \u06a9\u0648 \u062e\u0648\u0628\u0635\u0648\u0631\u062a\u06cc \u0633\u06d2 \u06a9\u0645 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0636\u0627\u0641\u06c1 \u06a9\u06cc \u063a\u0644\u0637\u06cc\u0627\u06ba \u0633\u0631\u062e \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0639\u0646\u0628\u0631 \u0645\u06cc\u06ba \u062f\u06a9\u06be\u0627\u0626\u06cc \u062f\u06cc\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 \u0627\u0633 \u06a9\u06cc \u0648\u062c\u06c1 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u06cc\u06c1 \u0627\u06cc\u06a9 \u0627\u0646\u062a\u0628\u0627\u06c1 \u06c1\u06d2 (\u0644\u06cc\u0628\u0644 \u0627\u0628 \u0628\u06be\u06cc \u06c1\u0648\u062a\u0627 \u06c1\u06d2) \u0646\u06c1 \u06a9\u06c1 \u0628\u0644\u0627\u06a9 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0646\u0627\u06a9\u0627\u0645\u06cc\u06d4 \u06cc\u06c1 \u0686\u06be\u0648\u0679\u06d2 UI \u0633\u0631\u0627\u06af \u06c1\u06cc\u06ba \u062c\u0648 \u063a\u0644\u0637 \u06c1\u0648\u0646\u06d2 \u06a9\u06cc \u0627\u0635\u0644 \u0634\u062f\u062a \u0633\u06d2 \u0645\u06cc\u0644 \u06a9\u06be\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-the-resume-button\">\u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u0628\u0679\u0646<\/h3>\n<p>\u0627\u06cc\u06a9 \u062a\u0639\u0627\u0645\u0644 \u0627\u0631\u0627\u062f\u06d2 \u06a9\u06d2 \u0646\u0642\u0634\u06d2 \u06a9\u0648 \u0631\u06cc\u0626\u0644 \u0679\u0627\u0626\u0645 \u0646\u06cc\u0648\u06cc\u06af\u06cc\u0634\u0646 \u0633\u06d2 \u062f\u0648\u0628\u0627\u0631\u06c1 \u062c\u0648\u0691\u062a\u0627 \u06c1\u06d2\u06d4 \u06c1\u0631 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u0627\u0631\u0688 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0631\u06cc\u0632\u06cc\u0648\u0645\u06d2 \u0628\u0679\u0646 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u0627\u0633 \u0635\u0641\u062d\u06c1 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u06be\u0648\u0644\u062a\u0627 \u06c1\u06d2 \u062c\u0633 \u067e\u0631 \u0622\u067e \u0641\u06cc \u0627\u0644\u062d\u0627\u0644 \u062a\u06be\u06d2\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u062a\u06be\u0631\u06cc\u0688 \u067e\u0631 \u0622\u067e\u0631\u06cc\u0634\u0646\u0632 \u06c1\u0633\u0679\u0631\u06cc \u0645\u06cc\u06ba \u062a\u0644\u0627\u0634 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0627\u06cc\u06a9 \u06a9\u0644\u06a9 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u06a9\u06cc\u06d2 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-typescript\">const RESUME_SKIP_DOMAINS = new Set([\n  \"google.com\", \"youtube.com\", \"bing.com\", \"duckduckgo.com\",\n  \"gmail.com\", \"mail.google.com\",\n]);\n\nfunction resumeThread(thread: IntentThread): void {\n  const seen = new Set<string>();\n  const urls: string[] = [];\n\n  const sorted = thread.sessions\n    .flatMap((s) => s.events)\n    .sort((a, b) => b.visitedAt - a.visitedAt);\n\n  for (const ev of sorted) {\n    if (RESUME_SKIP_DOMAINS.has(ev.domain)) continue;\n    if (seen.has(ev.url)) continue;\n    seen.add(ev.url);\n    urls.push(ev.url);\n    if (urls.length >= 3) break;\n  }\n\n  urls.forEach((url, i) => {\n    chrome.tabs.create({ url, active: i === 0 });\n  });\n}\n<\/string><\/code><\/pre>\n<p>\u062a\u0627\u0632\u06c1 \u062a\u0631\u06cc\u0646 \u0633\u06d2 \u0634\u0631\u0648\u0639 \u06c1\u0648\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u062f\u06be\u0627\u06af\u06d2 \u0645\u06cc\u06ba \u0648\u0627\u0642\u0639\u0627\u062a \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06a9\u0631\u06cc\u06ba\u060c \u0633\u0631\u0686 \u0627\u0646\u062c\u0646\u0648\u06ba \u0627\u0648\u0631 \u0648\u06cc\u0628 \u0645\u06cc\u0644 \u06a9\u0648 \u0686\u06be\u0648\u0691 \u062f\u06cc\u062a\u0627 \u06c1\u06d2 (\u0627\u0646 \u0645\u0646\u0632\u0644\u0648\u06ba \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u062c\u06c1\u0627\u06ba \u0622\u067e \u0648\u0627\u067e\u0633 \u062c\u0627\u0646\u0627 \u0686\u0627\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba)\u060c \u06cc\u0648 \u0622\u0631 \u0627\u06cc\u0644 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0688\u067e\u0644\u06cc\u06a9\u06cc\u0679\u0633 \u06a9\u0648 \u06c1\u0679\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u062a\u06cc\u0646 \u062d\u0627\u0644\u06cc\u06c1 \u0628\u0627\u0645\u0639\u0646\u06cc \u0635\u0641\u062d\u0627\u062a \u06a9\u0648 \u06a9\u06be\u0648\u0644\u062a\u0627 \u06c1\u06d2\u06d4 \u067e\u06c1\u0644\u0627 \u0627\u06cc\u06a9\u0679\u06cc\u0648 \u0679\u06cc\u0628 \u06c1\u06d2 \u0627\u0648\u0631 \u0628\u0627\u0642\u06cc \u0628\u06cc\u06a9 \u06af\u0631\u0627\u0624\u0646\u0688 \u0645\u06cc\u06ba \u06c1\u06cc\u06ba\u06d4 \u06cc\u06c1 \u0627\u06cc\u06a9 \u0686\u06be\u0648\u0679\u06cc \u0633\u06cc \u062e\u0635\u0648\u0635\u06cc\u062a \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u0627\u0633 \u0633\u06d2 \u06cc\u06c1 \u0645\u062d\u0633\u0648\u0633 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u062f\u06be\u0627\u06af\u06c1 \u06a9\u06c1\u0627\u06ba \u0631\u06c1\u0627 \u06c1\u06d2 \u0627\u0633 \u06a9\u06d2 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0627\u06cc\u06a9 \u0627\u06cc\u0633\u06cc \u062c\u06af\u06c1 \u062c\u06c1\u0627\u06ba \u0622\u067e \u0648\u0627\u067e\u0633 \u062c\u0627 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-checkpoint\">\u0686\u0648\u06a9\u06cc<\/h3>\n<p>\u0688\u06cc\u0634 \u0628\u0648\u0631\u0688\u0632 \u06a9\u06d2 \u0645\u0646\u0633\u0644\u06a9 \u06c1\u0648\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f\u060c \u067e\u0648\u0631\u06cc \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0622\u062e\u0631 \u06a9\u0627\u0631 \u0627\u0646\u0679\u0631\u0641\u06cc\u0633 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0627\u06cc\u0646\u0688 \u0679\u0648 \u0627\u06cc\u0646\u0688 \u062a\u06a9 \u062f\u0633\u062a\u06cc\u0627\u0628 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 \u062c\u0628 \u0622\u067e \u0627\u06cc\u06a9\u0633\u0679\u06cc\u0646\u0634\u0646 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0644\u0648\u0688 \u06a9\u0631\u06cc\u06ba \u06af\u06d2 \u0627\u0648\u0631 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u06a9\u06be\u0648\u0644\u06cc\u06ba \u06af\u06d2\u060c \u062a\u0648 \u0622\u067e \u06a9\u0648 \u0627\u06cc\u06a9 \u0648\u06cc\u0644\u06a9\u0645 \u0627\u0633\u06a9\u0631\u06cc\u0646 \u0646\u0638\u0631 \u0622\u0626\u06d2 \u06af\u06cc \u062c\u0648 \u0622\u067e \u0633\u06d2 \u0627\u0633\u06a9\u06cc\u0646 \u06a9\u0631\u0646\u06d2 \u06a9\u0648 \u06a9\u06c1\u06d2 \u06af\u06cc\u06d4<\/p>\n<p>\u0627\u0633\u06a9\u06cc\u0646 \u067e\u0631 \u06a9\u0644\u06a9 \u06a9\u0631\u06cc\u06ba\u060c \u0633\u06cc\u0634\u0646 \u0628\u0646\u0627\u0626\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u0627\u0631\u0627\u062f\u06d2 \u06a9\u0627 \u0646\u0642\u0634\u06c1 \u0628\u0646\u0627\u0626\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0622\u067e \u06a9\u0648 \u0633\u0679\u06cc\u0679\u0633 \u06a9\u06d2 \u0644\u062d\u0627\u0638 \u0633\u06d2 \u062f\u06be\u0627\u06af\u0648\u06ba \u06a9\u0627 \u06af\u0631\u0648\u067e \u0646\u0638\u0631 \u0622\u0626\u06d2 \u06af\u0627\u06d4 \u0627\u06cc\u0646\u062a\u06be\u0631\u0648\u067e\u06a9 \u06a9\u0644\u06cc\u062f (\u0627\u062e\u062a\u06cc\u0627\u0631\u06cc \u0637\u0648\u0631 \u067e\u0631 context.dev \u06a9\u0644\u06cc\u062f) \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u0639\u0646\u0648\u0627\u0646 \u0627\u0648\u0631 \u0627\u06af\u0644\u06d2 \u0627\u0642\u062f\u0627\u0645\u0627\u062a \u0648\u0627\u0636\u062d \u06c1\u0648\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \"\u0644\u06cc\u0628\u0644 \u0627\u0648\u0631 \u0627\u0636\u0627\u0641\u06c1 \u06a9\u0631\u06cc\u06ba\" \u067e\u0631 \u06a9\u0644\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4 \u067e\u0648\u0631\u0627 \u0644\u0648\u067e \u062c\u0648 \u06c1\u0645 \u0646\u06d2 \u067e\u0686\u06be\u0644\u06d2 \u062a\u0645\u0627\u0645 \u062d\u0635\u0648\u06ba \u0645\u06cc\u06ba \u0628\u0646\u0627\u06cc\u0627 \u062a\u06be\u0627 \u0627\u0628 \u0627\u06cc\u06a9 \u06c1\u06cc \u0627\u0633\u06a9\u0631\u06cc\u0646 \u067e\u0631 \u0686\u0644\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0628\u0633 \u062c\u0648 \u0631\u06c1 \u06af\u06cc\u0627 \u06c1\u06d2 \u0648\u06c1 \u062f\u0627\u0626\u06cc\u06ba \u0637\u0631\u0641 \u0688\u0627\u0626\u06cc\u0644\u0627\u06af \u067e\u0631\u062a \u06c1\u06d2\u06d4 \u0627\u06cc\u06a9 AI \u0627\u0633\u0633\u0679\u0646\u0679 \u062c\u0648 \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u062a\u0645\u0627\u0645 \u062a\u06be\u0631\u06cc\u0688\u0632 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u0627\u0633\u062a\u062f\u0644\u0627\u0644 \u06a9\u0631 \u0633\u06a9\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0633\u0648\u0627\u0644\u0627\u062a \u06a9\u0627 \u062c\u0648\u0627\u0628 \u062f\u06d2 \u0633\u06a9\u062a\u0627 \u06c1\u06d2 \u062c\u06cc\u0633\u06d2 \"\u0645\u062c\u06be\u06d2 \u0627\u0633 \u06c1\u0641\u062a\u06d2 \u06a9\u06cc\u0627 \u0628\u0646\u062f \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u061f\" \u06c1\u0645 \u0627\u0633\u06d2 \u0627\u06af\u0644\u06d2 \u062d\u0635\u06d2 \u0645\u06cc\u06ba \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h2 id=\"heading-how-to-build-the-ai-assistant\">\u0627\u06d2 \u0622\u0626\u06cc \u0627\u0633\u0633\u0679\u0646\u0679 \u06a9\u06cc\u0633\u06d2 \u0628\u0646\u0627\u06cc\u0627 \u062c\u0627\u0626\u06d2\u06d4<\/h2>\n<p>\u0644\u06cc\u0628\u0644\u0646\u06af \u06a9\u0627 \u0645\u0631\u062d\u0644\u06c1 \u06a9\u0644\u0627\u0688 \u0633\u06d2 \u0627\u06cc\u06a9 \u0648\u0642\u062a \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u0646\u06d2 \u06a9\u0648 \u06a9\u06c1\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633\u0633\u0679\u0646\u0679 \u06a9\u0686\u06be \u0627\u0648\u0631 \u0645\u0634\u06a9\u0644 \u0633\u06d2 \u067e\u0648\u0686\u06be\u062a\u0627 \u06c1\u06d2\u06d4 \u062a\u0645\u0627\u0645 \u062a\u06be\u0631\u06cc\u0688\u0632 \u06a9\u0648 \u0627\u06a9\u0679\u06be\u0627 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u06a9\u06be\u0644\u06d2 \u0633\u0648\u0627\u0644\u0627\u062a \u06a9\u06d2 \u062c\u0648\u0627\u0628 \u062f\u06cc\u06ba \u062c\u06cc\u0633\u06d2 \u06a9\u06c1 \u0627\u0633 \u06c1\u0641\u062a\u06d2 \u06a9\u0648 \u06a9\u06cc\u0627 \u062e\u062a\u0645 \u06a9\u0631\u0646\u0627 \u06c1\u06d2\u060c \u06a9\u0633 \u0686\u06cc\u0632 \u0645\u06cc\u06ba \u0633\u0628 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u062a\u0627\u062e\u06cc\u0631 \u06c1\u0648\u0626\u06cc \u06c1\u06d2\u060c \u06cc\u0627 \u06a9\u0633\u06cc \u062e\u0627\u0635 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u0648 \u06a9\u06cc\u0633\u06d2 \u0645\u06a9\u0645\u0644 \u06a9\u0631\u0646\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u06cc\u06c1 \u0627\u06cc\u06a9 \u0686\u06cc\u0679 \u0627\u0646\u0679\u0631\u0641\u06cc\u0633 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u06cc\u06c1 \u0645\u062d\u062f\u0648\u062f \u06c1\u06d2\u06d4 \u0686\u0648\u0646\u06a9\u06c1 \u06cc\u06c1 \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u0622\u067e \u06a9\u06d2 \u0627\u067e\u0646\u06d2 \u062a\u06be\u0631\u06cc\u0688 \u0688\u06cc\u0679\u0627 \u067e\u0631 \u0645\u0628\u0646\u06cc \u06c1\u06d2\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u062c\u0648\u0627\u0628\u0627\u062a \u0639\u0627\u0645 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631\u06cc \u0645\u0634\u0648\u0631\u06d2 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0627\u0635\u0644 \u062f\u06be\u0627\u06af\u0648\u06ba \u06a9\u0627 \u0646\u0627\u0645 \u0644\u06d2 \u06a9\u0631 \u062d\u0648\u0627\u0644\u06c1 \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u067e\u0648\u0631\u0627 \u0688\u06cc\u0632\u0627\u0626\u0646 \u0627\u06cc\u06a9 \u062e\u06cc\u0627\u0644 \u067e\u0631 \u0645\u0628\u0646\u06cc \u06c1\u06d2\u06d4 \u062f\u06cc \u06af\u0626\u06cc \u0635\u0648\u0631\u062a\u062d\u0627\u0644 \u06a9\u06d2 \u0645\u0637\u0627\u0628\u0642 \u0686\u06cc\u0679 \u0627\u0633\u0633\u0679\u0646\u0679 \u06a9\u06cc \u06a9\u0627\u0631\u06a9\u0631\u062f\u06af\u06cc \u0628\u06c1\u062a\u0631 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 \u0644\u06c1\u0630\u0627 \u06cc\u06c1\u0627\u06ba \u0632\u06cc\u0627\u062f\u06c1 \u062a\u0631 \u06a9\u0627\u0645 \u06c1\u0631 \u067e\u06cc\u063a\u0627\u0645 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0635\u062d\u06cc\u062d \u0628\u0646\u06cc\u0627\u062f\u06cc \u0633\u06cc\u0627\u0642 \u0648 \u0633\u0628\u0627\u0642 \u06a9\u06cc \u062a\u0639\u0645\u06cc\u0631 \u06a9\u0631 \u0631\u06c1\u0627 \u06c1\u06d2\u060c \u0646\u06c1 \u06a9\u06c1 \u062e\u0648\u062f \u0686\u06cc\u0679 \u0645\u06cc\u06a9\u0627\u0646\u0632\u0645\u06d4<\/p>\n<h3 id=\"heading-grounding-the-conversation\">\u0645\u06a9\u0627\u0644\u0645\u06d2 \u06a9\u06cc \u0628\u0646\u06cc\u0627\u062f \u0631\u06a9\u06be\u0646\u0627<\/h3>\n<p>\u06a9\u0644\u0627\u0688 \u06a9\u0648 \u067e\u06cc\u063a\u0627\u0645 \u067e\u06c1\u0646\u0686\u0627\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2\u060c \u0627\u0633\u0633\u0679\u0646\u0679 \u0627\u06cc\u06a9 \u0633\u0633\u0679\u0645 \u067e\u0631\u0627\u0645\u067e\u0679 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u0635\u0627\u0631\u0641 \u06a9\u06d2 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u0648 \u0628\u06cc\u0627\u0646 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u062f\u0648 \u0637\u0631\u06cc\u0642\u0648\u06ba \u0645\u06cc\u06ba \u0633\u06d2 \u0627\u06cc\u06a9 \u0645\u06cc\u06ba \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0633 \u0628\u0627\u062a \u067e\u0631 \u0645\u0646\u062d\u0635\u0631 \u06c1\u06d2 \u06a9\u06c1 \u0622\u06cc\u0627 \u0635\u0627\u0631\u0641 \u0646\u06d2 \u06a9\u0633\u06cc \u0645\u062e\u0635\u0648\u0635 \u062a\u06be\u0631\u06cc\u0688 \u067e\u0631 \u06a9\u0644\u06a9 \u06a9\u06cc\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u06af\u0631 \u06a9\u0648\u0626\u06cc \u062f\u06be\u0627\u06af\u06c1 \u0645\u0646\u062a\u062e\u0628 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u062a\u0645\u0627\u0645 \u062a\u06be\u0631\u06cc\u0688\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0645\u062e\u062a\u0635\u0631 \u0688\u0627\u0626\u062c\u0633\u0679 \u0628\u0646\u0627\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06cc\u06a9 \u06a9\u0648 \u0645\u0646\u062a\u062e\u0628 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u0622\u067e \u06a9\u0648 \u0627\u0633 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u0628\u06be\u0631\u067e\u0648\u0631 \u062a\u0641\u0635\u06cc\u0644\u0627\u062a \u0627\u0648\u0631 \u062f\u0648\u0633\u0631\u06d2 \u062a\u06be\u0631\u06cc\u0688\u0632 \u06a9\u06cc \u0627\u06cc\u06a9 \u0645\u062e\u062a\u0635\u0631 \u0641\u06c1\u0631\u0633\u062a \u0645\u0644\u06d2 \u06af\u06cc\u06d4<\/p>\n<pre><code class=\"language-typescript\">function buildGroundingContext(\n  threads: IntentThread[],\n  brands: Map<string brand=\"\">,\n  selectedThread: IntentThread | null,\n): string {\n  if (!selectedThread) {\n    const digest = threads\n      .map(\n        const domains = [...new Set(t.sessions.flatMap((s) => s.domains))].slice(0, 5).join(\", \");\n        return `- ({t.title} (){t.status}, ({t.type}): ){t.summary ?? \"no summary yet\"} | next: ({t.nextStep ?? \"none\"} | domains: ){domains || \"none\"}`;\n      })\n      .join(\"n\");\n\n    return `({SYSTEM_INSTRUCTION}nnHere is a digest of all the user's open intent threads:n){digest || \"(no threads yet)\"}`;\n  }\n\n  const keywords = [...new Set(selectedThread.sessions.flatMap((s) => s.keywords))].slice(0, 10).join(\", \");\n  const domains = [...new Set(selectedThread.sessions.flatMap((s) => s.domains))].slice(0, 5);\n\n  const domainLines = domains\n    .map((d) => {\n      const brand = brands.get(d);\n      if (brand?.description) return `- ({d}: ){brand.name} \u2014 ${brand.description}`;\n      return `- ${d}`;\n    })\n    .join(\"n\");\n\n  const sampleTitles = [...new Set(selectedThread.sessions.flatMap((s) => s.events.map((e) => e.title)))]\n    .slice(0, 20)\n    .map(\n    .join(\"n\");\n\n  const otherTitles = threads\n    .filter(\n    .map(\n    .join(\", \");\n\n  return `${SYSTEM_INSTRUCTION}\n\nThe user is focused on this thread:\nTitle: ${selectedThread.title}\nStatus: ${selectedThread.status}\nType: ${selectedThread.type}\nSummary: ${selectedThread.summary ?? \"none\"}\nNext step: ${selectedThread.nextStep ?? \"none\"}\nKeywords: ${keywords || \"none\"}\n\nDomains visited:\n${domainLines || \"(none)\"}\n\nRecent page titles:\n${sampleTitles || \"(none)\"}\n\nFor context, the user's other open threads are: ${otherTitles || \"none\"}.`;\n}\n<\/string><\/code><\/pre>\n<p>\u06cc\u06c1 \u062f\u0648\u0646\u0648\u06ba \u0637\u0631\u06cc\u0642\u06d2 \u0627\u0646 \u062f\u0648 \u0642\u0633\u0645 \u06a9\u06d2 \u0633\u0648\u0627\u0644\u0627\u062a \u06a9\u06d2 \u0645\u0637\u0627\u0628\u0642 \u06c1\u06cc\u06ba \u062c\u0648 \u0644\u0648\u06af \u067e\u0648\u0686\u06be\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0633\u0648\u0627\u0644\u0627\u062a \u062c\u06cc\u0633\u06d2 \"\u0645\u062c\u06be\u06d2 \u0627\u0633 \u06c1\u0641\u062a\u06d2 \u06a9\u06cc\u0627 \u062e\u062a\u0645 \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u061f\" \u0686\u0648\u0646\u06a9\u06c1 \u06cc\u06c1 \u067e\u0648\u0631\u06d2 \u0633\u06cc\u0679 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u06c1\u06d2\u060c \u0688\u0627\u0626\u062c\u0633\u0679 \u0645\u0648\u0688 \u06a9\u0644\u0627\u0688 \u06a9\u0648 \u06c1\u0631 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u0627 \u0627\u06cc\u06a9 \u0633\u0637\u0631\u06cc \u062e\u0644\u0627\u0635\u06c1 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 \u06c1\u0631 \u0686\u06cc\u0632 \u06a9\u0627 \u0645\u0648\u0627\u0632\u0646\u06c1 \u0627\u0648\u0631 \u062a\u0631\u062c\u06cc\u062d \u062f\u06cc\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06cc\u06c1 \u06a9\u0627\u0641\u06cc \u06af\u0646\u062c\u0627\u0626\u0634 \u06c1\u06d2\u06d4<\/p>\n<p>\u062f\u0648\u0633\u0631\u06cc \u0637\u0631\u0641\u060c \u0633\u0648\u0627\u0644\u0627\u062a \u062c\u06cc\u0633\u06d2 \"\u0645\u06cc\u06ba \u06cc\u06c1 \u06a9\u06cc\u0633\u06d2 \u06a9\u0631\u0648\u06ba\u061f\" \u0627\u06cc\u06a9 \u06c1\u06cc \u062f\u06be\u0627\u06af\u06d2 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u06c1\u06cc\u06ba\u060c \u0644\u06c1\u0630\u0627 \u0627\u0646\u062a\u06c1\u0627\u0626\u06cc \u0645\u0648\u0688 \u0645\u06cc\u06ba \u0622\u067e \u0686\u0648\u0691\u0627\u0626\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2 \u06af\u06c1\u0631\u0627\u0626\u06cc \u06a9\u06cc \u062a\u062c\u0627\u0631\u062a \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u0633 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u06d2 \u06a9\u0644\u06cc\u062f\u06cc \u0627\u0644\u0641\u0627\u0638\u060c \u0627\u067e\u0646\u06d2 \u0628\u0631\u0627\u0646\u0688 \u06a9\u06cc \u062a\u0641\u0635\u06cc\u0644 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u06cc\u06a9 \u0688\u0648\u0645\u06cc\u0646\u060c \u0627\u0648\u0631 20 \u0627\u0635\u0644 \u0635\u0641\u062d\u06c1 \u06a9\u06d2 \u0639\u0646\u0648\u0627\u0646\u0627\u062a \u06a9\u0648 \u067e\u0627\u0633 \u06a9\u0631\u06cc\u06ba\u060c \u062c\u0628\u06a9\u06c1 \u062f\u0648\u0633\u0631\u06d2 \u062a\u06be\u0631\u06cc\u0688\u0632 \u06a9\u06d2 \u0646\u0627\u0645 \u062c\u0627\u0631\u06cc \u0631\u06a9\u06be\u06cc\u06ba \u062a\u0627\u06a9\u06c1 Claude \u06a9\u0648 \u0645\u0639\u0644\u0648\u0645 \u06c1\u0648 \u06a9\u06c1 \u0622\u067e \u0627\u0648\u0631 \u06a9\u0633 \u0686\u06cc\u0632 \u067e\u0631 \u06a9\u0627\u0645 \u06a9\u0631 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0641\u0648\u06a9\u0633 \u0645\u0648\u0688 \u0648\u06c1 \u062c\u06af\u06c1 \u06c1\u06d2 \u062c\u06c1\u0627\u06ba \u0628\u0631\u0627\u0646\u0688 \u06af\u0631\u0627\u0624\u0646\u0688\u0646\u06af \u062f\u0648\u0628\u0627\u0631\u06c1 \u0627\u0628\u06be\u0631\u062a\u06cc \u06c1\u06d2\u06d4 \u0688\u0648\u0645\u06cc\u0646 \u06a9\u06cc \u0641\u06c1\u0631\u0633\u062a \u0645\u06cc\u06ba \u0648\u06c1\u06cc \u0628\u0631\u0627\u0646\u0688 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u0634\u0627\u0645\u0644 \u06c1\u06d2 \u062c\u0648 \u0627\u0641\u0632\u0648\u062f\u06af\u06cc \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646 \u06a9\u06be\u06cc\u0646\u0686\u0627 \u06af\u06cc\u0627 \u062a\u06be\u0627\u060c \u0644\u06c1\u0630\u0627 \u062c\u0628 \u0635\u0627\u0631\u0641 \u062f\u06be\u0627\u06af\u06d2 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u067e\u0648\u0686\u06be\u062a\u0627 \u06c1\u06d2\u060c \u06a9\u0644\u0627\u0688 <code>mastra.ai: Mastra \u2014 TypeScript framework for building AI agents<\/code> \u062e\u0627\u0644\u06cc \u0688\u0648\u0645\u06cc\u0646 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0648\u06c1\u06cc \u0628\u0646\u06cc\u0627\u062f\u06cc \u0627\u0635\u0648\u0644 \u06c1\u06d2 \u062c\u06cc\u0633\u0627 \u06a9\u06c1 \u0644\u06cc\u0628\u0644\u0646\u06af\u060c \u0627\u0628 \u0628\u0627\u062a \u0686\u06cc\u062a \u067e\u0631 \u0644\u0627\u06af\u0648 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0633\u0633\u0679\u0645 \u06a9\u0645\u0627\u0646\u0688\u0632 \u062c\u0648 \u062f\u0648\u0646\u0648\u06ba \u0645\u0648\u0688\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2 \u067e\u0631\u06cc\u0641\u06a9\u0633 \u0628\u062a\u0627\u062a\u06cc \u06c1\u06cc\u06ba \u0627\u0633 \u0688\u06cc\u0679\u0627 \u06a9\u06d2 \u0627\u0633\u0633\u0679\u0646\u0679 \u06a9\u0648 \u0627\u06cc\u0646\u06a9\u0631 \u06a9\u0631\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-typescript\">const SYSTEM_INSTRUCTION =\n  `You are the assistant inside \"openloops\", a browser extension that reconstructs ` +\n  `the user's browsing history into \"intent threads\" \u2014 decisions, research, or ` +\n  `plans they started and haven't closed. Help the user understand and act on ` +\n  `these open loops. Be concrete: reference the actual threads by name and ` +\n  `suggest real next actions. You are grounded only in the thread data provided ` +\n  `below \u2014 if the user asks about something not present in it, say so plainly ` +\n  `rather than guessing.`;\n<\/code><\/pre>\n<p>\u0622\u062e\u0631\u06cc \u06c1\u062f\u0627\u06cc\u062a \u0627\u06c1\u0645 \u06c1\u06d2\u06d4 \u0645\u0627\u0688\u0644 \u06a9\u0648 \u0627\u0633 \u0628\u0627\u062a \u06a9\u0648 \u062a\u0633\u0644\u06cc\u0645 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u06c1\u062f\u0627\u06cc\u062a \u06a9\u0631\u0646\u0627 \u06a9\u06c1 \u062c\u0628 \u06a9\u0648\u0626\u06cc \u0642\u0627\u0628\u0644 \u0641\u06c1\u0645 \u062c\u0648\u0627\u0628 \u067e\u06cc\u062f\u0627 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0688\u06cc\u0679\u0627 \u0645\u06cc\u06ba \u06a9\u0686\u06be \u063a\u0627\u0626\u0628 \u06c1\u0648 \u062a\u0648 \u0648\u06c1 \u0627\u0633\u0633\u0679\u0646\u0679 \u06a9\u0648 \u0628\u06be\u0631\u0648\u0633\u06c1 \u0645\u0646\u062f \u0631\u06a9\u06be\u062a\u0627 \u06c1\u06d2 \u062c\u0628 \u0635\u0627\u0631\u0641\u06cc\u0646 \u0688\u06cc\u0679\u0627 \u0645\u06cc\u06ba \u063a\u06cc\u0631 \u0645\u0648\u062c\u0648\u062f \u062a\u06be\u0631\u06cc\u0688\u0632 \u06cc\u0627 \u062a\u0641\u0635\u06cc\u0644\u0627\u062a \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u067e\u0648\u0686\u06be\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-sending-a-message\">\u067e\u06cc\u063a\u0627\u0645 \u0628\u06be\u06cc\u062c\u06cc\u06ba\u06d4<\/h3>\n<p>\u0628\u06be\u06cc\u062c\u0646\u06d2 \u06a9\u0627 \u0641\u0646\u06a9\u0634\u0646 \u06c1\u0631 \u067e\u06cc\u063a\u0627\u0645 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0646\u0626\u06d2 \u0632\u0645\u06cc\u0646\u06cc \u0633\u06cc\u0627\u0642 \u0648 \u0633\u0628\u0627\u0642 \u06a9\u06cc \u062a\u0634\u06a9\u06cc\u0644 \u0646\u0648 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633\u0633\u0679\u0646\u0679 \u06c1\u0645\u06cc\u0634\u06c1 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u06cc \u0645\u0648\u062c\u0648\u062f\u06c1 \u062d\u0627\u0644\u062a \u06a9\u06cc \u0639\u06a9\u0627\u0633\u06cc \u06a9\u0631\u062a\u0627 \u06c1\u06d2 (\u0628\u0634\u0645\u0648\u0644 \u0628\u0627\u062a \u0686\u06cc\u062a \u0634\u0631\u0648\u0639 \u06c1\u0648\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f \u0633\u06d2 \u06a9\u06cc\u0627 \u062a\u0628\u062f\u06cc\u0644\u06cc \u0622\u0626\u06cc \u06c1\u06d2) \u0627\u0648\u0631 \u06a9\u0644\u0627\u0624\u0688 \u06a9\u0648 \u067e\u06cc\u063a\u0627\u0645 \u06a9\u06cc \u067e\u0648\u0631\u06cc \u062a\u0627\u0631\u06cc\u062e \u067e\u0648\u0633\u0679 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-typescript\">async function send(text: string) {\n  const trimmed = text.trim();\n  if (!trimmed || sending) return;\n\n  if (!keySaved) {\n    setError(\"Add your Anthropic key above to chat.\");\n    return;\n  }\n\n  setError(null);\n  const nextMessages: Message[] = [...messages, { role: \"user\", content: trimmed }];\n  setMessages(nextMessages);\n  setInput(\"\");\n  setSending(true);\n\n  try {\n    const systemPrompt = buildGroundingContext(threads, brands, selectedThread);\n    const maxTokens = EFFORT_OPTIONS.find((e) => e.id === effort)?.maxTokens ?? 1024;\n\n    const response = await fetch(\"https:\/\/api.anthropic.com\/v1\/messages\", {\n      method: \"POST\",\n      headers: {\n        \"content-type\": \"application\/json\",\n        \"x-api-key\": apiKey,\n        \"anthropic-version\": \"2023-06-01\",\n        \"anthropic-dangerous-direct-browser-access\": \"true\",\n      },\n      body: JSON.stringify({\n        model,\n        max_tokens: maxTokens,\n        system: systemPrompt,\n        messages: nextMessages.map((m) => ({ role: m.role, content: m.content })),\n      }),\n    });\n\n    if (!response.ok) {\n      if (response.status === 401) {\n        throw new Error(\"Invalid API key. Check your Anthropic API key and try again.\");\n      }\n      throw new Error(`API request failed: ({response.status} ){response.statusText}`);\n    }\n\n    const data: { content: AnthropicContentBlock[] } = await response.json();\n    const reply = data.content\n      .filter((b) => b.type === \"text\" && b.text)\n      .map((b) => b.text)\n      .join(\"\");\n\n    setMessages((prev) => [...prev, { role: \"assistant\", content: reply || \"(empty response)\" }]);\n  } catch (err) {\n    setError(err instanceof Error ? err.message : \"Something went wrong.\");\n  } finally {\n    setSending(false);\n  }\n}\n<\/code><\/pre>\n<p>\u0645\u06cc\u06a9\u0627\u0646\u0632\u0645 \u0644\u06cc\u0628\u0644\u0646\u06af \u06a9\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a\u0648\u06ba\u060c \u0648\u06c1\u06cc \u0627\u062e\u062a\u062a\u0627\u0645\u06cc \u0646\u0642\u0637\u0648\u06ba\u060c \u0648\u06c1\u06cc \u0628\u0631\u0627\u0624\u0632\u0631 \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u06a9\u06d2 \u06c1\u06cc\u0688\u0631\u060c \u0627\u0648\u0631 \u0648\u06c1\u06cc 401 \u0634\u0646\u0627\u062e\u062a\u06cc \u063a\u0644\u0637\u06cc \u0633\u06d2 \u0646\u0645\u0679\u0646\u06d2 \u06a9\u0627 \u0622\u0626\u06cc\u0646\u06c1 \u062f\u0627\u0631 \u06c1\u06d2\u06d4 \u0627\u0633 \u06a9\u06cc \u0648\u062c\u06c1 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u0648\u06c1 \u062f\u0648\u0646\u0648\u06ba \u0627\u06cc\u06a9 \u06c1\u06cc \u0645\u062d\u062f\u0648\u062f \u0645\u0627\u062d\u0648\u0644 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u06c1\u06cc API \u0633\u06d2 \u0628\u0627\u062a \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0622\u067e \u06a9\u0627 \u067e\u06cc\u063a\u0627\u0645 \u0686\u0644\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u067e\u06cc\u063a\u0627\u0645\u0627\u062a \u0645\u06cc\u06ba \u0634\u0627\u0645\u0644 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>messages<\/code> \u0635\u0641\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u067e\u0648\u0631\u06cc \u0635\u0641 \u0628\u06be\u06cc\u062c\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06d2 \u062a\u0627\u06a9\u06c1 \u0645\u0627\u0688\u0644 \u0627\u0628 \u062a\u06a9 \u0627\u0633 \u0633\u06d2 \u0628\u0627\u062a \u06a9\u0631 \u0633\u06a9\u06d2\u060c \u0627\u0648\u0631 \u0627\u0633\u0645\u0628\u0644 \u0634\u062f\u06c1 \u0632\u0645\u06cc\u0646\u06cc \u0633\u06cc\u0627\u0642 \u0648 \u0633\u0628\u0627\u0642 \u0627\u0633 \u0637\u0631\u062d \u06c1\u06d2: <code>system<\/code> \u0641\u0648\u0631\u06cc\u06d4 \u062c\u0648\u0627\u0628 \u0645\u06cc\u06ba \u0645\u062a\u0646 \u06a9\u06d2 \u0627\u06cc\u06a9 \u0628\u0644\u0627\u06a9 \u06a9\u0648 \u0645\u062a\u0628\u0627\u062f\u0644 \u0633\u0679\u0631\u0646\u06af \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062c\u0648\u0691 \u06a9\u0631 \u0646\u06a9\u0627\u0644\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u0627\u06af\u0631 \u0645\u0627\u0688\u0644 \u06a9\u0648\u0626\u06cc \u062f\u0633\u062a\u06cc\u0627\u0628 \u0634\u06d2 \u0648\u0627\u067e\u0633 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u062a\u0639\u0645\u06cc\u0631 \u0646\u0648 <code>buildGroundingContext<\/code> \u06c1\u0631 \u0628\u0627\u062a \u0686\u06cc\u062a \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u0628\u06be\u06cc\u062c\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u06c1\u0631 \u0628\u0627\u0631 \u0628\u06be\u06cc\u062c\u0646\u06d2 \u06a9\u0627 \u06cc\u06c1 \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u0627\u0646\u062a\u062e\u0627\u0628 \u06c1\u06d2\u06d4 \u062c\u0628 \u06a9\u0648\u0626\u06cc \u0635\u0627\u0631\u0641 \u0628\u0627\u062a \u0686\u06cc\u062a \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0686\u0644\u0627\u062a\u0627 \u06c1\u06d2 \u06cc\u0627 \u06a9\u0633\u06cc \u062f\u06be\u0627\u06af\u06d2 \u067e\u0631 \u0644\u06cc\u0628\u0644 \u0644\u06af\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0627\u06af\u0644\u0627 \u067e\u06cc\u063a\u0627\u0645 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u0627\u067e \u0688\u06cc\u0679 \u0634\u062f\u06c1 \u0688\u06cc\u0679\u0627 \u06a9\u06cc \u0639\u06a9\u0627\u0633\u06cc \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0628 \u0633\u06d2 \u0686\u06cc\u0679 \u0634\u0631\u0648\u0639 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-model-and-effort-controls\">\u0645\u0627\u0688\u0644 \u0627\u0648\u0631 \u06a9\u0648\u0634\u0634 \u06a9\u0627 \u06a9\u0646\u0679\u0631\u0648\u0644<\/h3>\n<p>\u0627\u0633\u0633\u0679\u0646\u0679 \u062f\u0648 \u0633\u0644\u06cc\u06a9\u0679\u0631\u0632 \u06a9\u0648 \u0638\u0627\u06c1\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2: \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u0627\u0688\u0644 \u0627\u0648\u0631 \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06af\u06c1\u0631\u0627\u0626\u06cc\u06d4 \u062f\u0648\u0646\u0648\u06ba \u0622\u062e\u0631\u06cc\u06d4 <code>chrome.storage.local<\/code> \u06a9\u0644\u06cc\u062f \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0627\u0633\u06cc \u0633\u06cc\u0679 \u0627\u067e \u067e\u06cc\u0679\u0631\u0646 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2:<\/p>\n<pre><code class=\"language-typescript\">const MODEL_OPTIONS = [\n  { id: \"claude-haiku-4-5-20251001\", label: \"Haiku 4.5 \u2014 fastest\" },\n  { id: \"claude-sonnet-4-6\",          label: \"Sonnet 4.6 \u2014 balanced\" },\n  { id: \"claude-opus-4-8\",            label: \"Opus 4.8 \u2014 most capable\" },\n];\n\nconst EFFORT_OPTIONS = [\n  { id: \"low\",    label: \"Low\",    maxTokens: 512 },\n  { id: \"medium\", label: \"Medium\", maxTokens: 1024 },\n  { id: \"high\",   label: \"High\",   maxTokens: 2048 },\n];\n<\/code><\/pre>\n<p>\u0645\u0627\u0688\u0644 \u0633\u0644\u06cc\u06a9\u0679\u0631\u0632 \u0631\u0641\u062a\u0627\u0631 \u0628\u0645\u0642\u0627\u0628\u0644\u06c1 \u0641\u0639\u0627\u0644\u06cc\u062a \u06a9\u06d2 \u0627\u0633\u067e\u06cc\u06a9\u0679\u0631\u0645 \u06a9\u0648 \u067e\u06be\u06cc\u0644\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0641\u0648\u0631\u06cc \u062c\u0648\u0627\u0628\u0627\u062a \u06a9\u06d2 \u0644\u06cc\u06d2 \u06c1\u0627\u0626\u06cc\u06a9\u0648\u060c \u0627\u0644\u062c\u06be\u06d2 \u06c1\u0648\u0626\u06d2 \u062f\u06be\u0627\u06af\u0648\u06ba \u06a9\u06d2 \u0633\u06cc\u0679 \u067e\u0631 \u0632\u06cc\u0627\u062f\u06c1 \u0645\u0634\u06a9\u0644 \u0627\u0646\u062f\u0627\u0632\u06c1 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0648\u067e\u0633\u06d4 \u06a9\u0648\u0634\u0634 \u0633\u0644\u06cc\u06a9\u0679\u0631 \u0646\u0642\u0634\u06c1 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2: <code>max_tokens<\/code>\u0631\u062f\u0639\u0645\u0644 \u06a9\u06cc \u0645\u062f\u062a \u06a9\u0648 \u06a9\u0646\u0679\u0631\u0648\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u0645\u0627\u0688\u0644 \u062a\u06cc\u0627\u0631 \u06a9\u0631 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633 \u0628\u0627\u062a \u06a9\u0648 \u0645\u062f\u0646\u0638\u0631 \u0631\u06a9\u06be\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u06a9\u06c1 \u0645\u06cc\u0633\u062c\u0646\u06af API \u0645\u06cc\u06ba \u06a9\u0648\u0626\u06cc \u0648\u0642\u0641 \u0634\u062f\u06c1 \u06af\u06c1\u0631\u0627\u0626\u06cc \u06a9\u0646\u0679\u0631\u0648\u0644 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u060c \u06cc\u06c1 \u0631\u062f\u0639\u0645\u0644 \u06a9\u06cc \u06af\u06c1\u0631\u0627\u0626\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0645\u0639\u0642\u0648\u0644 \u067e\u0631\u0627\u06a9\u0633\u06cc \u06c1\u06d2\u06d4 \u0648\u06c1 \u0635\u0627\u0631\u0641\u06cc\u0646 \u062c\u0648 \u0627\u06cc\u06a9 \u0633\u0637\u0631\u06cc \u062c\u0648\u0627\u0628 \u0686\u0627\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u0645 \u06a9\u0648 \u0645\u0646\u062a\u062e\u0628 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u061b \u0648\u06c1 \u0635\u0627\u0631\u0641\u06cc\u0646 \u062c\u0648 \u0627\u06cc\u06a9 \u0645\u0639\u0642\u0648\u0644\u060c \u0627\u0639\u0644\u06cc \u062a\u0631\u062c\u06cc\u062d\u06cc \u0645\u0646\u0635\u0648\u0628\u06c1 \u0686\u0627\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba \u06c1\u0627\u0626\u06cc \u06a9\u0648 \u0645\u0646\u062a\u062e\u0628 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-rendering-replies-and-the-empty-state\">\u0631\u06cc\u0646\u0688\u0631\u0646\u06af \u062c\u0648\u0627\u0628 \u0627\u0648\u0631 \u062e\u0627\u0644\u06cc \u062d\u0627\u0644\u062a<\/h3>\n<p>\u0645\u0627\u0688\u0644 \u0642\u062f\u0631\u062a\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0627\u06cc\u06a9 \u062a\u0631\u062c\u06cc\u062d\u06cc \u0641\u06c1\u0631\u0633\u062a \u0627\u0648\u0631 \u0645\u0631\u062d\u0644\u06c1 \u0648\u0627\u0631 \u062a\u062c\u0627\u0648\u06cc\u0632 \u06a9\u0648 \u0639\u0646\u0648\u0627\u0646\u0627\u062a \u0627\u0648\u0631 \u06af\u0648\u0644\u06cc\u0648\u06ba \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0641\u0627\u0631\u0645\u06cc\u0679 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06c1\u0630\u0627 \u0645\u062f\u062f\u06af\u0627\u0631 Claude \u06a9\u06d2 \u062c\u0648\u0627\u0628 \u06a9\u0648 Markdown \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u067e\u06cc\u0634 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u062c\u0628 \u0633\u0627\u062f\u06c1 \u0645\u062a\u0646 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u067e\u06cc\u0634 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u06cc\u06c1 \u062e\u0627\u0645 \u0633\u062a\u0627\u0631\u06d2 \u0627\u0648\u0631 \u06c1\u06cc\u0634 \u06a9\u06cc \u0637\u0631\u062d \u0644\u06af\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba <code>react-markdown<\/code>\u0631\u062f\u0639\u0645\u0644 \u06a9\u0627 \u062c\u0632\u0648 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0637\u0648\u0631 \u067e\u0631 \u06c1\u06d2\u06d4 <code><reactmarkdown>{m.content}<\/reactmarkdown><\/code> \u062b\u0627\u0646\u0648\u06cc \u067e\u06cc\u063a\u0627\u0645\u0627\u062a \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u0635\u0627\u0631\u0641 \u06a9\u06d2 \u067e\u06cc\u063a\u0627\u0645 \u06a9\u0648 \u0633\u0627\u062f\u06c1 \u0645\u062a\u0646 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u067e\u06cc\u0634 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0633\u0627\u062a\u06be \u0648\u0627\u0644\u06cc \u0637\u0631\u0632\u06cc\u06ba \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u06a9\u06d2 \u0679\u0627\u0626\u067e \u0627\u0633\u06a9\u06cc\u0644 \u0633\u06d2 \u0645\u0645\u0627\u062b\u0644 \u0645\u0627\u0631\u06a9 \u0688\u0627\u0624\u0646 \u0639\u0646\u0627\u0635\u0631 \u06a9\u0648 \u0646\u0634\u0627\u0646\u06c1 \u0628\u0646\u0627\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0628\u0627\u062a \u0686\u06cc\u062a \u0634\u0631\u0648\u0639 \u06c1\u0648\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2\u060c \u067e\u06cc\u0646\u0644 \u0627\u06cc\u06a9 \u0644\u0627\u0626\u0646 \u06a9\u06cc \u062a\u0641\u0635\u06cc\u0644 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u06cc\u06a9 \u062e\u0627\u0644\u06cc \u062d\u0627\u0644\u062a \u062f\u06a9\u06be\u0627\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u06a9\u0644\u06a9 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u0686\u067e\u0633 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06c1 \u062a\u062c\u0648\u06cc\u0632 \u06a9\u0631\u062f\u06c1 \u06a9\u0626\u06cc \u0627\u0634\u0627\u0631\u06d2\u060c \u062c\u06cc\u0633\u06d2 \u06a9\u06c1 \"\u0645\u062c\u06be\u06d2 \u0627\u0633 \u06c1\u0641\u062a\u06d2 \u06a9\u06cc\u0627 \u0628\u0646\u062f \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u061f\"\u060c \"\u0644\u0648\u067e \u06a9\u0627 \u062e\u0644\u0627\u0635\u06c1 \u06a9\u06be\u0648\u0644\u06cc\u06ba\"\u060c \u0627\u0648\u0631 \"\u0633\u0628 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u062a\u0627\u062e\u06cc\u0631 \u06a9\u0633 \u0686\u06cc\u0632 \u0645\u06cc\u06ba \u06c1\u0648\u0626\u06cc\u061f\" \u062f\u0648\u0646\u0648\u06ba \u0622\u067e \u06a9\u0648 \u062f\u06a9\u06be\u0627\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u0622\u067e \u06a9\u0627 \u0627\u0633\u0633\u0679\u0646\u0679 \u06a9\u06cc\u0627 \u06a9\u0631 \u0633\u06a9\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0622\u067e \u06a9\u0648 \u0627\u06cc\u06a9 \u06a9\u0644\u06a9 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0634\u0631\u0648\u0639 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0637\u0631\u06cc\u0642\u06c1 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u062c\u0628 \u06a9\u0633\u06cc \u062a\u06be\u0631\u06cc\u0688 \u067e\u0631 \u0641\u0648\u06a9\u0633 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u062a\u0648 \u062a\u062c\u0648\u06cc\u0632 \u06a9\u0631\u062f\u06c1 \u067e\u0631\u0627\u0645\u067e\u0679 \u062a\u06be\u0648\u0691\u0627 \u0633\u0627 \u0628\u062f\u0644 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \"\u0645\u06cc\u06ba \u0627\u0633 \u06a9\u0627\u0645 \u06a9\u0648 \u06a9\u06cc\u0633\u06d2 \u0645\u06a9\u0645\u0644 \u06a9\u0631\u0648\u06ba\u061f\" \u06cc\u06c1 \u0645\u06a9\u0645\u0644 \u0633\u06cc\u0679 \u0633\u0645\u0631\u06cc \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0641\u0648\u06a9\u0633\u0688 \u06af\u0631\u0627\u0624\u0646\u0688\u0646\u06af \u0645\u0648\u0688 \u0633\u06d2 \u0645\u06cc\u0644 \u06a9\u06be\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u06cc\u06a9 \u067e\u0631\u0627\u0626\u06cc\u0648\u06cc\u0633\u06cc \u0644\u0627\u0626\u0646 \u0645\u0633\u062a\u0642\u0644 \u0637\u0648\u0631 \u067e\u0631 \u0645\u0635\u0646\u0641 \u06a9\u06d2 \u0646\u06cc\u0686\u06d2 \u0648\u0627\u0642\u0639 \u06c1\u06d2\u060c \u062c\u0633 \u0633\u06d2 \u06cc\u06c1 \u0638\u0627\u06c1\u0631 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0686\u06cc\u0679 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u0627 \u0639\u0646\u0648\u0627\u0646 \u0627\u0648\u0631 \u062e\u0644\u0627\u0635\u06c1 Anthropic \u06a9\u0648 \u0628\u06be\u06cc\u062c\u06d2 \u06af\u0627\u060c \u0627\u0648\u0631 \u0688\u06cc\u0648\u0627\u0626\u0633 \u06a9\u06d2 \u0628\u0627\u06c1\u0631 \u06a9\u0686\u06be \u0646\u06c1\u06cc\u06ba \u0628\u06be\u06cc\u062c\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4 \u06cc\u06c1 \u0627\u06cc\u0645\u0627\u0646\u062f\u0627\u0631\u0627\u0646\u06c1 \u0627\u0646\u06a9\u0634\u0627\u0641 \u06a9\u0627 \u0648\u06c1\u06cc \u0627\u0635\u0648\u0644 \u06c1\u06d2 \u062c\u0648 \u067e\u0648\u0631\u06d2 \u0628\u0648\u0631\u0688 \u0645\u06cc\u06ba \u0627\u0646 \u062c\u06af\u06c1\u0648\u06ba \u067e\u0631 \u0644\u0627\u06af\u0648 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u062c\u06c1\u0627\u06ba \u0635\u0627\u0631\u0641 \u0679\u0627\u0626\u067e \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0686\u06cc\u0632\u0648\u06ba \u06a9\u0648 \u062f\u06cc\u06a9\u06be \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-checkpoint\">\u0686\u0648\u06a9\u06cc<\/h3>\n<p>\u0627\u0633\u0633\u0679\u0646\u0679 \u06a9\u06d2 \u0633\u0627\u062a\u06be\u060c \u0627\u0648\u067e\u0646 \u0644\u0648\u067e\u0633 \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u0641\u0639\u0627\u0644 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0644\u0648\u0688 \u06a9\u0631\u06cc\u06ba\u060c \u0627\u06cc\u06a9 \u0627\u0631\u0627\u062f\u06d2 \u06a9\u0627 \u0646\u0642\u0634\u06c1 \u0628\u0646\u0627\u0626\u06cc\u06ba\u060c \u0627\u0646\u062a\u06be\u0631\u0648\u067e\u06a9 \u06a9\u06cc\u0632 \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u060c \u0627\u0648\u0631 \u062a\u062c\u0648\u06cc\u0632 \u06a9\u0631\u062f\u06c1 \u0627\u0634\u0627\u0631\u06d2 \u0622\u0632\u0645\u0627\u0626\u06cc\u06ba\u06d4 \u062c\u0628 \u0627\u0633 \u0633\u06d2 \u067e\u0648\u0686\u06be\u0627 \u06af\u06cc\u0627 \u06a9\u06c1 \u0627\u0633 \u06c1\u0641\u062a\u06d2 \u06a9\u06cc\u0627 \u062e\u062a\u0645 \u06a9\u0631\u0646\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0622\u067e \u06a9\u06d2 \u0645\u0639\u0627\u0648\u0646 \u06a9\u0648 \u0627\u06cc\u06a9 \u0645\u062e\u0635\u0648\u0635 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u0627 \u0646\u0627\u0645 \u062f\u06cc\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2 \u0627\u0648\u0631 \u06cc\u06c1 \u0628\u062a\u0627\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2 \u06a9\u06c1 \u062d\u0642\u06cc\u0642\u06cc \u0641\u06cc\u0635\u0644\u06d2 \u06a9\u06d2 \u0645\u0642\u0627\u0628\u0644\u06d2 \u0645\u06cc\u06ba \u06cc\u06c1 \u0627\u06cc\u06a9 \u0622\u0633\u0627\u0646 \u062c\u06cc\u062a \u06a9\u06cc\u0648\u06ba \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0622\u067e \u06a9\u0633\u06cc \u0627\u06cc\u06a9 \u062a\u06be\u0631\u06cc\u0688 \u067e\u0631 \u06a9\u0644\u06a9 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u067e\u0648\u0686\u06be\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u06cc\u06c1 \u06a9\u06cc\u0633\u06d2 \u062e\u062a\u0645 \u06c1\u0648\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u060c \u062a\u0648 \u062c\u0648\u0627\u0628 \u0627\u0633 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u06cc \u062a\u0641\u0635\u06cc\u0644\u0627\u062a \u062a\u06a9 \u0645\u062d\u062f\u0648\u062f \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4<\/p>\n<p>\u0628\u0627\u062a \u0686\u06cc\u062a \u0627\u0635\u0644 \u0645\u0648\u062c\u0648\u062f\u06c1 \u062f\u06be\u0627\u06af\u06d2 \u06a9\u06cc \u0639\u06a9\u0627\u0633\u06cc \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u060c \u0627\u0648\u0631 \u06af\u0641\u062a\u06af\u0648 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u06a9\u0686\u06be \u0628\u06be\u06cc \u0622\u067e \u06a9\u06d2 \u06a9\u0645\u067e\u06cc\u0648\u0679\u0631 \u067e\u0631 \u0628\u0627\u0642\u06cc \u0646\u06c1\u06cc\u06ba \u0631\u06c1\u062a\u0627 \u0633\u0648\u0627\u0626\u06d2 \u0627\u06cc\u06a9 \u062f\u06be\u0627\u06af\u06d2 \u06a9\u06d2 \u062e\u0644\u0627\u0635\u06d2 \u06a9\u06d2 \u062c\u0633\u06d2 \u062e\u0648\u062f \u0632\u0645\u06cc\u0646\u06cc \u062a\u0646\u0627\u0638\u0631 \u0645\u06cc\u06ba \u062f\u06cc\u06a9\u06be\u0627 \u062c\u0627 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u062a\u0639\u0645\u06cc\u0631 \u0645\u06a9\u0645\u0644 \u06c1\u06d2\u06d4 \u0622\u062e\u0631\u06cc \u062d\u0635\u06d2 \u0645\u06cc\u06ba\u060c \u06c1\u0645 \u0627\u06cc\u06a9 \u0642\u062f\u0645 \u067e\u06cc\u0686\u06be\u06d2 \u06c1\u0679\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u062f\u06cc\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u0622\u067e \u0646\u06d2 \u06a9\u06cc\u0627 \u0628\u0646\u0627\u06cc\u0627 \u06c1\u06d2\u06d4 \u06cc\u0639\u0646\u06cc\u060c \u06cc\u06c1 \u0627\u0633 \u062e\u06cc\u0627\u0644 \u06a9\u06cc \u0627\u06cc\u06a9 \u0645\u0631\u06a9\u0632\u06cc \u062f\u06be\u0627\u0631\u06d2 \u06a9\u06cc \u06a9\u0648\u0634\u0634 \u0633\u06d2 \u06a9\u0633 \u0637\u0631\u062d \u0645\u0648\u0627\u0632\u0646\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u06cc\u06c1 \u0631\u0627\u0632\u062f\u0627\u0631\u06cc \u06a9\u06d2 \u0645\u0627\u0688\u0644 \u0645\u06cc\u06ba \u06a9\u06cc\u0627 \u0627\u0636\u0627\u0641\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u06cc\u06c1 \u0627\u0633\u06d2 \u0627\u06af\u0644\u06d2 \u062f\u0631\u062c\u06d2 \u062a\u06a9 \u06a9\u06c1\u0627\u06ba \u0644\u06d2 \u062c\u0627 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h2 id=\"heading-what-youve-built-and-where-to-take-it\">\u0622\u067e \u06a9\u06cc\u0627 \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u06a9\u06c1\u0627\u06ba \u0644\u06d2 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/h2>\n<p>\u06c1\u0645 \u0646\u06d2 \u0627\u06cc\u06a9 \u0645\u06a9\u0645\u0644 \u0646\u0638\u0627\u0645 \u0628\u0646\u0627\u06cc\u0627 \u06c1\u06d2\u06d4 \u062a\u0644\u0627\u0634 \u06a9\u06cc \u0633\u0631\u06af\u0632\u0634\u062a \u06a9\u0648 \u06a9\u06cc\u067e\u0686\u0631 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0641\u06cc\u0688 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0645\u0646\u0638\u0645 \u0627\u0648\u0631 \u0633\u06cc\u0634\u0646\u0632 \u0645\u06cc\u06ba \u062a\u0642\u0633\u06cc\u0645 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0646\u0679\u06cc\u0646\u0679 \u062a\u06be\u0631\u06cc\u0688\u0632 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u06a9\u0644\u0633\u0679\u0631\u0688 \u0627\u0648\u0631 \u0627\u0633\u06a9\u0648\u0631 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0627\u062e\u062a\u06cc\u0627\u0631\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0644\u06cc\u0628\u0644 \u0644\u06af\u0627 \u06c1\u0648\u0627 \u0627\u0648\u0631 AI \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0686\u0644\u0627\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0628\u0627\u062a \u0686\u06cc\u062a \u06a9\u06d2 \u0645\u0639\u0627\u0648\u0646\u06cc\u0646 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0688\u0633\u067e\u0644\u06d2 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u06c1\u0631 \u0642\u062f\u0645 \u0627\u067e\u0646\u06cc \u0645\u0634\u06cc\u0646 \u067e\u0631 \u0686\u0644\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 AI \u067e\u0631\u062a \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u06d2 \u0627\u0648\u067e\u0631 \u0627\u06cc\u06a9 \u0627\u062e\u062a\u06cc\u0627\u0631\u06cc \u0627\u0636\u0627\u0641\u06c1 \u06c1\u06d2\u060c \u062c\u0648 \u0627\u0633 \u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u06af\u0631 \u06a9\u0644\u0633\u0679\u0631\u0646\u06af \u0622\u067e \u06a9\u0648 Chrome \u06a9\u06cc \u067e\u0631\u0627\u0646\u06cc Journeys \u06a9\u06cc \u062e\u0635\u0648\u0635\u06cc\u062a \u06a9\u06cc \u06cc\u0627\u062f \u062f\u0644\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u06cc\u06c1 \u0627\u06cc\u06a9 \u0645\u0646\u0635\u0641\u0627\u0646\u06c1 \u06a9\u0646\u06a9\u0634\u0646 \u06c1\u06d2\u06d4 \u0648\u0642\u062a \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0639\u0646\u0648\u0627\u0646 \u06a9\u06d2 \u0644\u062d\u0627\u0638 \u0633\u06d2 \u0631\u06cc\u06a9\u0627\u0631\u0688\u0632 \u06a9\u0648 \u06af\u0631\u0648\u067e \u06a9\u0631\u0646\u0627 \u0627\u062a\u0646\u0627 \u06c1\u06cc \u0627\u0686\u06be\u0627 \u0646\u0642\u0637\u06c1 \u0622\u063a\u0627\u0632 \u06c1\u06d2\u06d4<\/p>\n<p>openloops \u0627\u06cc\u06a9 \u0642\u062f\u0645 \u0622\u06af\u06d2 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u06c1\u0631 \u062f\u06be\u0627\u06af\u06c1 \u0627\u0639\u062a\u0645\u0627\u062f \u06a9\u06d2 \u0627\u0633\u06a9\u0648\u0631 \u0627\u0648\u0631 \u062d\u0627\u0644\u062a \u06a9\u0648 \u067e\u0627\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0627\u06cc\u06a9 AI \u067e\u0631\u062a \u0644\u06cc\u0628\u0644\u0632 \u0627\u0648\u0631 \u0645\u062e\u0635\u0648\u0635 \u0627\u06af\u0644\u06d2 \u0645\u0631\u0627\u062d\u0644 \u06a9\u0627 \u0627\u0636\u0627\u0641\u06c1 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u060c \u0645\u0637\u0627\u0644\u0628\u06d2 \u067e\u0631 \u062a\u06be\u0631\u06cc\u0688\u0632 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0627\u0633\u0633\u0679\u0646\u0679 \u0648\u062c\u0648\u06c1\u0627\u062a\u060c \u0627\u0648\u0631 \u0633\u0628 \u06a9\u0686\u06be \u0627\u0648\u067e\u0646 \u0633\u0648\u0631\u0633 \u0627\u0648\u0631 \u0644\u0648\u06a9\u0644 \u0641\u0631\u0633\u0679 \u06c1\u06d2\u06d4 \u0627\u0633 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2 \u06a9\u06c1 \u0622\u067e \u0628\u0627\u0644\u06a9\u0644 \u0648\u06c1\u06cc \u067e\u0691\u06be \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0648 \u0688\u06cc\u0679\u0627 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-what-the-privacy-model-adds-up-to\">\u0631\u0627\u0632\u062f\u0627\u0631\u06cc \u06a9\u0627 \u0645\u0627\u0688\u0644 \u06a9\u06cc\u0627 \u0634\u0627\u0645\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/h3>\n<p>\u0631\u0627\u0632\u062f\u0627\u0631\u06cc \u0646\u06d2 \u06c1\u0631 \u0642\u062f\u0645 \u067e\u0631 \u062a\u0639\u0645\u06cc\u0631 \u06a9\u0648 \u0634\u06a9\u0644 \u062f\u06cc \u06c1\u06d2\u060c \u0627\u0648\u0631 \u06cc\u06c1 \u0627\u0633 \u06a9\u06d2 \u0645\u0648\u0627\u062f \u06a9\u0648 \u0627\u06cc\u06a9 \u062c\u06af\u06c1 \u062c\u0645\u0639 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u06c1\u06d2\u06d4 \u067e\u0648\u0631\u06cc \u0628\u0646\u06cc\u0627\u062f\u06cc \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646\u060c \u0633\u06a9\u0648\u0631 \u0634\u062f\u06c1 \u062a\u06be\u0631\u06cc\u0688\u0632 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u06a9\u06cc\u067e\u0686\u0631 \u06a9\u06cc \u06af\u0626\u06cc \u06c1\u06d2\u060c \u0628\u063a\u06cc\u0631 \u06a9\u0633\u06cc \u0646\u06cc\u0679 \u0648\u0631\u06a9 \u06a9\u0627\u0644 \u06a9\u06d2 \u0645\u0642\u0627\u0645\u06cc \u0637\u0648\u0631 \u067e\u0631 IndexedDB \u067e\u0631 \u0686\u0644\u062a\u06cc \u06c1\u06d2\u06d4 \u0622\u067e \u06a9\u06cc \u0628\u0631\u0627\u0624\u0632\u0646\u06af \u06c1\u0633\u0679\u0631\u06cc - \u062e\u0627\u0645 \u0648\u0627\u0642\u0639\u0627\u062a\u060c \u0633\u06cc\u0634\u0646\u0632\u060c \u062a\u06be\u0631\u06cc\u0688\u0632\u060c \u0648\u063a\u06cc\u0631\u06c1 - \u0622\u067e \u06a9\u06d2 \u06a9\u0645\u067e\u06cc\u0648\u0679\u0631 \u06a9\u0648 \u0633\u0633\u0679\u0645 \u06a9\u06d2 \u06a9\u0633\u06cc \u0627\u06cc\u0633\u06d2 \u062d\u0635\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0646\u06c1\u06cc\u06ba \u0686\u06be\u0648\u0691\u062a\u06cc \u062c\u0648 \u0628\u063a\u06cc\u0631 \u0686\u0627\u0628\u06cc\u0627\u06ba \u06a9\u06d2 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u062f\u0648 AI \u067e\u0631\u062a\u06cc\u06ba \u0648\u06c1 \u0648\u0627\u062d\u062f \u0631\u0627\u0633\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0646 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u062a\u0645\u0627\u0645 \u0688\u06cc\u0679\u0627 \u0688\u06cc\u0648\u0627\u0626\u0633 \u0633\u06d2 \u0646\u06a9\u0644 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u062f\u0648\u0646\u0648\u06ba \u0627\u067e\u0646\u06cc API \u06a9\u06cc\u0632 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0635\u0627\u0631\u0641\u06cc\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0622\u067e\u0679 \u0627\u0646 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0631\u0646 \u0679\u0627\u0626\u0645 \u067e\u0631 \u0628\u06be\u06cc\u062c\u0627 \u062c\u0627\u0646\u06d2 \u0648\u0627\u0644\u0627 \u0645\u0648\u0627\u062f \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u06a9\u0645 \u0633\u06d2 \u06a9\u0645 \u06c1\u06d2\u06d4 \u0628\u0631\u0627\u0646\u0688 \u0627\u06cc\u0646\u06c1\u0627\u0646\u0633\u0645\u0646\u0679 \u0635\u0631\u0641 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0688\u0648\u0645\u06cc\u0646 \u0646\u0627\u0645 \u0628\u06be\u06cc\u062c\u062a\u0627 \u06c1\u06d2\u060c URL \u06cc\u0627 \u0635\u0641\u062d\u06c1 \u06a9\u0627 \u0645\u0648\u0627\u062f \u0646\u06c1\u06cc\u06ba\u060c context.dev \u067e\u0631 \u0627\u0648\u0631 \u067e\u06c1\u0644\u06d2 \u0645\u0642\u0627\u0645\u06cc \u067e\u062a\u06d2 \u0646\u06a9\u0627\u0644 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 \u0644\u06cc\u0628\u0644\u0646\u06af \u0627\u0648\u0631 \u0627\u0633\u0633\u0679\u0646\u0679 \u062a\u06be\u0631\u06cc\u0688 \u06a9\u0627 \u0639\u0646\u0648\u0627\u0646\u060c \u062e\u0644\u0627\u0635\u06c1\u060c \u06a9\u0644\u06cc\u062f\u06cc \u0627\u0644\u0641\u0627\u0638\u060c \u0627\u0648\u0631 \u0646\u0645\u0648\u0646\u06c1 \u0635\u0641\u062d\u06c1 \u06a9\u0627 \u0639\u0646\u0648\u0627\u0646 Anthropic \u06a9\u0648 \u0628\u06be\u06cc\u062c\u062a\u0627 \u06c1\u06d2\u060c \u062c\u0648 \u0622\u067e \u06a9\u06d2 \u06a9\u0648\u0688 \u0633\u06d2 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u067e\u0691\u06be\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u0637\u06d2 \u0634\u062f\u06c1 \u0633\u06cc\u0627\u0642 \u0648 \u0633\u0628\u0627\u0642 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0633 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u06a9\u0686\u06be \u0646\u06c1\u06cc\u06ba\u06d4 \u06a9\u0644\u06cc\u062f \u062e\u0648\u062f <code>chrome.storage.local<\/code>\u06cc\u06c1 \u06a9\u0628\u06be\u06cc \u0628\u06be\u06cc \u0645\u0637\u0627\u0628\u0642\u062a \u067e\u0630\u06cc\u0631 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-where-to-take-it-next\">\u0645\u06cc\u06ba \u0627\u0633\u06d2 \u0622\u06af\u06d2 \u06a9\u06c1\u0627\u06ba \u0644\u06d2 \u062c\u0627\u0624\u06ba\u061f<\/h3>\n<p>\u062a\u0639\u0645\u06cc\u0631 \u0645\u06cc\u06ba \u0627\u0686\u06be\u06cc \u0645\u0634\u0642 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0686\u06be \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u0622\u0633\u0627\u0646\u06cc\u0627\u06ba \u0634\u0627\u0645\u0644 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0633\u0628 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0627\u0637\u0645\u06cc\u0646\u0627\u0646 \u0628\u062e\u0634 \u0686\u06cc\u0632 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u06a9\u0648\u0688 \u06a9\u06d2 \u0627\u0648\u067e\u0631\u06cc \u062d\u0635\u06d2 \u067e\u0631 \u0628\u0646\u0627\u0646\u0627 \u06c1\u06d2 \u062c\u0648 \u0622\u067e \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u0644\u06a9\u06be \u0686\u06a9\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0688\u0648\u0645\u06cc\u0646 \u06a9\u06cc \u0637\u0631\u0641 <code>ambient.ts<\/code>\u0627\u06cc\u0633\u06d2 \u0688\u0648\u0645\u06cc\u0646\u0632 \u06a9\u0648 \u06c1\u0679\u0627 \u062f\u06cc\u06ba \u062c\u0648 \u0632\u06cc\u0627\u062f\u06c1 \u0641\u0639\u0627\u0644 \u062f\u0646\u0648\u06ba \u0645\u06cc\u06ba \u0638\u0627\u06c1\u0631 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u062a\u0627\u06c1\u0645\u060c \u0645\u0637\u0644\u0648\u0628\u06c1 \u0627\u0644\u0641\u0627\u0638 \u06a9\u06cc \u0637\u0631\u0641 \u06a9\u0648\u0626\u06cc \u0645\u0633\u0627\u0648\u06cc \u0644\u0641\u0638 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u060c \u0644\u06c1\u0630\u0627 \u06cc\u06c1 \u06c1\u0631 \u062c\u06af\u06c1 \u0645\u0648\u062c\u0648\u062f \u0644\u0641\u0638 \u06c1\u06d2\u06d4 <em>\u0622\u067e \u06a9\u06d2 \u0644\u06cc\u06d2<\/em> (\u06a9\u06c1\u0648 <code>typescript<\/code>\u0627\u06af\u0631 \u0622\u067e TypeScript \u0688\u0648\u06cc\u0644\u067e\u0631 \u06c1\u06cc\u06ba)\u060c \u062a\u0648 \u0622\u067e \u062a\u0645\u0627\u0645 \u0633\u06cc\u0634\u0646\u0632 \u0645\u06cc\u06ba \u06a9\u0644\u06cc\u062f\u06cc \u0627\u0644\u0641\u0627\u0638 \u06a9\u0648 \u0632\u0646\u062f\u06c1 \u0631\u06a9\u06be \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u063a\u06cc\u0631 \u0645\u062a\u0639\u0644\u0642\u06c1 \u062a\u06be\u0631\u06cc\u0688\u0632 \u06a9\u0648 \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u0628\u0627\u0646\u062f\u06be \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0641\u06a9\u0633 \u0641\u0631\u06cc\u06a9\u0648\u0626\u0646\u0633\u06cc \u067e\u0631 \u0645\u0628\u0646\u06cc \u0645\u0637\u0644\u0648\u0628\u06c1 \u0627\u0644\u0641\u0627\u0638 \u06a9\u0627 \u067e\u062a\u06c1 \u0644\u06af\u0627\u0646\u06d2 \u0648\u0627\u0644\u0627 \u06c1\u06d2 \u062c\u0648 \u0627\u0633 \u06a9\u06cc \u0639\u06a9\u0627\u0633\u06cc \u06a9\u0631\u062a\u0627 \u06c1\u06d2: <code>detectAmbientDomains<\/code> \u062a\u0642\u0631\u06cc\u0628\u0627\u064b \u0633\u0637\u0631 \u0628\u06c1 \u0633\u0637\u0631\u060c \u06c1\u0645 \u062f\u0646 \u0641\u06cc \u0688\u0648\u0645\u06cc\u0646 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0641\u06cc \u06a9\u0644\u06cc\u062f\u06cc \u0644\u0641\u0638 \u06a9\u06d2 \u062f\u0646\u0648\u06ba \u06a9\u0627 \u062d\u0633\u0627\u0628 \u0644\u06af\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-typescript\">export function detectAmbientKeywords(sessions: Session[]): Set<string> {\n  const allEvents = sessions.flatMap((s) => s.events);\n  const activeDays = new Set(allEvents.map((e) => new Date(e.visitedAt).toDateString()));\n  const totalActiveDays = activeDays.size;\n  if (totalActiveDays < MIN_ACTIVE_DAYS) return new Set();\n\n  const keywordDayMap = new Map<string set=\"\">>();\n  for (const session of sessions) {\n    const day = new Date(session.startedAt).toDateString();\n    for (const kw of session.keywords) {\n      if (!keywordDayMap.has(kw)) keywordDayMap.set(kw, new Set());\n      keywordDayMap.get(kw)!.add(day);\n    }\n  }\n\n  const ambient = new Set<string>();\n  for (const [kw, days] of keywordDayMap) {\n    if (days.size \/ totalActiveDays >= UBIQUITY_THRESHOLD) ambient.add(kw);\n  }\n  return ambient;\n}\n<\/string><\/string><\/string><\/code><\/pre>\n<p>\u067e\u06be\u0631 \u06c1\u0645 \u0627\u0646 \u0645\u0637\u0644\u0648\u0628\u06c1 \u0627\u0644\u0641\u0627\u0638 \u06a9\u0648 \u0627\u0646\u062f\u0631 \u0633\u06d2 \u06c1\u0679\u0627 \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>similarity<\/code> \u0622\u062c \u06cc\u06c1 \u0628\u0627\u0644\u06a9\u0644 \u0627\u06cc\u0633\u0627 \u06c1\u06cc \u06c1\u06d2 \u062c\u06cc\u0633\u06d2 \u062f\u0648\u0646\u0648\u06ba \u0688\u0648\u0645\u06cc\u0646\u0632 \u06a9\u0648 \u0641\u0644\u0679\u0631 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u0631\u062f \u06af\u0631\u062f \u06a9\u06d2 \u0688\u0648\u0645\u06cc\u0646\u0632 \u06a9\u0648 \u06c1\u0679\u0627 \u062f\u06cc\u0627 \u062c\u0627\u0626\u06d2\u06d4 <code>sessionKeywords<\/code> \u0627\u0648\u0631 \u062a\u06be\u0631\u06cc\u0688 \u0645\u06cc\u06ba <code>keywordSet<\/code> \u062c\u06cc\u06a9\u0627\u0631\u0688 \u06a9\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2\u06d4<\/p>\n<p>\u062f\u0648 \u0686\u06be\u0648\u0679\u06cc \u0645\u0634\u0642\u06cc\u06ba \u062e\u062a\u0645 \u06c1\u0648\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 \u0633\u06cc\u0634\u0646 \u06a9\u0627 \u0648\u0642\u0641\u06c1\u060c \u0645\u0645\u0627\u062b\u0644\u062a \u06a9\u06cc \u062d\u062f\u060c \u0627\u0648\u0631 \u067e\u0691\u0648\u0633 \u06a9\u06cc \u06c1\u0631 \u062c\u06af\u06c1 \u06a9\u06cc \u062d\u062f \u0633\u0628\u06be\u06cc \u06c1\u0627\u0631\u0688 \u06a9\u0648\u0688 \u0648\u0627\u0644\u06d2 \u0645\u0633\u062a\u0642\u0644 \u06c1\u06cc\u06ba\u06d4 \u0645\u0639\u0627\u0648\u0646 \u062a\u0631\u062a\u06cc\u0628\u0627\u062a \u06a9\u06d2 \u067e\u06cc\u0646\u0644 \u067e\u0631 \u0644\u0641\u0679 \u06a9\u0631\u06cc\u06ba\u06d4 <code>chrome.storage.local<\/code> (\u0648\u06c1\u06cc \u0633\u0679\u0648\u0631\u06cc\u062c \u062c\u0648 \u0622\u067e \u06a9\u06cc API \u06a9\u06cc\u0632 \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631 \u0631\u06c1\u06cc \u06c1\u06cc\u06ba)\u060c \u0622\u067e \u06a9\u0644\u0633\u0679\u0631\u0646\u06af \u06a9\u0648 \u0627\u067e\u0646\u06cc \u062a\u0644\u0627\u0634 \u06a9\u06d2 \u0645\u0637\u0627\u0628\u0642 \u0628\u0646\u0627 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u0648\u0631 <code>extractDomain<\/code> \u06cc\u06c1 \u0635\u0631\u0641 \u0633\u0627\u0628\u0642\u06c1 \u200b\u200b\u06a9\u0648 \u06c1\u0679\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>www.<\/code>\u062a\u0648 <code>news.bbc.co.uk<\/code> \u0627\u0648\u0631 <code>bbc.co.uk<\/code> \u0627\u0646 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0645\u062e\u062a\u0644\u0641 \u0688\u0648\u0645\u06cc\u0646\u0632 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0633\u0644\u0648\u06a9 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0644\u0627\u0626\u0628\u0631\u06cc\u0631\u06cc\u0648\u06ba \u06a9\u06d2 \u0644\u0626\u06d2 \u0645\u06cc\u0632\u0628\u0627\u0646 \u0646\u0627\u0645 \u06a9\u06cc \u0645\u0646\u0637\u0642 \u06a9\u0648 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u06cc\u06ba \u062c\u0648 \u0639\u0648\u0627\u0645\u06cc \u0644\u0627\u062d\u0642\u06c1 \u0641\u06c1\u0631\u0633\u062a \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06cc \u06c1\u06cc\u06ba (\u0688\u0648\u0645\u06cc\u0646 \u0644\u0627\u062d\u0642\u0648\u06ba \u06a9\u06cc \u0627\u06cc\u06a9 \u06a9\u06cc\u0646\u0648\u0646\u06cc\u06a9\u0644 \u0641\u06c1\u0631\u0633\u062a\u060c \u062c\u06cc\u0633\u06d2: <code>.co.uk<\/code> \u0622\u067e \u062c\u0633 \u0628\u0631\u0627\u0624\u0632\u0631 \u06a9\u0648 \u06cc\u06c1 \u062c\u0627\u0646\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u0627\u06cc\u06a9 \u0631\u062c\u0633\u0679\u0631\u0688 \u0688\u0648\u0645\u06cc\u0646 \u062f\u0631\u0627\u0635\u0644 \u06a9\u06c1\u0627\u06ba \u062e\u062a\u0645 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u0648\u06c1 \u0627\u0633\u06cc \u0633\u0627\u0626\u0679 \u06a9\u06d2 \u0630\u06cc\u0644\u06cc \u0688\u0648\u0645\u06cc\u0646\u0632 \u06a9\u0648 \u0635\u062d\u06cc\u062d \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u062e\u062a\u0645 \u06a9\u0631 \u062f\u06d2 \u06af\u0627\u06d4<\/p>\n<p>\u067e\u0648\u0631\u06cc \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0645\u0642\u0627\u0645\u06cc \u0627\u0648\u0631 \u0642\u0627\u0628\u0644 \u0645\u0639\u0627\u0626\u0646\u06c1 \u06c1\u06d2\u060c \u0644\u06c1\u0630\u0627 \u06c1\u0631 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u0648 \u062d\u0642\u06cc\u0642\u06cc \u0688\u06cc\u0679\u0627 \u067e\u0631 \u0622\u0632\u0645\u0627\u06cc\u0627 \u062c\u0627 \u0633\u06a9\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0633 \u06a9\u06d2 \u0627\u062b\u0631\u0627\u062a \u0641\u0648\u0631\u06cc \u0637\u0648\u0631 \u067e\u0631 \u062f\u06cc\u06a9\u06be\u06d2 \u062c\u0627 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h2 id=\"heading-wrapping-up\">\u062e\u062a\u0645<\/h2>\n<p>\u0627\u0648\u067e\u0646 \u0644\u0648\u067e\u0633 \u0622\u067e \u06a9\u0648 \u06a9\u06be\u0644\u06d2 \u06c1\u0648\u0626\u06d2 \u0644\u0648\u067e\u0633 \u06a9\u0648 \u0628\u0646\u062f \u06a9\u0631\u0646\u06d2 \u0627\u0648\u0631 \u0627\u0633 \u0633\u0627\u062f\u06c1\u060c \u062a\u0627\u0631\u06cc\u062e\u06cc \u062a\u0627\u0631\u06cc\u062e \u06a9\u0648 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u0646\u06d2 \u0645\u06cc\u06ba \u0645\u062f\u062f \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0633\u06d2 \u0628\u0631\u0627\u0624\u0632\u0631 \u0627\u0633 \u06a9\u06d2 \u0646\u0642\u0634\u06d2 \u0645\u06cc\u06ba \u0631\u06a9\u06be\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u0622\u067e \u0627\u0635\u0644 \u0645\u06cc\u06ba \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u06a9\u0648\u0634\u0634 \u06a9\u0631 \u0631\u06c1\u06d2 \u062a\u06be\u06d2\u06d4<\/p>\n<p>\u0648\u0642\u062a \u06a9\u06d2 \u0648\u0642\u0641\u06d2 \u06a9\u06cc \u062a\u0642\u0633\u06cc\u0645\u060c \u067e\u0691\u0648\u0633 \u0645\u06cc\u06ba \u062a\u0631\u0645\u06cc\u0645 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0648\u0632\u0646\u06cc \u062c\u06cc\u06a9\u0627\u0631\u0688 \u06a9\u0644\u0633\u0679\u0631\u0646\u06af\u060c \u06c1\u06cc\u0648\u0631\u0633\u0679\u06a9 \u0627\u0633\u06a9\u0648\u0631\u0646\u06af\u060c \u062d\u0642\u06cc\u0642\u06cc \u06a9\u0645\u067e\u0646\u06cc \u06a9\u06d2 \u0688\u06cc\u0679\u0627 \u067e\u0631 \u0645\u0628\u0646\u06cc AI \u0644\u06cc\u0628\u0644\u0646\u06af\u060c \u0646\u062a\u0627\u0626\u062c \u067e\u0631 \u0628\u0627\u062a \u0686\u06cc\u062a \u06a9\u06cc \u062a\u06c1\u06cc\u06ba\u060c \u0648\u063a\u06cc\u0631\u06c1\u06d4 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0627\u0646\u062c\u06cc\u0646\u0626\u0631\u0646\u06af \u0627\u06cc\u06a9 \u0642\u0633\u0645 \u06a9\u0627 \u062f\u0631\u062c\u06c1 \u0628\u0646\u062f\u06cc \u06a9\u0627 \u0646\u0638\u0627\u0645 \u06c1\u06d2 \u062c\u06c1\u0627\u06ba \u06c1\u0631 \u0642\u062f\u0645 \u0627\u067e\u0646\u06d2 \u0622\u067e \u0645\u06cc\u06ba \u0622\u0633\u0627\u0646 \u06c1\u06d2 \u0627\u0648\u0631 \u0642\u062f\u0631 \u0627\u0633 \u0633\u06d2 \u0622\u062a\u06cc \u06c1\u06d2 \u06a9\u06c1 \u0627\u0633\u06d2 \u06a9\u06cc\u0633\u06d2 \u0628\u0646\u0627\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4<\/p>\n<h2 id=\"heading-resources\">\u0648\u0633\u0627\u0626\u0644<\/h2>\n<h3 id=\"heading-source-code\">\u0633\u0648\u0631\u0633 \u06a9\u0648\u0688<\/h3>\n<ul>\n<li>\u0645\u06a9\u0645\u0644 \u0645\u0627\u062e\u0630 MIT \u0644\u0627\u0626\u0633\u0646\u0633 \u06a9\u06d2 \u062a\u062d\u062a GitHub \u067e\u0631 \u062f\u0633\u062a\u06cc\u0627\u0628 \u06c1\u06d2 \u0644\u06c1\u0630\u0627 \u0622\u067e \u0627\u0633\u06d2 \u0686\u0644\u0627 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0633\u06d2 \u067e\u0691\u06be \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0627\u067e\u0646\u06d2 \u0646\u06cc\u0648\u06cc\u06af\u06cc\u0634\u0646\u0644 \u0627\u0646\u062f\u0627\u0632 \u06a9\u06d2 \u0645\u0637\u0627\u0628\u0642 \u0627\u0633 \u06a9\u06cc \u0634\u06a9\u0644 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u06af\u0631 \u0622\u067e \u06a9\u0648 \u06cc\u06c1 \u06a9\u0627\u0631\u0622\u0645\u062f \u0644\u06af\u0627\u060c \u062a\u0648 \u0628\u0631\u0627\u06c1 \u06a9\u0631\u0645 \u0627\u0633\u06d2 \u0633\u062a\u0627\u0631\u06c1 \u06a9\u06cc \u062f\u0631\u062c\u06c1 \u0628\u0646\u062f\u06cc \u062f\u06cc\u0646\u06d2 \u067e\u0631 \u063a\u0648\u0631 \u06a9\u0631\u06cc\u06ba\u06d4<\/li>\n<\/ul>\n<h3 id=\"heading-core-documentation\">\u0627\u06c1\u0645 \u062f\u0633\u062a\u0627\u0648\u06cc\u0632<\/h3>\n<h3 id=\"heading-services-used\">\u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u0634\u062f\u06c1 \u062e\u062f\u0645\u0627\u062a<\/h3>\n<h3 id=\"heading-build-tooling\">\u0627\u0648\u0632\u0627\u0631 \u0628\u0646\u0627\u0626\u06cc\u06ba<\/h3>\n<ul>\n<li>\n<p>\u0648\u0627\u0626\u0679: \u0679\u0648\u0644\u0632 \u0627\u0648\u0631 \u0688\u0648\u06cc\u0644\u067e\u0645\u0646\u0679 \u0633\u0631\u0648\u0631 \u0628\u0646\u0627\u0626\u06cc\u06ba<\/p>\n<\/li>\n<li>\n<p>CRXJS Vite \u067e\u0644\u06af \u0627\u0646: \u06c1\u0627\u0679 \u0631\u06cc \u0644\u0648\u0688\u0646\u06af \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0645\u06cc\u0646\u06cc \u0641\u06cc\u0633\u0679 V3 \u0627\u06cc\u06a9\u0633\u0679\u06cc\u0646\u0634\u0646 \u0645\u0631\u062a\u0628 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>idb: \u0648\u0639\u062f\u06c1 \u067e\u0631 \u0645\u0628\u0646\u06cc IndexedDB \u0631\u06cc\u067e\u0631 \u0679\u0627\u0626\u067e \u06a9\u06cc\u0627 \u06af\u06cc\u0627\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0631\u06cc \u0627\u06cc\u06a9\u0679 \u0645\u0627\u0631\u06a9 \u0688\u0627\u0648\u0646: \u0627\u067e\u0646\u06d2 \u0627\u0633\u0633\u0679\u0646\u0679 \u0633\u06d2 \u0645\u0627\u0631\u06a9 \u0688\u0627\u0648\u0646 \u062c\u0648\u0627\u0628 \u067e\u06cc\u0634 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<\/ul>\n<h3 id=\"heading-debugging-tools\">\u0688\u06cc\u0628\u06af\u0646\u06af \u0679\u0648\u0644\u0632<\/h3>\n<ul>\n<li>\n<p>\u06a9\u0631\u0648\u0645 \u0627\u06cc\u06a9\u0633\u0679\u06cc\u0646\u0634\u0646 \u0633\u0631\u0648\u0633 \u0648\u0631\u06a9\u0631 \u0688\u06cc\u0648 \u0679\u0648\u0644\u0632: \u0631\u06cc\u0626\u0644 \u0679\u0627\u0626\u0645 \u06a9\u06cc\u067e\u0686\u0631 \u0644\u0627\u06af\u0632 \u0627\u0648\u0631 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u0627 \u0645\u0639\u0627\u0626\u0646\u06c1 <code>console.table<\/code> \u062d\u0633\u0627\u0628<\/p>\n<\/li>\n<li>\n<p>\u06a9\u06c1 <strong>\u062f\u0631\u062e\u0648\u0627\u0633\u062a \u2192 IndexedDB<\/strong> Chrome DevTools \u0645\u06cc\u06ba \u067e\u06cc\u0646\u0644\u0632: \u0628\u0631\u0627\u0624\u0632 \u06a9\u0631\u06cc\u06ba\u06d4 <code>raw_events<\/code>, <code>sessions<\/code>, <code>intent_threads<\/code>\u0627\u0648\u0631 <code>domain_brands<\/code> \u06c1\u0631 \u0642\u062f\u0645 \u06a9\u0648 \u062e\u0648\u062f \u0686\u06cc\u06a9 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2<\/p>\n<\/li>\n<\/ul>\n<h3 id=\"heading-further-reading\">\u0645\u0632\u06cc\u062f \u067e\u0691\u06be\u0646\u0627<\/h3>\n<ul>\n<li>\n<p>\u062c\u06cc\u06a9\u0627\u0631\u0688 \u0627\u0646\u0688\u06cc\u06a9\u0633: \u062a\u06be\u0631\u06cc\u0688 \u06a9\u0644\u0633\u0679\u0631\u0646\u06af \u06a9\u06d2 \u067e\u06cc\u0686\u06be\u06d2 \u0627\u06cc\u06a9 \u0645\u0645\u0627\u062b\u0644\u062a \u0633\u06cc\u0679 \u067e\u06cc\u0645\u0627\u0646\u06c1\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0639\u0648\u0627\u0645\u06cc \u0644\u0627\u062d\u0642\u06c1 \u0641\u06c1\u0631\u0633\u062a: \u0642\u0627\u0628\u0644 \u0631\u062c\u0633\u0679\u0631 \u0688\u0648\u0645\u06cc\u0646\u0632 \u0646\u06a9\u0627\u0644\u0646\u06d2 \u06a9\u0627 \u0645\u0646\u0627\u0633\u0628 \u0637\u0631\u06cc\u0642\u06c1\u060c \u0645\u0633\u062a\u0642\u0628\u0644 \u0645\u06cc\u06ba \u0628\u06c1\u062a\u0631\u06cc \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0630\u06a9\u0631 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<p>\u0627\u06af\u0631 \u0622\u067e \u06a9\u0648 \u06cc\u06c1 \u0679\u06cc\u0648\u0679\u0648\u0631\u06cc\u0644 \u06a9\u0627\u0631\u0622\u0645\u062f \u0645\u0639\u0644\u0648\u0645 \u06c1\u0648\u0627 \u062a\u0648 \u0628\u0644\u0627 \u062c\u06be\u062c\u06a9 \u062f\u0648\u0633\u0631\u0648\u06ba \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u0633 \u06a9\u0627 \u0627\u0634\u062a\u0631\u0627\u06a9 \u06a9\u0631\u06cc\u06ba \u062c\u0648 \u0641\u0627\u0626\u062f\u06c1 \u0627\u0679\u06be\u0627 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06c1\u0645 \u0648\u0627\u0642\u0639\u06cc \u0622\u067e \u06a9\u06d2 \u062a\u0628\u0635\u0631\u06d2 \u06a9\u06cc \u062a\u0639\u0631\u06cc\u0641 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0622\u067e X \u067e\u0631 @wani_shola \u06a9\u0627 \u0630\u06a9\u0631 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u06cc\u0627 LinkedIn \u067e\u0631 \u0645\u062c\u06be \u0633\u06d2 \u0631\u0627\u0628\u0637\u06c1 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>\u0622\u067e \u06a9\u0627 \u0628\u0631\u0627\u0624\u0632\u0631 \u06c1\u0631 \u0648\u06c1 \u0635\u0641\u062d\u06c1 \u06cc\u0627\u062f \u0631\u06a9\u06be\u062a\u0627 \u06c1\u06d2 \u062c\u0633\u06d2 \u0622\u067e \u0646\u06d2 \u06a9\u0628\u06be\u06cc \u06a9\u06be\u0648\u0644\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u0627\u0633\u06d2 \u06a9\u0686\u06be \u0645\u0639\u0644\u0648\u0645 \u0646\u06c1\u06cc\u06ba \u06a9\u06c1 \u0622\u067e \u0646\u06d2 \u0627\u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0648\u06ba \u06a9\u06be\u0648\u0644\u0627\u06d4 \u0627\u06af\u0631 \u0622\u067e \u062a\u06cc\u0646 \u062f\u0646 \u062a\u06a9 \u062f\u0631\u062c\u0646 \u0628\u06be\u0631 \u0679\u06cc\u0628\u0632 \u067e\u0631 \u0645\u0648\u062c\u0648\u062f \u0646\u0648\u0679 \u0628\u06a9 \u06a9\u0627 \u0645\u0648\u0627\u0632\u0646\u06c1 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0645\u0634\u063a\u0648\u0644 \u06c1\u0648 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u06c1\u0641\u062a\u06d2 \u0628\u0639\u062f \u0648\u0627\u067e\u0633 \u0622\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0622\u067e [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":25616,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[1],"tags":[],"class_list":["post-25615","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog"],"_links":{"self":[{"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/posts\/25615","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/comments?post=25615"}],"version-history":[{"count":1,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/posts\/25615\/revisions"}],"predecessor-version":[{"id":25617,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/posts\/25615\/revisions\/25617"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/media\/25616"}],"wp:attachment":[{"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/media?parent=25615"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/categories?post=25615"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/tags?post=25615"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}