Web interfaces

رابط کاربری کنترل

Edit source

رابط کاربری Control یک اپلیکیشن تک‌صفحه‌ای کوچک با Vite + Lit است که توسط Gateway ارائه می‌شود:

  • پیش‌فرض: http://<host>:18789/
  • پیشوند اختیاری: gateway.controlUi.basePath را تنظیم کنید (مثلاً /openclaw)

این رابط مستقیماً با Gateway WebSocket روی همان پورت صحبت می‌کند.

باز کردن سریع (محلی)

اگر Gateway روی همان رایانه در حال اجراست، باز کنید:

اگر صفحه بارگذاری نشد، ابتدا Gateway را اجرا کنید: openclaw gateway.

احراز هویت هنگام دست‌دهی WebSocket از طریق موارد زیر ارائه می‌شود:

  • connect.params.auth.token
  • connect.params.auth.password
  • هدرهای هویت Tailscale Serve وقتی gateway.auth.allowTailscale: true است
  • هدرهای هویت پراکسی مورد اعتماد وقتی gateway.auth.mode: "trusted-proxy" است

پنل تنظیمات داشبورد یک توکن را برای نشست فعلی تب مرورگر و URL انتخاب‌شده Gateway نگه می‌دارد؛ گذرواژه‌ها ذخیره نمی‌شوند. راه‌اندازی اولیه معمولاً در اولین اتصال یک توکن Gateway برای احراز هویت با راز مشترک ایجاد می‌کند، اما وقتی gateway.auth.mode برابر "password" باشد، احراز هویت با گذرواژه هم کار می‌کند.

جفت‌سازی دستگاه (اتصال اول)

وقتی از یک مرورگر یا دستگاه جدید به رابط کاربری Control وصل می‌شوید، Gateway معمولاً به تأیید یک‌باره جفت‌سازی نیاز دارد. این یک اقدام امنیتی برای جلوگیری از دسترسی غیرمجاز است.

چیزی که خواهید دید: "disconnected (1008): pairing required"

  • فهرست کردن درخواست‌های در انتظار

    bash
    openclaw devices list
  • تأیید با شناسه درخواست

    bash
    openclaw devices approve <requestId>
  • اگر مرورگر با جزئیات احراز هویت تغییریافته دوباره برای جفت‌سازی تلاش کند (نقش/دامنه‌ها/کلید عمومی)، درخواست در انتظار قبلی جایگزین می‌شود و یک requestId جدید ایجاد می‌گردد. پیش از تأیید، دوباره openclaw devices list را اجرا کنید.

    اگر مرورگر از قبل جفت شده باشد و آن را از دسترسی خواندن به دسترسی نوشتن/مدیریت تغییر دهید، این به‌عنوان ارتقای تأیید در نظر گرفته می‌شود، نه اتصال دوباره بی‌صدا. OpenClaw تأیید قدیمی را فعال نگه می‌دارد، اتصال دوباره با دامنه گسترده‌تر را مسدود می‌کند و از شما می‌خواهد مجموعه دامنه جدید را صراحتاً تأیید کنید.

    پس از تأیید، دستگاه به خاطر سپرده می‌شود و نیازی به تأیید دوباره ندارد مگر اینکه آن را با openclaw devices revoke --device <id> --role <role> لغو کنید. برای چرخش توکن و لغو، CLI دستگاه‌ها را ببینید.

    هویت شخصی (محلیِ مرورگر)

    رابط کاربری Control از یک هویت شخصی به‌ازای هر مرورگر (نام نمایشی و آواتار) پشتیبانی می‌کند که برای انتساب در نشست‌های مشترک به پیام‌های خروجی پیوست می‌شود. این هویت در فضای ذخیره‌سازی مرورگر زندگی می‌کند، به پروفایل مرورگر فعلی محدود است، و به دستگاه‌های دیگر همگام‌سازی نمی‌شود یا در سمت سرور فراتر از فراداده معمول نویسندگی رونوشت روی پیام‌هایی که واقعاً ارسال می‌کنید پایدار نمی‌ماند. پاک کردن داده‌های سایت یا تغییر مرورگر آن را به حالت خالی بازنشانی می‌کند.

    همین الگوی محلیِ مرورگر برای بازنویسی آواتار دستیار هم اعمال می‌شود. آواتارهای بارگذاری‌شده دستیار فقط در مرورگر محلی روی هویت حل‌شده توسط Gateway قرار می‌گیرند و هرگز از مسیر config.patch رفت‌وبرگشت نمی‌کنند. فیلد پیکربندی مشترک ui.assistant.avatar همچنان برای کلاینت‌های غیر UI که فیلد را مستقیماً می‌نویسند در دسترس است (مانند Gatewayهای اسکریپتی یا داشبوردهای سفارشی).

    نقطه پایانی پیکربندی زمان اجرا

    رابط کاربری Control تنظیمات زمان اجرای خود را از /__openclaw/control-ui-config.json دریافت می‌کند. آن نقطه پایانی با همان احراز هویت Gateway مانند بقیه سطح HTTP محافظت می‌شود: مرورگرهای احراز هویت‌نشده نمی‌توانند آن را دریافت کنند، و دریافت موفق به یک توکن/گذرواژه Gateway از پیش معتبر، هویت Tailscale Serve، یا هویت پراکسی مورد اعتماد نیاز دارد.

    پشتیبانی زبان

    رابط کاربری Control می‌تواند در اولین بارگذاری، خود را بر اساس زبان مرورگر شما محلی‌سازی کند. برای تغییر آن در آینده، نمای کلی -> دسترسی Gateway -> زبان را باز کنید. انتخابگر زبان در کارت دسترسی Gateway قرار دارد، نه زیر Appearance.

    • زبان‌های پشتیبانی‌شده: en, zh-CN, zh-TW, pt-BR, de, es, ja-JP, ko, fr, ar, it, tr, uk, id, pl, th, vi, nl, fa
    • ترجمه‌های غیرانگلیسی به‌صورت تنبل در مرورگر بارگذاری می‌شوند.
    • زبان انتخاب‌شده در فضای ذخیره‌سازی مرورگر ذخیره می‌شود و در بازدیدهای آینده دوباره استفاده می‌گردد.
    • کلیدهای ترجمه مفقود به انگلیسی برمی‌گردند.

    ترجمه‌های مستندات برای همان مجموعه زبان‌های غیرانگلیسی تولید می‌شوند، اما انتخابگر زبان داخلی سایت مستندات در Mintlify محدود به کدهای زبانی است که Mintlify می‌پذیرد. مستندات تایلندی (th) و فارسی (fa) همچنان در مخزن انتشار تولید می‌شوند؛ ممکن است تا زمانی که Mintlify از این کدها پشتیبانی نکند، در آن انتخابگر ظاهر نشوند.

    تم‌های ظاهری

    پنل Appearance تم‌های داخلی Claw، Knot و Dash را نگه می‌دارد، به‌علاوه یک جایگاه واردسازی tweakcn محلیِ مرورگر. برای وارد کردن یک تم، ویرایشگر tweakcn را باز کنید، یک تم را انتخاب یا ایجاد کنید، روی Share کلیک کنید، و لینک تم کپی‌شده را در Appearance بچسبانید. واردکننده همچنین URLهای رجیستری https://tweakcn.com/r/themes/<id>، URLهای ویرایشگر مانند https://tweakcn.com/editor/theme?theme=amethyst-haze، مسیرهای نسبی /themes/<id>، شناسه‌های خام تم، و نام‌های تم پیش‌فرض مانند amethyst-haze را می‌پذیرد.

    تم‌های واردشده فقط در پروفایل مرورگر فعلی ذخیره می‌شوند. آن‌ها در پیکربندی Gateway نوشته نمی‌شوند و بین دستگاه‌ها همگام‌سازی نمی‌گردند. جایگزین کردن تم واردشده همان یک جایگاه محلی را به‌روزرسانی می‌کند؛ پاک کردن آن، اگر تم واردشده انتخاب شده باشد، تم فعال را به Claw برمی‌گرداند.

    اکنون چه کارهایی می‌تواند انجام دهد

    گفت‌وگو و صحبت
    • گفت‌وگو با مدل از طریق Gateway WS (chat.history, chat.send, chat.abort, chat.inject).
    • بازخوانی‌های تاریخچه گفت‌وگو یک پنجره اخیر محدود با سقف متن به‌ازای هر پیام درخواست می‌کنند تا نشست‌های بزرگ پیش از قابل‌استفاده شدن گفت‌وگو مرورگر را مجبور به رندر کردن کل بار رونوشت نکنند.
    • صحبت از طریق نشست‌های بلادرنگ مرورگر. OpenAI از WebRTC مستقیم استفاده می‌کند، Google Live از یک توکن مرورگر یک‌بارمصرف محدود روی WebSocket استفاده می‌کند، و pluginهای صدای بلادرنگ فقط-بک‌اند از ترابری رله Gateway استفاده می‌کنند. نشست‌های ارائه‌دهنده تحت مالکیت کلاینت با talk.client.create شروع می‌شوند؛ نشست‌های رله Gateway با talk.session.create شروع می‌شوند. رله اعتبارنامه‌های ارائه‌دهنده را روی Gateway نگه می‌دارد در حالی که مرورگر PCM میکروفون را از طریق talk.session.appendAudio استریم می‌کند و فراخوانی‌های ابزار ارائه‌دهنده openclaw_agent_consult را از طریق talk.client.toolCall برای سیاست Gateway و مدل OpenClaw بزرگ‌ترِ پیکربندی‌شده ارسال می‌کند.
    • استریم فراخوانی‌های ابزار + کارت‌های خروجی زنده ابزار در Chat (رویدادهای عامل).
    کانال‌ها، نمونه‌ها، نشست‌ها، رؤیاها
    • کانال‌ها: وضعیت کانال‌های داخلی به‌علاوه کانال‌های plugin بسته‌بندی‌شده/خارجی، ورود QR، و پیکربندی به‌ازای هر کانال (channels.status, web.login.*, config.patch).
    • بازخوانی‌های کاوش کانال، snapshot قبلی را تا پایان بررسی‌های کند ارائه‌دهنده قابل مشاهده نگه می‌دارند، و وقتی یک کاوش یا ممیزی از بودجه UI خود فراتر برود، snapshotهای جزئی برچسب‌گذاری می‌شوند.
    • نمونه‌ها: فهرست حضور + بازخوانی (system-presence).
    • نشست‌ها: به‌طور پیش‌فرض نشست‌های عامل پیکربندی‌شده را فهرست می‌کند، از کلیدهای نشست عامل پیکربندی‌نشده کهنه fallback می‌کند، و بازنویسی‌های مدل/تفکر/سریع/پرگو/ردیابی/استدلال را به‌ازای هر نشست اعمال می‌کند (sessions.list, sessions.patch).
    • رؤیاها: وضعیت Dreaming، کلید فعال/غیرفعال، و خواننده Dream Diary (doctor.memory.status, doctor.memory.dreamDiary, config.patch).
    Cron، Skills، گره‌ها، تأییدیه‌های اجرا
    • کارهای Cron: فهرست/افزودن/ویرایش/اجرا/فعال‌سازی/غیرفعال‌سازی + تاریخچه اجرا (cron.*).
    • Skills: وضعیت، فعال/غیرفعال، نصب، به‌روزرسانی‌های کلید API (skills.*).
    • گره‌ها: فهرست + قابلیت‌ها (node.list).
    • تأییدیه‌های اجرا: ویرایش allowlistهای Gateway یا گره + سیاست پرسش برای exec host=gateway/node (exec.approvals.*).
    پیکربندی
    • مشاهده/ویرایش ~/.openclaw/openclaw.json (config.get, config.set).
    • اعمال + راه‌اندازی دوباره با اعتبارسنجی (config.apply) و بیدار کردن آخرین نشست فعال.
    • نوشتن‌ها شامل یک محافظ هش پایه هستند تا از بازنویسی و از بین بردن ویرایش‌های هم‌زمان جلوگیری شود.
    • نوشتن‌ها (config.set/config.apply/config.patch) پیش از اجرا، حل SecretRef فعال را برای ارجاع‌های موجود در بار پیکربندی ارسالی بررسی می‌کنند؛ ارجاع‌های ارسالی فعالِ حل‌نشده پیش از نوشتن رد می‌شوند.
    • رندر schema + فرم (config.schema / config.schema.lookup، شامل title / description فیلد، راهنماهای UI منطبق، خلاصه‌های فرزند بلافاصله، فراداده مستندات روی گره‌های آبجکت/ wildcard / آرایه / ترکیب تودرتو، به‌علاوه schemaهای plugin + کانال وقتی در دسترس باشند)؛ ویرایشگر JSON خام فقط وقتی snapshot رفت‌وبرگشت خام امنی داشته باشد در دسترس است.
    • اگر یک snapshot نتواند متن خام را با ایمنی رفت‌وبرگشت کند، رابط کاربری Control حالت Form را اجباری می‌کند و حالت Raw را برای آن snapshot غیرفعال می‌سازد.
    • گزینه "Reset to saved" در ویرایشگر JSON خام، به‌جای رندر دوباره یک snapshot تخت‌شده، شکل خام‌نوشته‌شده را حفظ می‌کند (قالب‌بندی، نظرها، چینش $include)؛ بنابراین وقتی snapshot بتواند با ایمنی رفت‌وبرگشت کند، ویرایش‌های خارجی از بازنشانی جان سالم به‌در می‌برند.
    • مقادیر آبجکت SecretRef ساختاریافته در ورودی‌های متنی فرم به‌صورت فقط‌خواندنی رندر می‌شوند تا از خراب شدن تصادفی آبجکت به رشته جلوگیری شود.
    اشکال‌زدایی، گزارش‌ها، به‌روزرسانی
    • اشکال‌زدایی: snapshotهای وضعیت/سلامت/مدل‌ها + گزارش رویداد + فراخوانی‌های دستی RPC (status, health, models.list).
    • گزارش رویداد شامل زمان‌بندی‌های بازخوانی/RPC رابط کاربری Control، زمان‌بندی‌های رندر کند گفت‌وگو/پیکربندی، و ورودی‌های پاسخ‌گویی مرورگر برای فریم‌های انیمیشن طولانی یا taskهای طولانی است، وقتی مرورگر آن نوع ورودی‌های PerformanceObserver را ارائه کند.
    • گزارش‌ها: tail زنده گزارش‌های فایل Gateway با فیلتر/خروجی گرفتن (logs.tail).
    • به‌روزرسانی: اجرای به‌روزرسانی بسته/git + راه‌اندازی دوباره (update.run) با گزارش راه‌اندازی دوباره، سپس نظرسنجی update.status پس از اتصال دوباره برای تأیید نسخه Gateway در حال اجرا.
    نکات پنل کارهای Cron
    • برای کارهای ایزوله، پیش‌فرض تحویل روی اعلام خلاصه است. اگر اجرای فقط داخلی می‌خواهید، می‌توانید آن را به none تغییر دهید.
    • وقتی announce انتخاب شده باشد، فیلدهای کانال/هدف ظاهر می‌شوند.
    • حالت Webhook از delivery.mode = "webhook" با delivery.to تنظیم‌شده روی یک URL معتبر Webhook از نوع HTTP(S) استفاده می‌کند.
    • برای کارهای نشست اصلی، حالت‌های تحویل webhook و none در دسترس هستند.
    • کنترل‌های ویرایش پیشرفته شامل حذف پس از اجرا، پاک کردن بازنویسی عامل، گزینه‌های cron دقیق/پراکنده، بازنویسی‌های مدل/تفکر عامل، و کلیدهای تحویل best-effort هستند.
    • اعتبارسنجی فرم به‌صورت درون‌خطی با خطاهای سطح فیلد است؛ مقادیر نامعتبر دکمه ذخیره را تا زمان اصلاح غیرفعال می‌کنند.
    • برای ارسال یک توکن bearer اختصاصی، cron.webhookToken را تنظیم کنید؛ اگر حذف شود، webhook بدون هدر احراز هویت ارسال می‌شود.
    • fallback منسوخ: کارهای قدیمی ذخیره‌شده با notify: true همچنان می‌توانند تا زمان مهاجرت از cron.webhook استفاده کنند.

    رفتار گفت‌وگو

    معنای ارسال و تاریخچه
    • chat.send غیرمسدودکننده است: بلافاصله با { runId, status: "started" } تأیید می‌کند و پاسخ از طریق رویدادهای chat جریان می‌یابد.
    • بارگذاری‌های چت تصویرها به‌علاوه فایل‌های غیر ویدیویی را می‌پذیرند. تصویرها مسیر تصویر بومی را نگه می‌دارند؛ فایل‌های دیگر به‌عنوان رسانه مدیریت‌شده ذخیره می‌شوند و در تاریخچه به‌صورت پیوندهای پیوست نمایش داده می‌شوند.
    • ارسال دوباره با همان idempotencyKey هنگام اجرا { status: "in_flight" } و پس از تکمیل { status: "ok" } را برمی‌گرداند.
    • پاسخ‌های chat.history برای ایمنی UI از نظر اندازه محدود می‌شوند. وقتی ورودی‌های رونوشت بیش از حد بزرگ باشند، Gateway ممکن است فیلدهای متنی طولانی را کوتاه کند، بلوک‌های فراداده سنگین را حذف کند، و پیام‌های بیش‌ازحد بزرگ را با یک جانگهدار ([chat.history omitted: message too large]) جایگزین کند.
    • تصویرهای دستیار/تولیدشده به‌عنوان ارجاع‌های رسانه مدیریت‌شده پایدار می‌شوند و از طریق URLهای رسانه احرازهویت‌شده Gateway دوباره ارائه می‌شوند، بنابراین بارگذاری‌های مجدد به باقی‌ماندن payloadهای تصویر base64 خام در پاسخ تاریخچه چت وابسته نیستند.
    • هنگام رندر کردن chat.history، UI کنترل برچسب‌های دستور درون‌خطی صرفاً نمایشی را از متن قابل‌مشاهده دستیار حذف می‌کند (برای مثال [[reply_to_*]] و [[audio_as_voice]])، payloadهای XML فراخوانی ابزار در متن ساده (از جمله <tool_call>...</tool_call>، <function_call>...</function_call>، <tool_calls>...</tool_calls>، <function_calls>...</function_calls>، و بلوک‌های کوتاه‌شده فراخوانی ابزار)، و توکن‌های کنترل مدل ASCII/تمام‌عرض نشت‌کرده را حذف می‌کند، و ورودی‌های دستیار را که کل متن قابل‌مشاهده‌شان فقط توکن خاموش دقیق NO_REPLY / no_reply یا توکن تأیید Heartbeat یعنی HEARTBEAT_OK است حذف می‌کند.
    • در طول یک ارسال فعال و تازه‌سازی نهایی تاریخچه، نمای چت پیام‌های خوش‌بینانه محلی کاربر/دستیار را قابل‌مشاهده نگه می‌دارد اگر chat.history برای مدتی کوتاه یک snapshot قدیمی‌تر برگرداند؛ رونوشت مرجع پس از آنکه تاریخچه Gateway به‌روز شد، آن پیام‌های محلی را جایگزین می‌کند.
    • رویدادهای زنده chat وضعیت تحویل هستند، درحالی‌که chat.history از رونوشت ماندگار نشست بازسازی می‌شود. پس از رویدادهای نهایی ابزار، UI کنترل تاریخچه را دوباره بارگذاری می‌کند و فقط یک دنباله خوش‌بینانه کوچک را ادغام می‌کند؛ مرز رونوشت در WebChat مستند شده است.
    • chat.inject یک یادداشت دستیار را به رونوشت نشست اضافه می‌کند و یک رویداد chat را برای به‌روزرسانی‌های صرفاً UI پخش می‌کند (بدون اجرای عامل، بدون تحویل کانال).
    • سربرگ چت فیلتر عامل را پیش از انتخابگر نشست نشان می‌دهد، و انتخابگر نشست بر اساس عامل انتخاب‌شده محدود می‌شود. تغییر عامل‌ها فقط نشست‌های وابسته به آن عامل را نشان می‌دهد و وقتی هنوز هیچ نشست داشبورد ذخیره‌شده‌ای ندارد، به نشست اصلی آن عامل برمی‌گردد.
    • در عرض‌های دسکتاپ، کنترل‌های چت در یک ردیف فشرده می‌مانند و هنگام پیمایش به پایین رونوشت جمع می‌شوند؛ پیمایش به بالا، بازگشت به بالای صفحه، یا رسیدن به پایین، کنترل‌ها را بازیابی می‌کند.
    • پیام‌های متنی تکراری پیاپی به‌صورت یک حباب با نشان شمارش رندر می‌شوند. پیام‌هایی که تصویر، پیوست، خروجی ابزار، یا پیش‌نمایش canvas دارند جمع نمی‌شوند.
    • انتخابگرهای مدل و تفکر در سربرگ چت نشست فعال را بلافاصله از طریق sessions.patch وصله می‌کنند؛ آن‌ها overrideهای پایدار نشست هستند، نه گزینه‌های ارسال فقط برای یک نوبت.
    • اگر هنگام ذخیره شدن تغییر انتخابگر مدل برای همان نشست پیامی بفرستید، composer پیش از فراخوانی chat.send منتظر وصله آن نشست می‌ماند تا ارسال از مدل انتخاب‌شده استفاده کند.
    • تایپ کردن /new در UI کنترل همان نشست تازه داشبورد New Chat را ایجاد می‌کند و به آن جابه‌جا می‌شود، مگر وقتی session.dmScope: "main" پیکربندی شده باشد و والد فعلی نشست اصلی عامل باشد؛ در آن حالت، نشست اصلی را درجا بازنشانی می‌کند. تایپ کردن /reset بازنشانی درجای صریح Gateway را برای نشست فعلی نگه می‌دارد.
    • انتخابگر مدل چت نمای مدل پیکربندی‌شده Gateway را درخواست می‌کند. اگر agents.defaults.models موجود باشد، آن فهرست مجاز انتخابگر را هدایت می‌کند، از جمله ورودی‌های provider/* که کاتالوگ‌های محدود به provider را پویا نگه می‌دارند. در غیر این صورت انتخابگر ورودی‌های صریح models.providers.*.models به‌علاوه providerهایی با احراز هویت قابل‌استفاده را نشان می‌دهد. کاتالوگ کامل از طریق RPC اشکال‌زدایی models.list با view: "all" همچنان در دسترس است.
    • وقتی گزارش‌های تازه مصرف نشست Gateway شامل توکن‌های زمینه فعلی باشند، ناحیه composer چت یک نشانگر فشرده مصرف زمینه را نشان می‌دهد. در فشار بالای زمینه به سبک هشدار تغییر می‌کند و، در سطوح پیشنهادی Compaction، یک دکمه فشرده نشان می‌دهد که مسیر عادی Compaction نشست را اجرا می‌کند. snapshotهای قدیمی توکن پنهان می‌شوند تا زمانی که Gateway دوباره مصرف تازه را گزارش کند.
    حالت گفت‌وگو (بی‌درنگ مرورگر)

    حالت گفت‌وگو از یک provider صدای بی‌درنگ ثبت‌شده استفاده می‌کند. OpenAI را با talk.realtime.provider: "openai" به‌علاوه یکی از talk.realtime.providers.openai.apiKey، OPENAI_API_KEY، یا پروفایل OAuth openai-codex پیکربندی کنید؛ Google را با talk.realtime.provider: "google" به‌علاوه talk.realtime.providers.google.apiKey پیکربندی کنید. مرورگر هرگز یک کلید API استاندارد provider دریافت نمی‌کند. OpenAI یک secret موقت کلاینت Realtime برای WebRTC دریافت می‌کند. Google Live یک توکن احراز هویت Live API محدود و یک‌بارمصرف برای یک نشست WebSocket مرورگر دریافت می‌کند، همراه با دستورالعمل‌ها و اعلان‌های ابزار که توسط Gateway در توکن قفل شده‌اند. providerهایی که فقط یک پل بی‌درنگ backend ارائه می‌کنند از مسیر انتقال relay Gateway عبور می‌کنند، بنابراین credentials و socketهای فروشنده در سمت سرور می‌مانند، درحالی‌که صدای مرورگر از طریق RPCهای احرازهویت‌شده Gateway جابه‌جا می‌شود. پرامپت نشست Realtime توسط Gateway ساخته می‌شود؛ talk.client.create overrideهای دستورالعمل ارائه‌شده از سوی فراخواننده را نمی‌پذیرد.

    composer چت یک دکمه گزینه‌های گفت‌وگو کنار دکمه شروع/توقف گفت‌وگو دارد. گزینه‌ها روی نشست گفت‌وگوی بعدی اعمال می‌شوند و می‌توانند provider، انتقال، مدل، صدا، میزان تلاش استدلال، آستانه VAD، مدت سکوت، و padding پیشوند را override کنند. وقتی گزینه‌ای خالی باشد، Gateway در صورت وجود از پیش‌فرض‌های پیکربندی‌شده یا از پیش‌فرض provider استفاده می‌کند. انتخاب relay Gateway مسیر relay backend را اجباری می‌کند؛ انتخاب WebRTC نشست را در مالکیت کلاینت نگه می‌دارد و اگر provider نتواند نشست مرورگر بسازد، به‌جای fallback خاموش به relay، شکست می‌خورد.

    در composer چت، کنترل گفت‌وگو دکمه موج‌ها کنار دکمه دیکته میکروفون است. وقتی گفت‌وگو شروع می‌شود، ردیف وضعیت composer ابتدا Connecting Talk...، سپس هنگام اتصال صدا Talk live، یا هنگام مشورت یک فراخوانی ابزار بی‌درنگ با مدل بزرگ‌تر پیکربندی‌شده از طریق talk.client.toolCall، Asking OpenClaw... را نشان می‌دهد.

    smoke زنده نگه‌دارنده: OPENAI_API_KEY=... GEMINI_API_KEY=... node --import tsx scripts/dev/realtime-talk-live-smoke.ts پل WebSocket backend OpenAI، تبادل SDP مرورگر WebRTC OpenAI، راه‌اندازی WebSocket مرورگر با توکن محدود Google Live، و آداپتور مرورگر relay Gateway را با رسانه میکروفون جعلی تأیید می‌کند. این دستور فقط وضعیت provider را چاپ می‌کند و secretها را log نمی‌کند.

    توقف و لغو
    • روی توقف کلیک کنید (chat.abort را فراخوانی می‌کند).
    • وقتی یک اجرا فعال است، پیگیری‌های عادی در صف قرار می‌گیرند. روی هدایت در یک پیام صف‌شده کلیک کنید تا آن پیگیری را به نوبت در حال اجرا تزریق کنید.
    • برای لغو خارج از باند، /stop را تایپ کنید (یا عبارت‌های لغو مستقل مانند stop، stop action، stop run، stop openclaw، please stop).
    • chat.abort از { sessionKey } (بدون runId) برای لغو همه اجراهای فعال آن نشست پشتیبانی می‌کند.
    نگهداری بخشی پس از لغو
    • وقتی یک اجرا لغو می‌شود، متن بخشی دستیار هنوز می‌تواند در UI نمایش داده شود.
    • Gateway وقتی خروجی bufferشده وجود داشته باشد، متن بخشی لغوشده دستیار را در تاریخچه رونوشت پایدار می‌کند.
    • ورودی‌های پایدارشده شامل فراداده لغو هستند تا مصرف‌کنندگان رونوشت بتوانند بخش‌های لغو را از خروجی تکمیل عادی تشخیص دهند.

    نصب PWA و push وب

    UI کنترل همراه با یک manifest.webmanifest و یک service worker ارائه می‌شود، بنابراین مرورگرهای مدرن می‌توانند آن را به‌عنوان یک PWA مستقل نصب کنند. Web Push به Gateway اجازه می‌دهد PWA نصب‌شده را حتی وقتی برگه یا پنجره مرورگر باز نیست، با اعلان‌ها بیدار کند.

    سطح کاری که انجام می‌دهد
    ui/public/manifest.webmanifest مانیفست PWA. مرورگرها پس از قابل‌دسترسی شدن، "Install app" را پیشنهاد می‌کنند.
    ui/public/sw.js service worker که رویدادهای push و کلیک‌های اعلان را مدیریت می‌کند.
    push/vapid-keys.json (در زیر دایرکتوری state OpenClaw) جفت‌کلید VAPID تولیدشده خودکار که برای امضای payloadهای Web Push استفاده می‌شود.
    push/web-push-subscriptions.json endpointهای اشتراک مرورگر که پایدار شده‌اند.

    وقتی می‌خواهید کلیدها را ثابت نگه دارید (برای استقرارهای چندمیزبانه، چرخش secretها، یا تست‌ها)، جفت‌کلید VAPID را از طریق متغیرهای محیطی روی فرایند Gateway override کنید:

    • OPENCLAW_VAPID_PUBLIC_KEY
    • OPENCLAW_VAPID_PRIVATE_KEY
    • OPENCLAW_VAPID_SUBJECT (به‌طور پیش‌فرض mailto:openclaw@localhost)

    UI کنترل از این روش‌های Gateway محدودشده بر اساس scope برای ثبت و تست اشتراک‌های مرورگر استفاده می‌کند:

    • push.web.vapidPublicKey — کلید عمومی VAPID فعال را دریافت می‌کند.
    • push.web.subscribe — یک endpoint به‌علاوه keys.p256dh/keys.auth را ثبت می‌کند.
    • push.web.unsubscribe — یک endpoint ثبت‌شده را حذف می‌کند.
    • push.web.test — یک اعلان آزمایشی به اشتراک فراخواننده می‌فرستد.

    embedهای میزبانی‌شده

    پیام‌های دستیار می‌توانند محتوای وب میزبانی‌شده را به‌صورت درون‌خطی با shortcode [embed ...] رندر کنند. سیاست sandbox iframe با gateway.controlUi.embedSandbox کنترل می‌شود:

    strict

    اجرای script را درون embedهای میزبانی‌شده غیرفعال می‌کند.

    scripts (پیش‌فرض)

    embedهای تعاملی را مجاز می‌کند و هم‌زمان جداسازی origin را حفظ می‌کند؛ این پیش‌فرض است و معمولاً برای بازی‌ها/ویجت‌های مرورگری خودبسنده کافی است.

    trusted

    برای سندهای same-site که عمداً به امتیازهای قوی‌تری نیاز دارند، allow-same-origin را روی allow-scripts اضافه می‌کند.

    مثال:

    json5
    {  gateway: {    controlUi: {      embedSandbox: "scripts",    },  },}

    URLهای embed خارجی مطلق http(s) به‌طور پیش‌فرض مسدود می‌مانند. اگر عمداً می‌خواهید [embed url="https://..."] صفحه‌های شخص ثالث را بارگذاری کند، gateway.controlUi.allowExternalEmbedUrls: true را تنظیم کنید.

    عرض پیام چت

    پیام‌های چت گروه‌بندی‌شده از max-width پیش‌فرض خوانا استفاده می‌کنند. استقرارهای نمایشگر عریض می‌توانند بدون وصله کردن CSS بسته‌بندی‌شده، با تنظیم gateway.controlUi.chatMessageMaxWidth آن را override کنند:

    json5
    {  gateway: {    controlUi: {      chatMessageMaxWidth: "min(1280px, 82%)",    },  },}

    مقدار پیش از رسیدن به مرورگر اعتبارسنجی می‌شود. مقدارهای پشتیبانی‌شده شامل طول‌ها و درصدهای ساده مانند 960px یا 82%، به‌علاوه عبارت‌های عرض محدودشده min(...)، max(...)، clamp(...)، calc(...)، و fit-content(...) هستند.

    دسترسی Tailnet (پیشنهادی)

    Integrated Tailscale Serve (ترجیحی)

    Gateway را روی loopback نگه دارید و بگذارید Tailscale Serve آن را با HTTPS proxy کند:

    bash
    openclaw gateway --tailscale serve

    باز کنید:

    • https://<magicdns>/ (یا gateway.controlUi.basePath پیکربندی‌شده شما)

    به‌طور پیش‌فرض، درخواست‌های Serve برای رابط کاربری کنترل/WebSocket می‌توانند از طریق سرآیندهای هویت Tailscale (tailscale-user-login) احراز هویت شوند، وقتی gateway.auth.allowTailscale برابر true باشد. OpenClaw هویت را با resolve کردن نشانی x-forwarded-for از طریق tailscale whois و تطبیق آن با سرآیند تأیید می‌کند، و این موارد را فقط زمانی می‌پذیرد که درخواست با سرآیندهای x-forwarded-* متعلق به Tailscale به loopback برسد. برای نشست‌های اپراتور رابط کاربری کنترل با هویت دستگاه مرورگر، این مسیر Serve تأییدشده رفت‌وبرگشت جفت‌سازی دستگاه را نیز رد می‌کند؛ مرورگرهای بدون دستگاه و اتصال‌های دارای نقش node همچنان بررسی‌های عادی دستگاه را دنبال می‌کنند. اگر می‌خواهید حتی برای ترافیک Serve نیز اعتبارنامه‌های shared-secret صریح لازم باشد، gateway.auth.allowTailscale: false را تنظیم کنید. سپس از gateway.auth.mode: "token" یا "password" استفاده کنید.

    برای آن مسیر ناهمگام هویت Serve، تلاش‌های ناموفق احراز هویت برای همان IP کلاینت و دامنه احراز هویت، پیش از نوشتن‌های rate-limit به‌صورت سریالی انجام می‌شوند. بنابراین تلاش‌های مجدد بد هم‌زمان از همان مرورگر می‌توانند در درخواست دوم به‌جای دو عدم‌تطابق ساده که موازی رقابت می‌کنند، retry later نشان دهند.

    Bind to tailnet + token

    bash
    openclaw gateway --bind tailnet --token "$(openssl rand -hex 32)"

    سپس باز کنید:

    • http://<tailscale-ip>:18789/ (یا gateway.controlUi.basePath پیکربندی‌شده شما)

    shared secret متناظر را در تنظیمات UI وارد کنید (که به‌صورت connect.params.auth.token یا connect.params.auth.password ارسال می‌شود).

    HTTP ناامن

    اگر داشبورد را از طریق HTTP ساده (http://<lan-ip> یا http://<tailscale-ip>) باز کنید، مرورگر در یک بافت ناامن اجرا می‌شود و WebCrypto را مسدود می‌کند. به‌طور پیش‌فرض، OpenClaw اتصال‌های رابط کاربری کنترل بدون هویت دستگاه را مسدود می‌کند.

    استثناهای مستندشده:

    • سازگاری HTTP ناامن فقط برای localhost با gateway.controlUi.allowInsecureAuth=true
    • احراز هویت موفق اپراتور رابط کاربری کنترل از طریق gateway.auth.mode: "trusted-proxy"
    • حالت اضطراری gateway.controlUi.dangerouslyDisableDeviceAuth=true

    راهکار پیشنهادی: از HTTPS (Tailscale Serve) استفاده کنید یا UI را به‌صورت محلی باز کنید:

    • https://<magicdns>/ (Serve)
    • http://127.0.0.1:18789/ (روی میزبان Gateway)
    Insecure-auth toggle behavior
    json5
    {  gateway: {    controlUi: { allowInsecureAuth: true },    bind: "tailnet",    auth: { mode: "token", token: "replace-me" },  },}

    allowInsecureAuth فقط یک toggle سازگاری محلی است:

    • اجازه می‌دهد نشست‌های localhost رابط کاربری کنترل در بافت‌های HTTP ناامن بدون هویت دستگاه ادامه پیدا کنند.
    • بررسی‌های جفت‌سازی را دور نمی‌زند.
    • الزامات هویت دستگاه راه دور (غیر localhost) را آسان‌تر نمی‌کند.
    Break-glass only
    json5
    {  gateway: {    controlUi: { dangerouslyDisableDeviceAuth: true },    bind: "tailnet",    auth: { mode: "token", token: "replace-me" },  },}
    Trusted-proxy note
    • احراز هویت trusted-proxy موفق می‌تواند نشست‌های اپراتور رابط کاربری کنترل را بدون هویت دستگاه بپذیرد.
    • این موضوع به نشست‌های رابط کاربری کنترل با نقش node تعمیم پیدا نمی‌کند.
    • پراکسی‌های معکوس loopback روی همان میزبان همچنان احراز هویت trusted-proxy را برآورده نمی‌کنند؛ احراز هویت پراکسی قابل اعتماد را ببینید.

    برای راهنمایی راه‌اندازی HTTPS، Tailscale را ببینید.

    سیاست امنیت محتوا

    رابط کاربری کنترل با یک سیاست سخت‌گیرانه img-src عرضه می‌شود: فقط دارایی‌های همان origin، URLهای data: و URLهای blob: تولیدشده به‌صورت محلی مجاز هستند. URLهای تصویر راه دور http(s) و وابسته به پروتکل توسط مرورگر رد می‌شوند و fetch شبکه‌ای صادر نمی‌کنند.

    معنای عملی این موضوع:

    • آواتارها و تصویرهایی که زیر مسیرهای نسبی ارائه می‌شوند (برای مثال /avatars/<id>) همچنان render می‌شوند، از جمله مسیرهای آواتار احراز هویت‌شده‌ای که UI آن‌ها را fetch و به URLهای محلی blob: تبدیل می‌کند.
    • URLهای درون‌خطی data:image/... همچنان render می‌شوند (برای payloadهای درون‌پروتکلی مفید است).
    • URLهای محلی blob: ساخته‌شده توسط رابط کاربری کنترل همچنان render می‌شوند.
    • URLهای آواتار راه دور که توسط فراداده channel منتشر می‌شوند، در helperهای آواتار رابط کاربری کنترل حذف و با logo/badge داخلی جایگزین می‌شوند، بنابراین یک channel آلوده یا مخرب نمی‌تواند مرورگر اپراتور را مجبور به fetch دلخواه تصویر راه دور کند.

    برای دریافت این رفتار لازم نیست چیزی را تغییر دهید؛ همیشه فعال است و قابل پیکربندی نیست.

    احراز هویت مسیر آواتار

    وقتی احراز هویت Gateway پیکربندی شده باشد، endpoint آواتار رابط کاربری کنترل همان توکن Gateway را مانند بقیه API لازم دارد:

    • GET /avatar/<agentId> تصویر آواتار را فقط به فراخواننده‌های احراز هویت‌شده برمی‌گرداند. GET /avatar/<agentId>?meta=1 فراداده آواتار را تحت همان قاعده برمی‌گرداند.
    • درخواست‌های احراز هویت‌نشده به هر یک از مسیرها رد می‌شوند (مطابق مسیر هم‌خانواده assistant-media). این کار جلوی نشت هویت agent از مسیر آواتار را روی میزبان‌هایی که در غیر این صورت محافظت شده‌اند می‌گیرد.
    • خود رابط کاربری کنترل هنگام fetch کردن آواتارها، توکن Gateway را به‌عنوان سرآیند bearer ارسال می‌کند و از URLهای blob احراز هویت‌شده استفاده می‌کند تا تصویر همچنان در داشبوردها render شود.

    اگر احراز هویت Gateway را غیرفعال کنید (روی میزبان‌های مشترک توصیه نمی‌شود)، مسیر آواتار نیز مطابق بقیه Gateway بدون احراز هویت می‌شود.

    احراز هویت مسیر رسانه assistant

    وقتی احراز هویت Gateway پیکربندی شده باشد، پیش‌نمایش‌های رسانه محلی assistant از یک مسیر دومرحله‌ای استفاده می‌کنند:

    • GET /__openclaw__/assistant-media?meta=1&source=<path> احراز هویت عادی اپراتور رابط کاربری کنترل را لازم دارد. مرورگر هنگام بررسی دسترس‌پذیری، توکن Gateway را به‌عنوان سرآیند bearer ارسال می‌کند.
    • پاسخ‌های موفق فراداده شامل یک mediaTicket کوتاه‌عمر هستند که به همان مسیر منبع دقیق محدود شده است.
    • URLهای تصویر، صوت، ویدیو و سند که توسط مرورگر render می‌شوند، به‌جای توکن یا گذرواژه فعال Gateway از mediaTicket=<ticket> استفاده می‌کنند. ticket سریع منقضی می‌شود و نمی‌تواند منبع دیگری را مجاز کند.

    این کار render عادی رسانه را با عنصرهای رسانه‌ای native مرورگر سازگار نگه می‌دارد، بدون اینکه اعتبارنامه‌های قابل‌استفاده مجدد Gateway در URLهای رسانه قابل مشاهده قرار بگیرند.

    ساخت UI

    Gateway فایل‌های ایستا را از dist/control-ui ارائه می‌کند. آن‌ها را با این دستور بسازید:

    bash
    pnpm ui:build

    base مطلق اختیاری (وقتی URLهای ثابت دارایی می‌خواهید):

    bash
    OPENCLAW_CONTROL_UI_BASE_PATH=/openclaw/ pnpm ui:build

    برای توسعه محلی (dev server جداگانه):

    bash
    pnpm ui:dev

    سپس UI را به URL مربوط به Gateway WS خود اشاره دهید (مثلاً ws://127.0.0.1:18789).

    صفحه خالی رابط کاربری کنترل

    اگر مرورگر یک داشبورد خالی بارگذاری کند و DevTools خطای مفیدی نشان ندهد، ممکن است یک افزونه یا content script اولیه مانع ارزیابی app ماژول JavaScript شده باشد. صفحه ایستا شامل یک پنل بازیابی HTML ساده است که وقتی <openclaw-app> پس از startup ثبت نشده باشد ظاهر می‌شود.

    پس از تغییر محیط مرورگر، از اقدام دوباره تلاش کن پنل استفاده کنید، یا پس از این بررسی‌ها به‌صورت دستی reload کنید:

    • افزونه‌هایی را که به همه صفحه‌ها inject می‌شوند غیرفعال کنید، به‌ویژه افزونه‌هایی با content scriptهای <all_urls>.
    • یک پنجره خصوصی، یک پروفایل مرورگر تمیز، یا یک مرورگر دیگر را امتحان کنید.
    • Gateway را در حال اجرا نگه دارید و پس از تغییر مرورگر همان URL داشبورد را بررسی کنید.

    اشکال‌زدایی/آزمون: dev server + Gateway راه دور

    رابط کاربری کنترل فایل‌های ایستا است؛ target مربوط به WebSocket قابل پیکربندی است و می‌تواند با origin مربوط به HTTP متفاوت باشد. این برای زمانی مناسب است که می‌خواهید dev server مربوط به Vite محلی باشد اما Gateway در جای دیگری اجرا شود.

  • Start the UI dev server

    bash
    pnpm ui:dev
  • Open with gatewayUrl

    text
    http://localhost:5173/?gatewayUrl=ws%3A%2F%2F<gateway-host>%3A18789

    احراز هویت یک‌باره اختیاری (در صورت نیاز):

    text
    http://localhost:5173/?gatewayUrl=wss%3A%2F%2F<gateway-host>%3A18789#token=<gateway-token>
  • Notes
    • gatewayUrl پس از load در localStorage ذخیره و از URL حذف می‌شود.
    • اگر یک endpoint کامل ws:// یا wss:// را از طریق gatewayUrl ارسال می‌کنید، مقدار gatewayUrl را URL-encode کنید تا مرورگر query string را درست parse کند.
    • هر وقت ممکن است، token باید از طریق fragment URL (#token=...) ارسال شود. fragmentها به server ارسال نمی‌شوند، که از نشت در request-log و Referer جلوگیری می‌کند. query paramهای قدیمی ?token= همچنان برای سازگاری یک‌بار import می‌شوند، اما فقط به‌عنوان fallback، و بلافاصله پس از bootstrap حذف می‌شوند.
    • password فقط در حافظه نگه داشته می‌شود.
    • وقتی gatewayUrl تنظیم شده باشد، UI به اعتبارنامه‌های config یا environment fallback نمی‌کند. token (یا password) را صریحاً ارائه کنید. نبود اعتبارنامه‌های صریح یک خطا است.
    • وقتی Gateway پشت TLS قرار دارد (Tailscale Serve، پراکسی HTTPS و غیره)، از wss:// استفاده کنید.
    • gatewayUrl فقط در یک پنجره top-level پذیرفته می‌شود (نه embedded) تا از clickjacking جلوگیری شود.
    • استقرارهای رابط کاربری کنترل غیر loopback باید gateway.controlUi.allowedOrigins را به‌صورت صریح تنظیم کنند (originهای کامل). این شامل setupهای dev راه دور نیز می‌شود.
    • startup مربوط به Gateway ممکن است originهای محلی مانند http://localhost:<port> و http://127.0.0.1:<port> را از bind و port مؤثر runtime مقداردهی اولیه کند، اما originهای مرورگر راه دور همچنان به entryهای صریح نیاز دارند.
    • از gateway.controlUi.allowedOrigins: ["*"] جز برای آزمون محلی کاملاً کنترل‌شده استفاده نکنید. معنای آن اجازه دادن به هر origin مرورگر است، نه «مطابقت با هر میزبانی که استفاده می‌کنم».
    • gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true حالت fallback origin بر پایه سرآیند Host را فعال می‌کند، اما یک حالت امنیتی خطرناک است.

    نمونه:

    json5
    {  gateway: {    controlUi: {      allowedOrigins: ["http://localhost:5173"],    },  },}

    جزئیات راه‌اندازی دسترسی راه دور: دسترسی راه دور.

    مرتبط

    Was this useful?