# Result — 002 Planning > اکشن مرتبط: [`action/002_action_planning.md`](../action/002_action_planning.md) > تاریخ اجرا: 2026-06-09 --- ## هدف این جلسه خواندن پروژه، فهمیدن ساختار، و پیاده‌سازی گام اول MVP: اتصال افزونه‌ی Chrome به یک سرور پایتون بیرون مرورگر از طریق WebSocket. --- ## تصمیم‌های کلیدی که گرفته شد ### معماری — چرا extension به‌عنوان WS client؟ افزونه نمی‌تواند خودش سرور باشد (MV3 سرویس‌ورکر TCP port نمی‌تواند باز کند). پس **افزونه client است و پایتون server** — افزونه به `ws://127.0.0.1:8765` وصل می‌شود. همچنین WS باید از service worker باز شود، نه content script؛ چون content script تابع CSP صفحه‌ی گوگل میت است و `connect-src` اتصال را بلاک می‌کند. ### نقطه‌ی hook در کد افزونه `setSpeaker()` در `storage.js` — هر پاراگراف caption نهایی از این تابع رد می‌شود. یک `chrome.runtime.sendMessage` کوچک به آن اضافه شد که background را خبر می‌کند. ### venv برای پایتون تصمیم گرفته شد پایتون داخل `.venv` اجرا شود تا سیستم کثیف نشود. --- ## چه چیزی ساخته شد | فایل | نوع | کار | |------|-----|-----| | `bridge/server.py` | جدید | WebSocket server پایتون روی `127.0.0.1:8765` | | `bridge/requirements.txt` | جدید | فقط `websockets>=12.0` | | `bridge/.gitignore` | جدید | `.venv/` و `transcripts/` از git خارج | | `bridge/README.md` | جدید | راهنمای اجرا با venv | | `bridge/_smoke_test.py` | جدید | کلاینت تستی بدون Chrome | | `bridge/.venv/` | جدید | محیط ایزوله پایتون | | `google-meet-transcripts-extension/bridge.js` | جدید | WS client داخل service worker | | `login.js` | ویرایش | اضافه شدن `importScripts("bridge.js")` | | `storage.js` | ویرایش | `setSpeaker` حالا `TRANSCRIPT_UPDATE` می‌فرستد | | `manifest.json` | ویرایش | `ws://127.0.0.1:8765/*` به `host_permissions` اضافه شد | --- ## تست انجام شده سرور پایتون با `_smoke_test.py` end-to-end تست شد: - PING → PONG ✅ - سه `TRANSCRIPT_UPDATE` → سه ACK ✅ - فایل `transcripts/meeting-abc123.txt` با متن فارسی درست ذخیره شد ✅ تست با Chrome واقعی هنوز انجام نشده (نیاز به Reload افزونه و یک جلسه‌ی Meet). --- ## وضعیت چک‌لیست اصلی (از action) - [x] حذف کدهای laxis — **انجام شد** (اجرای ۲۰۲۶-۰۶-۱۰، پایین را ببین) - [x] لوگوی اختصاصی — **انجام شد** (لوگوی جدید جایگزین شد) - [x] گرفتن caption از افزونه — گام ۱ (اتصال) انجام شد - [x] سرویس MCP روی پورت — **انجام شد** (روی همان `server.py`) - [ ] تست میدانی با Chrome واقعی — باقی‌مانده (نیاز به مرورگر و یک جلسه‌ی Meet) --- ## اجرای دوم — پاک‌سازی laxis + MCP + لوگو (۲۰۲۶-۰۶-۱۰) ### پاک‌سازی laxis (هیچ داده‌ای دیگر بیرون نمی‌رود) - `analytics.js`: کاملاً خالی شد (از قبل کامنت‌شده و مرده بود؛ در manifest هم لود نمی‌شد). - `login.js` (service worker): بازنویسی شد — حذف `tabs.onRemoved` (که transcript را آپلود می‌کرد)، حذف `onMessageExternal` (دریافت توکن) و `getTopics`. فقط import ها + نگه‌داشتن وضعیت لوکال ماند. - `runtime.js` (content script): حذف فراخوانی `addRemindLogin()` و کل listener دریافت توکن/fetch. - `meetingInfo.js`: `checkToken` و `renewToken` با `return;` در ابتدا خنثی شدند؛ آپلود پایان جلسه (`Export2App` + باز کردن `domainUrl/transcript`) حذف شد. - `transcript.js`: `Export2App` بلافاصله reject می‌کند (آپلود ابری قطع)، `getTopics` خنثی شد، `addRemindLogin` خالی شد، منوی دانلود از حالت پیش‌فرضِ «app/cloud» به دانلود محلی `txt` تغییر کرد. - `panel/main.js`: لینک لوگو → `domainUrl/login` در هر سه جا حذف شد؛ متن‌های برند «Laxis…» حذف شدند. - `manifest.json`: `update_url` فروشگاه حذف شد (که افزونه با ID لاکسیس آپدیت نشود)؛ name/description به نسخه‌ی محلی و بدون cloud تغییر کرد. ### MCP روی server.py سرور حالا در یک پراسس هم WebSocket (برای افزونه) و هم MCP stdio (برای Claude) را اجرا می‌کند و حافظه‌ی `sessions` را share می‌کنند. ابزارها: `list_sessions`، `get_transcript`، `get_latest_transcript` و resource با الگوی `transcript://{session_id}`. کانفیگ Claude Desktop در `bridge/README.md`. ### درس‌آموخته‌ها - **stdout برای MCP رزرو است:** همه‌ی `print` ها به stderr منتقل شدند، وگرنه استریم JSON-RPC خراب می‌شود. برای تست دستیِ WebSocket باید از `python server.py --ws-only` استفاده کرد. - **کد افزونه minified است:** برای فایل‌های فشرده (`meetingInfo.js`) به‌جای حذفِ بدنه‌ها، با `return;` در ابتدای تابع خنثی‌سازی شد (کم‌ریسک‌تر). کدِ مرده باقی می‌ماند ولی هرگز اجرا نمی‌شود. - **یک رشته‌ی غیرفعال باقی‌ست:** متنِ «Autosave to Laxis cloud…» در `displayGoogleMeetQuota` (`transcript.js`) داخل کدِ مرده مانده — هرگز نمایش داده نمی‌شود چون فراخوان‌هایش خنثی‌اند. ### تأیید (validation) - syntax همه‌ی فایل‌های JS با `node --check` پاس شد. - منطق `server.py` با AST + یک smoke test واقعیِ WebSocket (PONG/ACK + ذخیره‌ی صحیح فارسی) تأیید شد. - ابزار/resource های MCP با `mcp` SDK ساخته و اجرا شدند (`get_latest_transcript` متن را درست برگرداند). ### باقی‌مانده برای تو تست میدانی: venv را بساز/فعال کن، `python server.py --ws-only` را اجرا کن، افزونه را در `chrome://extensions` **Reload** کن، در یک Meet واقعی caption را روشن کن و خروجی را در `bridge/transcripts/` ببین. بعد کانفیگ MCP را به Claude Desktop اضافه کن.