Web interfaces
رابط کاربری کنترل
رابط کاربری کنترل یک برنامهٔ تکصفحهای کوچک با Vite + Lit است که توسط Gateway ارائه میشود:
- پیشفرض:
http://<host>:18789/ - پیشوند اختیاری:
gateway.controlUi.basePathرا تنظیم کنید (مثلاً/openclaw)
این رابط مستقیماً با WebSocket Gateway روی همان پورت ارتباط برقرار میکند.
باز کردن سریع (محلی)
اگر Gateway روی همان رایانه در حال اجراست، باز کنید:
اگر صفحه بارگذاری نشد، ابتدا Gateway را اجرا کنید: openclaw gateway.
احراز هویت هنگام دستدهی WebSocket از طریق موارد زیر ارائه میشود:
connect.params.auth.tokenconnect.params.auth.password- سرآیندهای هویت Tailscale Serve وقتی
gateway.auth.allowTailscale: trueباشد - سرآیندهای هویت trusted-proxy وقتی
gateway.auth.mode: "trusted-proxy"باشد
پنل تنظیمات داشبورد یک توکن را برای نشست فعلی تب مرورگر و URL انتخابشدهٔ gateway نگه میدارد؛ گذرواژهها پایدار نمیشوند. فرایند راهاندازی معمولاً در اولین اتصال یک توکن gateway برای احراز هویت shared-secret تولید میکند، اما احراز هویت با گذرواژه هم وقتی gateway.auth.mode برابر "password" باشد کار میکند.
جفتسازی دستگاه (اولین اتصال)
وقتی از یک مرورگر یا دستگاه جدید به رابط کاربری کنترل وصل میشوید، Gateway معمولاً به یک تأیید جفتسازی یکباره نیاز دارد. این یک اقدام امنیتی برای جلوگیری از دسترسی غیرمجاز است.
آنچه خواهید دید: "disconnected (1008): pairing required"
فهرست کردن درخواستهای در انتظار
openclaw devices list
تأیید با شناسهٔ درخواست
openclaw devices approve <requestId>
اگر مرورگر جفتسازی را با جزئیات احراز هویت تغییرکرده دوباره امتحان کند (نقش/دامنهها/کلید عمومی)، درخواست در انتظار قبلی جایگزین میشود و یک requestId جدید ساخته میشود. پیش از تأیید، دوباره openclaw devices list را اجرا کنید.
اگر مرورگر از قبل جفت شده باشد و آن را از دسترسی خواندن به دسترسی نوشتن/مدیر تغییر دهید، این بهعنوان ارتقای تأیید در نظر گرفته میشود، نه اتصال مجدد بیصدا. OpenClaw تأیید قدیمی را فعال نگه میدارد، اتصال مجدد گستردهتر را مسدود میکند، و از شما میخواهد مجموعهٔ دامنهٔ جدید را صریحاً تأیید کنید.
پس از تأیید، دستگاه به خاطر سپرده میشود و مگر اینکه آن را با openclaw devices revoke --device <id> --role <role> لغو کنید، دوباره به تأیید نیاز نخواهد داشت. برای چرخش و لغو توکن، CLI دستگاهها را ببینید.
هویت شخصی (محلیِ مرورگر)
رابط کاربری کنترل از یک هویت شخصی برای هر مرورگر پشتیبانی میکند (نام نمایشی و آواتار) که برای انتساب در نشستهای مشترک به پیامهای خروجی متصل میشود. این هویت در فضای ذخیرهسازی مرورگر قرار دارد، به پروفایل فعلی مرورگر محدود است، و به دستگاههای دیگر همگامسازی نمیشود یا فراتر از فرادادهٔ عادی نویسندگی رونوشت روی پیامهایی که واقعاً ارسال میکنید، در سمت سرور پایدار نمیشود. پاک کردن دادههای سایت یا تغییر مرورگر آن را به حالت خالی بازنشانی میکند.
همین الگوی محلیِ مرورگر برای بازنویسی آواتار دستیار نیز اعمال میشود. آواتارهای بارگذاریشدهٔ دستیار فقط در مرورگر محلی، هویت تعیینشده توسط gateway را میپوشانند و هرگز از مسیر config.patch رفتوبرگشت نمیشوند. فیلد پیکربندی مشترک ui.assistant.avatar همچنان برای کلاینتهای غیر UI که این فیلد را مستقیماً مینویسند در دسترس است (مانند gatewayهای اسکریپتشده یا داشبوردهای سفارشی).
نقطهٔ پایانی پیکربندی زمان اجرا
رابط کاربری کنترل تنظیمات زمان اجرای خود را از /__openclaw/control-ui-config.json دریافت میکند. این نقطهٔ پایانی با همان احراز هویت gateway مانند بقیهٔ سطح HTTP محافظت میشود: مرورگرهای احراز هویتنشده نمیتوانند آن را دریافت کنند، و دریافت موفق به یک توکن/گذرواژهٔ gateway که از قبل معتبر است، هویت Tailscale Serve، یا هویت trusted-proxy نیاز دارد.
پشتیبانی زبان
رابط کاربری کنترل میتواند در اولین بارگذاری، خود را بر اساس locale مرورگر شما محلیسازی کند. برای بازنویسی آن در آینده، نمای کلی -> دسترسی Gateway -> زبان را باز کنید. انتخابگر locale در کارت دسترسی Gateway قرار دارد، نه زیر ظاهر.
- localeهای پشتیبانیشده:
en,zh-CN,zh-TW,pt-BR,de,es,ja-JP,ko,fr,ar,it,tr,uk,id,pl,th,vi,nl,fa - ترجمههای غیرانگلیسی در مرورگر بهصورت lazy-loaded بارگذاری میشوند.
- locale انتخابشده در فضای ذخیرهسازی مرورگر ذخیره میشود و در بازدیدهای آینده دوباره استفاده میشود.
- کلیدهای ترجمهٔ موجودنبودن به انگلیسی fallback میکنند.
ترجمههای مستندات برای همان مجموعهٔ locale غیرانگلیسی تولید میشوند، اما انتخابگر زبان داخلی سایت مستندات در Mintlify به کدهای localeای محدود است که Mintlify میپذیرد. مستندات تایلندی (th) و فارسی (fa) همچنان در مخزن انتشار تولید میشوند؛ ممکن است تا زمانی که Mintlify از آن کدها پشتیبانی نکند در آن انتخابگر ظاهر نشوند.
تمهای ظاهر
پنل ظاهر، تمهای داخلی Claw، Knot، و Dash را بههمراه یک جایگاه import محلیِ مرورگر از tweakcn نگه میدارد. برای import کردن یک تم، ویرایشگر tweakcn را باز کنید، یک تم انتخاب یا ایجاد کنید، روی اشتراکگذاری کلیک کنید، و پیوند تم کپیشده را در ظاهر جایگذاری کنید. importکننده همچنین URLهای رجیستری https://tweakcn.com/r/themes/<id>، URLهای ویرایشگر مانند https://tweakcn.com/editor/theme?theme=amethyst-haze، مسیرهای نسبی /themes/<id>، شناسههای خام تم، و نامهای تم پیشفرض مانند amethyst-haze را میپذیرد.
تمهای importشده فقط در پروفایل فعلی مرورگر ذخیره میشوند. آنها در پیکربندی gateway نوشته نمیشوند و بین دستگاهها همگامسازی نمیشوند. جایگزین کردن تم importشده همان یک جایگاه محلی را بهروزرسانی میکند؛ پاک کردن آن، اگر تم importشده انتخاب شده باشد، تم فعال را به Claw برمیگرداند.
اکنون چه کارهایی میتواند انجام دهد
چت و گفتوگو
- از طریق Gateway WS با مدل چت کنید (
chat.history,chat.send,chat.abort,chat.inject). - تازهسازی تاریخچهٔ چت یک پنجرهٔ اخیر محدود با سقف متن برای هر پیام درخواست میکند تا نشستهای بزرگ، مرورگر را مجبور نکنند پیش از قابل استفاده شدن چت، payload کامل رونوشت را render کند.
- از طریق نشستهای realtime مرورگر گفتوگو کنید. OpenAI از WebRTC مستقیم استفاده میکند، Google Live از یک توکن یکبارمصرف محدود مرورگر روی WebSocket استفاده میکند، و Pluginهای صدای realtime فقط backend از انتقال relay در Gateway استفاده میکنند. نشستهای provider که مالکشان کلاینت است با
talk.client.createشروع میشوند؛ نشستهای relay در Gateway باtalk.session.createشروع میشوند. relay، اعتبارنامههای provider را روی Gateway نگه میدارد در حالی که مرورگر PCM میکروفون را از طریقtalk.session.appendAudiostream میکند و فراخوانیهای ابزار provider با نامopenclaw_agent_consultرا از طریقtalk.client.toolCallبرای سیاست Gateway و مدل بزرگتر پیکربندیشدهٔ OpenClaw ارسال میکند. - فراخوانیهای ابزار + کارتهای خروجی زندهٔ ابزار را در چت stream کنید (رویدادهای agent).
کانالها، نمونهها، نشستها، رؤیاها
- کانالها: وضعیت کانالهای داخلی بههمراه Plugin داخلی/خارجی، ورود QR، و پیکربندی برای هر کانال (
channels.status,web.login.*,config.patch). - تازهسازی probe کانالها snapshot قبلی را تا پایان بررسیهای کند provider قابل مشاهده نگه میدارد، و وقتی یک probe یا audit از بودجهٔ UI خود فراتر برود، snapshotهای جزئی برچسبگذاری میشوند.
- نمونهها: فهرست حضور + تازهسازی (
system-presence). - نشستها: فهرست + بازنویسیهای مدل/تفکر/سریع/verbose/ردیابی/reasoning برای هر نشست (
sessions.list,sessions.patch). - رؤیاها: وضعیت Dreaming، کلید فعال/غیرفعال، و خوانندهٔ Dream Diary (
doctor.memory.status,doctor.memory.dreamDiary,config.patch).
Cron، Skills، Nodeها، تأییدیههای exec
- کارهای Cron: فهرست/افزودن/ویرایش/اجرا/فعالسازی/غیرفعالسازی + تاریخچهٔ اجرا (
cron.*). - Skills: وضعیت، فعال/غیرفعالسازی، نصب، بهروزرسانیهای کلید API (
skills.*). - Nodeها: فهرست + قابلیتها (
node.list). - تأییدیههای exec: ویرایش allowlistهای gateway یا node + سیاست پرسش برای
exec host=gateway/node(exec.approvals.*).
پیکربندی
- مشاهده/ویرایش
~/.openclaw/openclaw.json(config.get,config.set). - اعمال + راهاندازی دوباره همراه با اعتبارسنجی (
config.apply) و بیدار کردن آخرین نشست فعال. - نوشتنها شامل یک محافظ base-hash برای جلوگیری از بازنویسی و از بین بردن ویرایشهای همزمان هستند.
- نوشتنها (
config.set/config.apply/config.patch) پیش از اجرا، resolve شدن SecretRefهای فعال را برای refهای موجود در payload پیکربندی ارسالی بررسی میکنند؛ refهای فعال ارسالی که resolve نشده باشند پیش از نوشتن رد میشوند. - Schema + render فرم (
config.schema/config.schema.lookup، شاملtitle/descriptionفیلد، hintهای UI تطبیقیافته، خلاصههای فرزند فوری، فرادادهٔ مستندات روی nodeهای object/wildcard/array/composition تو در تو، بههمراه schemaهای Plugin + کانال وقتی موجود باشند)؛ ویرایشگر Raw JSON فقط وقتی در دسترس است که snapshot یک رفتوبرگشت خام امن داشته باشد. - اگر یک snapshot نتواند متن خام را با اطمینان رفتوبرگشت کند، رابط کاربری کنترل حالت Form را اجباری میکند و حالت Raw را برای آن snapshot غیرفعال میکند.
- گزینهٔ "بازنشانی به ذخیرهشده" در ویرایشگر Raw JSON شکل نوشتهشدهٔ خام را حفظ میکند (قالببندی، دیدگاهها، چیدمان
$include) بهجای اینکه یک snapshot تخت را دوباره render کند، تا وقتی snapshot بتواند با اطمینان رفتوبرگشت کند، ویرایشهای خارجی پس از بازنشانی باقی بمانند. - مقدارهای object ساختاریافتهٔ SecretRef در ورودیهای متنی فرم بهصورت فقطخواندنی render میشوند تا از خرابی تصادفی object-to-string جلوگیری شود.
اشکالزدایی، لاگها، بهروزرسانی
- اشکالزدایی: snapshotهای وضعیت/سلامت/مدلها + لاگ رویداد + فراخوانیهای دستی RPC (
status,health,models.list). - لاگ رویداد شامل زمانبندیهای تازهسازی/RPC رابط کاربری کنترل، زمانبندیهای کند render چت/پیکربندی، و ورودیهای پاسخگویی مرورگر برای فریمهای انیمیشن طولانی یا taskهای طولانی است، وقتی مرورگر آن نوع ورودیهای PerformanceObserver را ارائه کند.
- لاگها: دنبال کردن زندهٔ لاگهای فایل gateway با فیلتر/export (
logs.tail). - بهروزرسانی: اجرای بهروزرسانی package/git + راهاندازی دوباره (
update.run) همراه با گزارش راهاندازی دوباره، سپس poll کردنupdate.statusپس از اتصال مجدد برای تأیید نسخهٔ gateway در حال اجرا.
یادداشتهای پنل کارهای Cron
- برای کارهای isolated، پیشفرض delivery اعلام خلاصه است. اگر اجراهای فقط داخلی میخواهید، میتوانید آن را به none تغییر دهید.
- فیلدهای کانال/هدف وقتی announce انتخاب شده باشد ظاهر میشوند.
- حالت Webhook از
delivery.mode = "webhook"باdelivery.toتنظیمشده روی یک URL معتبر webhook از نوع HTTP(S) استفاده میکند. - برای کارهای نشست اصلی، حالتهای delivery یعنی webhook و none در دسترس هستند.
- کنترلهای ویرایش پیشرفته شامل حذف پس از اجرا، پاک کردن بازنویسی agent، گزینههای cron exact/stagger، بازنویسیهای مدل/تفکر agent، و کلیدهای best-effort delivery هستند.
- اعتبارسنجی فرم بهصورت inline با خطاهای سطح فیلد انجام میشود؛ مقدارهای نامعتبر تا زمان اصلاح، دکمهٔ ذخیره را غیرفعال میکنند.
cron.webhookTokenرا تنظیم کنید تا یک bearer token اختصاصی ارسال شود؛ اگر حذف شود webhook بدون سرآیند احراز هویت ارسال میشود.- fallback منسوخ: کارهای legacy ذخیرهشده با
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، رابط کاربری کنترل برچسبهای دستور درونخطیِ صرفاً نمایشی را از متن قابل مشاهدهٔ دستیار حذف میکند (برای نمونه[[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از رونوشت پایدار نشست بازسازی میشود. پس از رویدادهای نهایی ابزار، رابط کاربری کنترل تاریخچه را دوباره بارگذاری میکند و فقط یک دنبالهٔ خوشبینانهٔ کوچک را ادغام میکند؛ مرز رونوشت در WebChat مستند شده است. chat.injectیک یادداشت دستیار را به رونوشت نشست اضافه میکند و یک رویدادchatرا برای بهروزرسانیهای فقط UI پخش میکند (بدون اجرای عامل، بدون تحویل کانال).- سربرگ گفتگو فیلتر عامل را پیش از انتخابگر نشست نشان میدهد، و انتخابگر نشست به عامل انتخابشده محدود میشود. تغییر عاملها فقط نشستهای وابسته به آن عامل را نشان میدهد و وقتی هنوز هیچ نشست داشبورد ذخیرهشدهای ندارد به نشست اصلی همان عامل بازمیگردد.
- در عرضهای دسکتاپ، کنترلهای گفتگو در یک ردیف فشرده میمانند و هنگام پیمایش به پایین رونوشت جمع میشوند؛ پیمایش به بالا، بازگشت به ابتدای صفحه، یا رسیدن به انتها کنترلها را بازمیگرداند.
- پیامهای پیاپی و تکراریِ فقط متنی بهصورت یک حباب با نشان شمارش رندر میشوند. پیامهایی که تصویر، پیوست، خروجی ابزار، یا پیشنمایش canvas دارند جمع نمیشوند.
- انتخابگرهای مدل و تفکر در سربرگ گفتگو نشست فعال را فوراً از طریق
sessions.patchوصله میکنند؛ آنها بازنویسیهای پایدار نشست هستند، نه گزینههای ارسال فقط برای یک نوبت. - تایپ کردن
/newدر رابط کاربری کنترل همان نشست تازهٔ داشبورد را مانند گفتگوی جدید ایجاد میکند و به آن تغییر میدهد. تایپ کردن/resetبازنشانی صریحِ درجا در Gateway را برای نشست فعلی حفظ میکند. - انتخابگر مدل گفتگو نمای مدل پیکربندیشدهٔ Gateway را درخواست میکند. اگر
agents.defaults.modelsوجود داشته باشد، همان allowlist انتخابگر را هدایت میکند. در غیر این صورت انتخابگر ورودیهای صریحmodels.providers.*.modelsبههمراه ارائهدهندگانی با احراز هویت قابل استفاده را نشان میدهد. کاتالوگ کامل از طریق RPC اشکالزداییmodels.listباview: "all"همچنان در دسترس است. - وقتی گزارشهای تازهٔ مصرف نشست Gateway فشار بالای زمینه را نشان میدهند، ناحیهٔ نویسندهٔ گفتگو یک اعلان زمینه نشان میدهد و در سطوح توصیهشدهٔ Compaction، یک دکمهٔ فشرده نمایش میدهد که مسیر عادی Compaction نشست را اجرا میکند. snapshotهای کهنهٔ توکن تا زمانی که Gateway دوباره مصرف تازه را گزارش کند پنهان میمانند.
حالت گفتار (بلادرنگ در مرورگر)
حالت گفتار از یک ارائهدهندهٔ صدای بلادرنگِ ثبتشده استفاده میکند. OpenAI را با talk.realtime.provider: "openai" بههمراه talk.realtime.providers.openai.apiKey پیکربندی کنید، یا Google را با talk.realtime.provider: "google" بههمراه talk.realtime.providers.google.apiKey پیکربندی کنید. مرورگر هرگز یک کلید API استاندارد ارائهدهنده را دریافت نمیکند. OpenAI یک secret موقتِ کلاینت Realtime برای WebRTC دریافت میکند. Google Live یک توکن احراز هویت Live API محدود و یکبارمصرف برای نشست WebSocket مرورگر دریافت میکند، در حالی که دستورالعملها و اعلانهای ابزار توسط Gateway در توکن قفل شدهاند. ارائهدهندگانی که فقط یک پل بلادرنگ backend ارائه میکنند از طریق انتقال relay در Gateway اجرا میشوند، بنابراین اعتبارنامهها و سوکتهای فروشنده سمت سرور میمانند و صدای مرورگر از طریق RPCهای احراز هویتشدهٔ Gateway منتقل میشود. prompt نشست Realtime توسط Gateway مونتاژ میشود؛ talk.client.create بازنویسی دستورالعمل ارائهشده توسط فراخواننده را نمیپذیرد.
در نویسندهٔ گفتگو، کنترل گفتار دکمهٔ موجها کنار دکمهٔ دیکتهٔ میکروفون است. وقتی گفتار شروع میشود، ردیف وضعیت نویسنده 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 تبادل SDP مربوط به WebRTC مرورگر OpenAI، راهاندازی WebSocket مرورگر با توکن محدود Google Live، و آداپتور مرورگر relay در Gateway را با رسانهٔ میکروفون جعلی بررسی میکند. این دستور فقط وضعیت ارائهدهنده را چاپ میکند و secretها را ثبت نمیکند.
توقف و لغو
- روی توقف کلیک کنید (
chat.abortرا فراخوانی میکند). - وقتی یک اجرا فعال است، پیگیریهای عادی در صف قرار میگیرند. روی هدایت در یک پیام صفشده کلیک کنید تا آن پیگیری به نوبت در حال اجرا تزریق شود.
- برای لغو خارج از باند،
/stopرا تایپ کنید (یا عبارتهای لغو مستقل مانندstop،stop action،stop run،stop openclaw،please stop). chat.abortاز{ sessionKey }(بدونrunId) برای لغو همهٔ اجراهای فعال آن نشست پشتیبانی میکند.
نگهداری بخشهای جزئی پس از لغو
- وقتی یک اجرا لغو میشود، متن جزئی دستیار همچنان میتواند در UI نمایش داده شود.
- Gateway وقتی خروجی بافرشده وجود داشته باشد، متن جزئیِ لغوشدهٔ دستیار را در تاریخچهٔ رونوشت پایدار میکند.
- ورودیهای پایدارشده شامل فرادادهٔ لغو هستند تا مصرفکنندگان رونوشت بتوانند بخشهای جزئیِ لغوشده را از خروجی تکمیل عادی تشخیص دهند.
نصب PWA و Web Push
رابط کاربری کنترل یک manifest.webmanifest و یک service worker ارائه میکند، بنابراین مرورگرهای مدرن میتوانند آن را بهعنوان یک PWA مستقل نصب کنند. Web Push به Gateway اجازه میدهد PWA نصبشده را حتی وقتی زبانه یا پنجرهٔ مرورگر باز نیست با اعلانها بیدار کند.
| سطح | کاری که انجام میدهد |
|---|---|
ui/public/manifest.webmanifest |
manifest مربوط به PWA. پس از در دسترس شدن، مرورگرها گزینهٔ «Install app» را پیشنهاد میکنند. |
ui/public/sw.js |
service worker که رویدادهای push و کلیکهای اعلان را مدیریت میکند. |
push/vapid-keys.json (زیر دایرکتوری وضعیت OpenClaw) |
جفتکلید VAPID تولیدشده بهصورت خودکار که برای امضای payloadهای Web Push استفاده میشود. |
push/web-push-subscriptions.json |
endpointهای subscription مرورگر که پایدار شدهاند. |
وقتی میخواهید کلیدها را ثابت نگه دارید (برای استقرارهای چندمیزبانه، چرخش secretها، یا تستها)، جفتکلید VAPID را از طریق env varها روی فرایند Gateway بازنویسی کنید:
OPENCLAW_VAPID_PUBLIC_KEYOPENCLAW_VAPID_PRIVATE_KEYOPENCLAW_VAPID_SUBJECT(پیشفرض:mailto:openclaw@localhost)
رابط کاربری کنترل از این متدهای Gateway با دامنهٔ محدود برای ثبت و آزمایش subscriptionهای مرورگر استفاده میکند:
push.web.vapidPublicKey— کلید عمومی VAPID فعال را دریافت میکند.push.web.subscribe— یکendpointبههمراهkeys.p256dh/keys.authثبت میکند.push.web.unsubscribe— یک endpoint ثبتشده را حذف میکند.push.web.test— یک اعلان آزمایشی به subscription فراخواننده میفرستد.
جاسازیهای میزبانیشده
پیامهای دستیار میتوانند محتوای وب میزبانیشده را با shortcode [embed ...] بهصورت درونخطی رندر کنند. سیاست sandbox مربوط به iframe با gateway.controlUi.embedSandbox کنترل میشود:
سختگیرانه
اجرای اسکریپت را داخل جاسازیهای میزبانیشده غیرفعال میکند.
اسکریپتها (پیشفرض)
جاسازیهای تعاملی را مجاز میکند و همزمان جداسازی origin را حفظ میکند؛ این حالت پیشفرض است و معمولاً برای بازیها/ویجتهای مرورگریِ خودبسنده کافی است.
مورد اعتماد
برای سندهای همان سایت که عمداً به امتیازهای قویتر نیاز دارند، allow-same-origin را روی allow-scripts اضافه میکند.
نمونه:
{
gateway: {
controlUi: {
embedSandbox: "scripts",
},
},
}
URLهای جاسازی خارجی مطلقِ http(s) بهصورت پیشفرض مسدود میمانند. اگر عمداً میخواهید [embed url="https://..."] صفحههای شخص ثالث را بارگذاری کند، gateway.controlUi.allowExternalEmbedUrls: true را تنظیم کنید.
عرض پیام گفتگو
پیامهای گروهبندیشدهٔ گفتگو از max-width پیشفرض خوانا استفاده میکنند. استقرارهای مانیتور عریض میتوانند بدون وصله کردن CSS بستهبندیشده، آن را با تنظیم gateway.controlUi.chatMessageMaxWidth بازنویسی کنند:
{
gateway: {
controlUi: {
chatMessageMaxWidth: "min(1280px, 82%)",
},
},
}
این مقدار پیش از رسیدن به مرورگر اعتبارسنجی میشود. مقدارهای پشتیبانیشده شامل طولها و درصدهای ساده مانند 960px یا 82%، بهعلاوهٔ عبارتهای عرض محدودشدهٔ min(...)، max(...)، clamp(...)، calc(...)، و fit-content(...) هستند.
دسترسی tailnet (توصیهشده)
Tailscale Serve یکپارچه (ترجیحی)
Gateway را روی loopback نگه دارید و اجازه دهید Tailscale Serve آن را با HTTPS پروکسی کند:
openclaw gateway --tailscale serve
باز کنید:
https://<magicdns>/(یاgateway.controlUi.basePathپیکربندیشدهٔ شما)
بهصورت پیشفرض، درخواستهای Serve مربوط به رابط کاربری کنترل/WebSocket میتوانند وقتی gateway.auth.allowTailscale برابر true است از طریق سربرگهای هویت Tailscale (tailscale-user-login) احراز هویت شوند. OpenClaw هویت را با resolve کردن نشانی x-forwarded-for با tailscale whois و تطبیق آن با سربرگ بررسی میکند، و این موارد را فقط وقتی میپذیرد که درخواست به loopback همراه با سربرگهای x-forwarded-* مربوط به Tailscale برسد. برای نشستهای اپراتور رابط کاربری کنترل با هویت دستگاه مرورگر، این مسیر Serve تأییدشده همچنین رفتوبرگشت pairing دستگاه را رد میکند؛ مرورگرهای بدون دستگاه و اتصالهای دارای نقش node همچنان بررسیهای عادی دستگاه را دنبال میکنند. اگر میخواهید حتی برای ترافیک Serve نیز اعتبارنامههای صریح shared-secret الزامی باشد، gateway.auth.allowTailscale: false را تنظیم کنید. سپس از gateway.auth.mode: "token" یا "password" استفاده کنید.
برای آن مسیر ناهمگام هویت Serve، تلاشهای احراز هویت ناموفق برای همان IP کلاینت و دامنهٔ احراز هویت پیش از نوشتن rate-limit سریالی میشوند. بنابراین تلاشهای بد همزمان از همان مرورگر میتوانند در درخواست دوم بهجای دو عدمتطابق ساده که موازی رقابت میکنند، retry later را نشان دهند.
اتصال به tailnet + توکن
openclaw gateway --bind tailnet --token "$(openssl rand -hex 32)"
سپس باز کنید:
http://<tailscale-ip>:18789/(یاgateway.controlUi.basePathپیکربندیشدهٔ شما)
راز مشترک مطابق را در تنظیمات رابط کاربری جایگذاری کنید (بهصورت 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) استفاده کنید یا رابط کاربری را بهصورت محلی باز کنید:
https://<magicdns>/(Serve)http://127.0.0.1:18789/(روی میزبان Gateway)
Insecure-auth toggle behavior
{
gateway: {
controlUi: { allowInsecureAuth: true },
bind: "tailnet",
auth: { mode: "token", token: "replace-me" },
},
}
allowInsecureAuth فقط یک کلید سازگاری محلی است:
- اجازه میدهد نشستهای رابط کاربری کنترل localhost بدون هویت دستگاه در زمینههای HTTP غیرامن ادامه پیدا کنند.
- بررسیهای جفتسازی را دور نمیزند.
- الزامات هویت دستگاه راهدور (غیر-localhost) را آسانتر نمیکند.
Break-glass only
{
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 ارائه میشود: فقط داراییهای same-origin، URLهای data: و URLهای blob: تولیدشده بهصورت محلی مجاز هستند. URLهای تصویر راهدور http(s) و protocol-relative توسط مرورگر رد میشوند و درخواست شبکهای صادر نمیکنند.
معنای عملی این موضوع:
- آواتارها و تصویرهایی که زیر مسیرهای نسبی ارائه میشوند (برای مثال
/avatars/<id>) همچنان رندر میشوند، از جمله مسیرهای آواتار احراز هویتشده که رابط کاربری آنها را واکشی میکند و به URLهای محلیblob:تبدیل میکند. - URLهای درونخطی
data:image/...همچنان رندر میشوند (برای payloadهای درونپروتکل مفید است). - URLهای محلی
blob:ساختهشده توسط رابط کاربری کنترل همچنان رندر میشوند. - URLهای آواتار راهدور که توسط فراداده کانال منتشر میشوند در helperهای آواتار رابط کاربری کنترل حذف و با لوگو/نشان داخلی جایگزین میشوند، بنابراین یک کانال نفوذکرده یا مخرب نمیتواند مرورگر اپراتور را مجبور به واکشی دلخواه تصویر راهدور کند.
برای دریافت این رفتار لازم نیست چیزی را تغییر دهید — همیشه فعال است و قابل پیکربندی نیست.
احراز هویت مسیر آواتار
وقتی احراز هویت Gateway پیکربندی شده باشد، endpoint آواتار رابط کاربری کنترل به همان توکن Gateway که بقیه API استفاده میکنند نیاز دارد:
GET /avatar/<agentId>تصویر آواتار را فقط به فراخوانهای احراز هویتشده برمیگرداند.GET /avatar/<agentId>?meta=1فراداده آواتار را تحت همان قاعده برمیگرداند.- درخواستهای احراز هویتنشده به هر دو مسیر رد میشوند (همانند مسیر خواهر assistant-media). این کار از نشت هویت agent از مسیر آواتار روی میزبانهایی که در غیر این صورت محافظت شدهاند جلوگیری میکند.
- خود رابط کاربری کنترل هنگام واکشی آواتارها، توکن Gateway را بهعنوان bearer header ارسال میکند و از URLهای blob احراز هویتشده استفاده میکند تا تصویر همچنان در داشبوردها رندر شود.
اگر احراز هویت Gateway را غیرفعال کنید (روی میزبانهای مشترک توصیه نمیشود)، مسیر آواتار نیز مانند بقیه Gateway بدون احراز هویت میشود.
احراز هویت مسیر رسانه assistant
وقتی احراز هویت Gateway پیکربندی شده باشد، پیشنمایشهای رسانه محلی assistant از یک مسیر دومرحلهای استفاده میکنند:
GET /__openclaw__/assistant-media?meta=1&source=<path>به احراز هویت معمول اپراتور رابط کاربری کنترل نیاز دارد. مرورگر هنگام بررسی دسترسپذیری، توکن Gateway را بهعنوان bearer header ارسال میکند.- پاسخهای موفق فراداده شامل یک
mediaTicketکوتاهعمر هستند که به همان مسیر source دقیق محدود شده است. - URLهای تصویر، صدا، ویدئو و سند که در مرورگر رندر میشوند بهجای توکن یا گذرواژه فعال Gateway از
mediaTicket=<ticket>استفاده میکنند. ticket بهسرعت منقضی میشود و نمیتواند source دیگری را مجاز کند.
این کار رندر عادی رسانه را با عناصر رسانه بومی مرورگر سازگار نگه میدارد، بدون اینکه اعتبارنامههای قابلاستفادهمجدد Gateway را در URLهای قابل مشاهده رسانه قرار دهد.
ساخت رابط کاربری
Gateway فایلهای static را از dist/control-ui ارائه میکند. آنها را با دستور زیر بسازید:
pnpm ui:build
base مطلق اختیاری (وقتی URLهای ثابت دارایی میخواهید):
OPENCLAW_CONTROL_UI_BASE_PATH=/openclaw/ pnpm ui:build
برای توسعه محلی (dev server جداگانه):
pnpm ui:dev
سپس رابط کاربری را به URL مربوط به WS در Gateway خود اشاره دهید (مثلاً ws://127.0.0.1:18789).
اشکالزدایی/آزمایش: dev server + Gateway راهدور
رابط کاربری کنترل فایلهای static است؛ هدف WebSocket قابل پیکربندی است و میتواند با مبدا HTTP متفاوت باشد. این زمانی مفید است که میخواهید Vite dev server بهصورت محلی اجرا شود اما Gateway در جای دیگری اجرا شود.
Start the UI dev server
pnpm ui:dev
Open with gatewayUrl
http://localhost:5173/?gatewayUrl=ws%3A%2F%2F<gateway-host>%3A18789
احراز هویت یکباره اختیاری (در صورت نیاز):
http://localhost:5173/?gatewayUrl=wss%3A%2F%2F<gateway-host>%3A18789#token=<gateway-token>
Notes
gatewayUrlپس از بارگذاری در localStorage ذخیره و از URL حذف میشود.- اگر یک endpoint کامل
ws://یاwss://را از طریقgatewayUrlارسال میکنید، مقدارgatewayUrlرا URL-encode کنید تا مرورگر query string را درست parse کند. tokenتا حد امکان باید از طریق fragment URL (#token=...) ارسال شود. fragmentها به سرور ارسال نمیشوند، که از نشت در request-log و Referer جلوگیری میکند. پارامترهای query قدیمی?token=همچنان برای سازگاری یکبار import میشوند، اما فقط بهعنوان fallback، و بلافاصله پس از bootstrap حذف میشوند.passwordفقط در memory نگه داشته میشود.- وقتی
gatewayUrlتنظیم شده باشد، رابط کاربری به اعتبارنامههای config یا environment fallback نمیکند.token(یاpassword) را صریح ارائه کنید. نبود اعتبارنامههای صریح یک خطا است. - وقتی Gateway پشت TLS است (Tailscale Serve، پراکسی HTTPS و غیره)، از
wss://استفاده کنید. gatewayUrlفقط در یک پنجره top-level پذیرفته میشود (نه embedded) تا از clickjacking جلوگیری شود.- استقرارهای رابط کاربری کنترل غیر-loopback باید
gateway.controlUi.allowedOriginsرا صریح تنظیم کنند (origins کامل). این شامل راهاندازیهای dev راهدور نیز میشود. - راهاندازی Gateway ممکن است origins محلی مانند
http://localhost:<port>وhttp://127.0.0.1:<port>را از bind و port موثر runtime seed کند، اما origins مرورگر راهدور همچنان به entries صریح نیاز دارند. - از
gateway.controlUi.allowedOrigins: ["*"]استفاده نکنید مگر برای آزمایش محلی کاملاً کنترلشده. معنای آن اجازه دادن به هر browser origin است، نه «مطابقت با هر میزبانی که استفاده میکنم». gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=trueحالت fallback مبدا بر اساس Host-header را فعال میکند، اما یک حالت امنیتی خطرناک است.
مثال:
{
gateway: {
controlUi: {
allowedOrigins: ["http://localhost:5173"],
},
},
}
جزئیات راهاندازی دسترسی راهدور: دسترسی راهدور.
مرتبط
- داشبورد — داشبورد Gateway
- بررسیهای سلامت — پایش سلامت Gateway
- TUI — رابط کاربری ترمینال
- WebChat — رابط گفتوگوی مبتنی بر مرورگر