Web interfaces
UI Kontrol
UI Kontrol adalah aplikasi satu halaman Vite + Lit kecil yang disajikan oleh Gateway:
- default:
http://<host>:18789/ - prefiks opsional: atur
gateway.controlUi.basePath(mis./openclaw)
Aplikasi ini berbicara langsung ke WebSocket Gateway pada port yang sama.
Buka cepat (lokal)
Jika Gateway berjalan di komputer yang sama, buka:
Jika halaman gagal dimuat, jalankan Gateway terlebih dahulu: openclaw gateway.
Auth diberikan selama handshake WebSocket melalui:
connect.params.auth.tokenconnect.params.auth.password- header identitas Tailscale Serve saat
gateway.auth.allowTailscale: true - header identitas trusted-proxy saat
gateway.auth.mode: "trusted-proxy"
Panel pengaturan dasbor menyimpan token untuk sesi tab browser saat ini dan URL gateway yang dipilih; kata sandi tidak dipersistenkan. Onboarding biasanya menghasilkan token gateway untuk auth rahasia bersama pada koneksi pertama, tetapi auth kata sandi juga berfungsi saat gateway.auth.mode adalah "password".
Pairing perangkat (koneksi pertama)
Saat Anda terhubung ke UI Kontrol dari browser atau perangkat baru, Gateway biasanya memerlukan persetujuan pairing satu kali. Ini adalah langkah keamanan untuk mencegah akses tidak sah.
Yang akan Anda lihat: "terputus (1008): pairing required"
Cantumkan permintaan tertunda
openclaw devices list
Setujui berdasarkan ID permintaan
openclaw devices approve <requestId>
Jika browser mencoba ulang pairing dengan detail auth yang berubah (role/scopes/kunci publik), permintaan tertunda sebelumnya akan digantikan dan requestId baru dibuat. Jalankan ulang openclaw devices list sebelum persetujuan.
Jika browser sudah dipairing dan Anda mengubahnya dari akses baca ke akses tulis/admin, ini diperlakukan sebagai peningkatan persetujuan, bukan rekoneksi diam-diam. OpenClaw mempertahankan persetujuan lama tetap aktif, memblokir rekoneksi yang lebih luas, dan meminta Anda menyetujui kumpulan scope baru secara eksplisit.
Setelah disetujui, perangkat akan diingat dan tidak akan memerlukan persetujuan ulang kecuali Anda mencabutnya dengan openclaw devices revoke --device <id> --role <role>. Lihat CLI Perangkat untuk rotasi dan pencabutan token.
Identitas pribadi (lokal browser)
UI Kontrol mendukung identitas pribadi per browser (nama tampilan dan avatar) yang dilampirkan ke pesan keluar untuk atribusi dalam sesi bersama. Identitas ini berada di penyimpanan browser, terbatas pada profil browser saat ini, dan tidak disinkronkan ke perangkat lain atau dipersistenkan di sisi server di luar metadata kepenulisan transkrip normal pada pesan yang benar-benar Anda kirim. Menghapus data situs atau beralih browser akan meresetnya menjadi kosong.
Pola lokal browser yang sama berlaku untuk override avatar asisten. Avatar asisten yang diunggah menimpa identitas yang diselesaikan gateway hanya pada browser lokal dan tidak pernah melakukan round-trip melalui config.patch. Field config bersama ui.assistant.avatar tetap tersedia untuk klien non-UI yang menulis field tersebut secara langsung (seperti gateway berskrip atau dasbor kustom).
Endpoint config runtime
UI Kontrol mengambil pengaturan runtime-nya dari /__openclaw/control-ui-config.json. Endpoint tersebut dijaga oleh auth gateway yang sama seperti bagian permukaan HTTP lainnya: browser yang tidak terautentikasi tidak dapat mengambilnya, dan pengambilan yang berhasil memerlukan token/kata sandi gateway yang sudah valid, identitas Tailscale Serve, atau identitas trusted-proxy.
Dukungan bahasa
UI Kontrol dapat melokalkan dirinya sendiri saat pertama dimuat berdasarkan locale browser Anda. Untuk menggantinya nanti, buka Overview -> Gateway Access -> Language. Pemilih locale berada di kartu Gateway Access, bukan di bawah Appearance.
- Locale yang didukung:
en,zh-CN,zh-TW,pt-BR,de,es,ja-JP,ko,fr,ar,it,tr,uk,id,pl,th,vi,nl,fa - Terjemahan non-Inggris dimuat secara lazy di browser.
- Locale yang dipilih disimpan di penyimpanan browser dan digunakan ulang pada kunjungan berikutnya.
- Kunci terjemahan yang hilang fallback ke bahasa Inggris.
Terjemahan docs dihasilkan untuk set locale non-Inggris yang sama, tetapi pemilih bahasa bawaan situs docs Mintlify terbatas pada kode locale yang diterima Mintlify. Docs bahasa Thai (th) dan Persia (fa) tetap dihasilkan di repo publish; keduanya mungkin belum muncul di pemilih tersebut sampai Mintlify mendukung kode-kode itu.
Tema tampilan
Panel Appearance mempertahankan tema bawaan Claw, Knot, dan Dash, plus satu slot impor tweakcn lokal browser. Untuk mengimpor tema, buka editor tweakcn, pilih atau buat tema, klik Share, dan tempel tautan tema yang disalin ke Appearance. Pengimpor juga menerima URL registry https://tweakcn.com/r/themes/<id>, URL editor seperti https://tweakcn.com/editor/theme?theme=amethyst-haze, path relatif /themes/<id>, ID tema mentah, dan nama tema default seperti amethyst-haze.
Tema yang diimpor hanya disimpan di profil browser saat ini. Tema tidak ditulis ke config gateway dan tidak disinkronkan lintas perangkat. Mengganti tema yang diimpor memperbarui satu slot lokal; menghapusnya mengalihkan tema aktif kembali ke Claw jika tema yang diimpor sedang dipilih.
Yang dapat dilakukannya (saat ini)
Chat dan Talk
- Chat dengan model melalui Gateway WS (
chat.history,chat.send,chat.abort,chat.inject). - Refresh riwayat Chat meminta jendela terbaru yang dibatasi dengan batas teks per pesan agar sesi besar tidak memaksa browser merender payload transkrip penuh sebelum chat dapat digunakan.
- Talk melalui sesi realtime browser. OpenAI menggunakan WebRTC langsung, Google Live menggunakan token browser sekali pakai yang dibatasi melalui WebSocket, dan plugin suara realtime khusus backend menggunakan transport relay Gateway. Sesi provider milik klien dimulai dengan
talk.client.create; sesi relay Gateway dimulai dengantalk.session.create. Relay menjaga kredensial provider di Gateway sementara browser mengalirkan PCM mikrofon melaluitalk.session.appendAudiodan meneruskan panggilan tool provideropenclaw_agent_consultmelaluitalk.client.toolCalluntuk kebijakan Gateway dan model OpenClaw terkonfigurasi yang lebih besar. - Streaming panggilan tool + kartu output tool live di Chat (event agen).
Channel, instance, sesi, dream
- Channel: status channel bawaan plus plugin bundled/eksternal, login QR, dan config per channel (
channels.status,web.login.*,config.patch). - Refresh probe channel mempertahankan snapshot sebelumnya tetap terlihat saat pemeriksaan provider yang lambat selesai, dan snapshot parsial diberi label saat probe atau audit melampaui anggaran UI-nya.
- Instance: daftar presence + refresh (
system-presence). - Sesi: daftar + override model/thinking/fast/verbose/trace/reasoning per sesi (
sessions.list,sessions.patch). - Dream: status dreaming, toggle aktifkan/nonaktifkan, dan pembaca Dream Diary (
doctor.memory.status,doctor.memory.dreamDiary,config.patch).
Cron, Skills, node, persetujuan exec
- Tugas Cron: daftar/tambah/edit/jalankan/aktifkan/nonaktifkan + riwayat run (
cron.*). - Skills: status, aktifkan/nonaktifkan, install, pembaruan kunci API (
skills.*). - Node: daftar + caps (
node.list). - Persetujuan exec: edit allowlist gateway atau node + kebijakan tanya untuk
exec host=gateway/node(exec.approvals.*).
Config
- Lihat/edit
~/.openclaw/openclaw.json(config.get,config.set). - Terapkan + mulai ulang dengan validasi (
config.apply) dan bangunkan sesi aktif terakhir. - Penulisan menyertakan guard base-hash untuk mencegah penimpaan edit konkuren.
- Penulisan (
config.set/config.apply/config.patch) melakukan preflight resolusi SecretRef aktif untuk ref dalam payload config yang dikirim; ref terkirim aktif yang tidak terselesaikan ditolak sebelum penulisan. - Schema + rendering form (
config.schema/config.schema.lookup, termasuk fieldtitle/description, hint UI yang cocok, ringkasan child langsung, metadata docs pada node objek/wildcard/array/komposisi bertingkat, plus schema plugin + channel saat tersedia); editor Raw JSON hanya tersedia saat snapshot memiliki round-trip mentah yang aman. - Jika snapshot tidak dapat melakukan round-trip teks mentah dengan aman, UI Kontrol memaksa mode Form dan menonaktifkan mode Raw untuk snapshot tersebut.
- Editor Raw JSON "Reset to saved" mempertahankan bentuk yang ditulis mentah (formatting, komentar, layout
$include) alih-alih merender ulang snapshot yang diratakan, sehingga edit eksternal tetap bertahan setelah reset saat snapshot dapat melakukan round-trip dengan aman. - Nilai objek SecretRef terstruktur dirender read-only di input teks form untuk mencegah korupsi objek-ke-string yang tidak disengaja.
Debug, log, pembaruan
- Debug: snapshot status/health/model + log event + panggilan RPC manual (
status,health,models.list). - Log event mencakup timing refresh/RPC UI Kontrol, timing render chat/config yang lambat, dan entri responsivitas browser untuk frame animasi panjang atau tugas panjang saat browser mengekspos tipe entri PerformanceObserver tersebut.
- Log: live tail log file gateway dengan filter/ekspor (
logs.tail). - Update: jalankan pembaruan package/git + restart (
update.run) dengan laporan restart, lalu pollingupdate.statussetelah rekoneksi untuk memverifikasi versi gateway yang berjalan.
Catatan panel tugas Cron
- Untuk tugas terisolasi, delivery default mengumumkan ringkasan. Anda dapat beralih ke none jika menginginkan run internal saja.
- Field channel/target muncul saat announce dipilih.
- Mode Webhook menggunakan
delivery.mode = "webhook"dengandelivery.todiatur ke URL webhook HTTP(S) yang valid. - Untuk tugas main-session, mode delivery webhook dan none tersedia.
- Kontrol edit lanjutan mencakup delete-after-run, hapus override agen, opsi cron exact/stagger, override model/thinking agen, dan toggle delivery best-effort.
- Validasi form bersifat inline dengan error tingkat field; nilai tidak valid menonaktifkan tombol simpan sampai diperbaiki.
- Atur
cron.webhookTokenuntuk mengirim token bearer khusus; jika dihilangkan, webhook dikirim tanpa header auth. - Fallback usang: tugas legacy yang tersimpan dengan
notify: truemasih dapat menggunakancron.webhooksampai dimigrasikan.
Perilaku Chat
Send and history semantics
chat.sendbersifat non-blocking: perintah ini langsung mengirim ack dengan{ runId, status: "started" }dan respons dialirkan melalui eventchat.- Unggahan chat menerima gambar serta file non-video. Gambar mempertahankan path gambar native; file lain disimpan sebagai media terkelola dan ditampilkan di riwayat sebagai tautan lampiran.
- Mengirim ulang dengan
idempotencyKeyyang sama mengembalikan{ status: "in_flight" }saat masih berjalan, dan{ status: "ok" }setelah selesai. - Respons
chat.historydibatasi ukurannya demi keamanan UI. Ketika entri transkrip terlalu besar, Gateway dapat memangkas bidang teks panjang, menghilangkan blok metadata berat, dan mengganti pesan yang terlalu besar dengan placeholder ([chat.history omitted: message too large]). - Gambar asisten/tergenerasi dipertahankan sebagai referensi media terkelola dan disajikan kembali melalui URL media Gateway yang terautentikasi, sehingga pemuatan ulang tidak bergantung pada payload gambar base64 mentah yang tetap berada di respons riwayat chat.
- Saat merender
chat.history, Control UI menghapus tag direktif inline khusus tampilan dari teks asisten yang terlihat (misalnya[[reply_to_*]]dan[[audio_as_voice]]), payload XML panggilan alat teks biasa (termasuk<tool_call>...</tool_call>,<function_call>...</function_call>,<tool_calls>...</tool_calls>,<function_calls>...</function_calls>, dan blok panggilan alat yang terpotong), serta token kontrol model ASCII/lebar-penuh yang bocor, dan menghilangkan entri asisten yang seluruh teks terlihatnya hanya token senyap persisNO_REPLY/no_replyatau token pengakuan HeartbeatHEARTBEAT_OK. - Selama pengiriman aktif dan penyegaran riwayat akhir, tampilan chat menjaga pesan pengguna/asisten optimistis lokal tetap terlihat jika
chat.historysesaat mengembalikan snapshot yang lebih lama; transkrip kanonis menggantikan pesan lokal tersebut setelah riwayat Gateway menyusul. - Event
chatlangsung adalah status pengiriman, sedangkanchat.historydibangun ulang dari transkrip sesi yang persisten. Setelah event akhir alat, Control UI memuat ulang riwayat dan hanya menggabungkan ekor optimistis kecil; batas transkrip didokumentasikan di WebChat. chat.injectmenambahkan catatan asisten ke transkrip sesi dan menyiarkan eventchatuntuk pembaruan khusus UI (tanpa proses agen, tanpa pengiriman channel).- Header chat menampilkan filter agen sebelum pemilih sesi, dan pemilih sesi dibatasi oleh agen yang dipilih. Beralih agen hanya menampilkan sesi yang terikat ke agen tersebut dan kembali ke sesi utama agen tersebut saat belum memiliki sesi dasbor tersimpan.
- Pada lebar desktop, kontrol chat tetap berada dalam satu baris ringkas dan menciut saat menggulir turun transkrip; menggulir naik, kembali ke atas, atau mencapai bawah memulihkan kontrol.
- Pesan teks-saja duplikat berurutan dirender sebagai satu gelembung dengan lencana jumlah. Pesan yang membawa gambar, lampiran, output alat, atau pratinjau canvas dibiarkan tidak diciutkan.
- Pemilih model dan thinking di header chat langsung mem-patch sesi aktif melalui
sessions.patch; keduanya adalah override sesi persisten, bukan opsi kirim satu giliran saja. - Mengetik
/newdi Control UI membuat dan beralih ke sesi dasbor baru yang sama seperti Chat Baru. Mengetik/resetmempertahankan reset eksplisit di tempat milik Gateway untuk sesi saat ini. - Pemilih model chat meminta tampilan model terkonfigurasi milik Gateway. Jika
agents.defaults.modelsada, allowlist tersebut mengendalikan pemilih. Jika tidak, pemilih menampilkan entri eksplisitmodels.providers.*.modelsserta provider dengan autentikasi yang dapat digunakan. Katalog lengkap tetap tersedia melalui RPC debugmodels.listdenganview: "all". - Saat laporan penggunaan sesi Gateway terbaru menunjukkan tekanan konteks yang tinggi, area composer chat menampilkan pemberitahuan konteks dan, pada level Compaction yang direkomendasikan, tombol ringkas yang menjalankan jalur Compaction sesi normal. Snapshot token basi disembunyikan sampai Gateway melaporkan penggunaan terbaru lagi.
Talk mode (browser realtime)
Mode bicara menggunakan provider suara realtime terdaftar. Konfigurasikan OpenAI dengan talk.realtime.provider: "openai" plus talk.realtime.providers.openai.apiKey, atau konfigurasikan Google dengan talk.realtime.provider: "google" plus talk.realtime.providers.google.apiKey. Browser tidak pernah menerima kunci API provider standar. OpenAI menerima rahasia klien Realtime sementara untuk WebRTC. Google Live menerima token autentikasi Live API terbatas sekali pakai untuk sesi WebSocket browser, dengan instruksi dan deklarasi alat yang dikunci ke dalam token oleh Gateway. Provider yang hanya mengekspos bridge realtime backend berjalan melalui transport relay Gateway, sehingga kredensial dan socket vendor tetap berada di sisi server sementara audio browser bergerak melalui RPC Gateway terautentikasi. Prompt sesi Realtime disusun oleh Gateway; talk.client.create tidak menerima override instruksi yang disediakan pemanggil.
Di composer Chat, kontrol Talk adalah tombol gelombang di sebelah tombol dikte mikrofon. Saat Talk dimulai, baris status composer menampilkan Connecting Talk..., lalu Talk live saat audio tersambung, atau Asking OpenClaw... saat panggilan alat realtime berkonsultasi dengan model lebih besar yang dikonfigurasi melalui talk.client.toolCall.
Smoke live maintainer: OPENAI_API_KEY=... GEMINI_API_KEY=... node --import tsx scripts/dev/realtime-talk-live-smoke.ts memverifikasi pertukaran SDP WebRTC browser OpenAI, penyiapan WebSocket browser token terbatas Google Live, dan adapter browser relay Gateway dengan media mikrofon palsu. Perintah ini hanya mencetak status provider dan tidak mencatat rahasia.
Stop and abort
- Klik Stop (memanggil
chat.abort). - Saat proses berjalan aktif, tindak lanjut normal masuk antrean. Klik Steer pada pesan antrean untuk menyuntikkan tindak lanjut tersebut ke giliran yang sedang berjalan.
- Ketik
/stop(atau frasa abort mandiri sepertistop,stop action,stop run,stop openclaw,please stop) untuk abort di luar jalur. chat.abortmendukung{ sessionKey }(tanparunId) untuk meng-abort semua proses aktif untuk sesi tersebut.
Abort partial retention
- Saat proses di-abort, teks asisten parsial masih dapat ditampilkan di UI.
- Gateway mempertahankan teks asisten parsial yang di-abort ke dalam riwayat transkrip saat output buffered ada.
- Entri yang dipertahankan menyertakan metadata abort sehingga konsumen transkrip dapat membedakan parsial abort dari output penyelesaian normal.
Instalasi PWA dan web push
Control UI mengirimkan manifest.webmanifest dan service worker, sehingga browser modern dapat menginstalnya sebagai PWA mandiri. Web Push memungkinkan Gateway membangunkan PWA terinstal dengan notifikasi bahkan saat tab atau jendela browser tidak terbuka.
| Permukaan | Fungsinya |
|---|---|
ui/public/manifest.webmanifest |
Manifest PWA. Browser menawarkan "Instal aplikasi" setelah dapat dijangkau. |
ui/public/sw.js |
Service worker yang menangani event push dan klik notifikasi. |
push/vapid-keys.json (di bawah dir status OpenClaw) |
Pasangan kunci VAPID yang dibuat otomatis untuk menandatangani payload Web Push. |
push/web-push-subscriptions.json |
Endpoint langganan browser yang dipertahankan. |
Override pasangan kunci VAPID melalui env var pada proses Gateway saat Anda ingin mem-pin kunci (untuk deployment multi-host, rotasi rahasia, atau pengujian):
OPENCLAW_VAPID_PUBLIC_KEYOPENCLAW_VAPID_PRIVATE_KEYOPENCLAW_VAPID_SUBJECT(default kemailto:openclaw@localhost)
Control UI menggunakan metode Gateway berbatas scope ini untuk mendaftarkan dan menguji langganan browser:
push.web.vapidPublicKey— mengambil kunci publik VAPID aktif.push.web.subscribe— mendaftarkanendpointpluskeys.p256dh/keys.auth.push.web.unsubscribe— menghapus endpoint terdaftar.push.web.test— mengirim notifikasi uji ke langganan pemanggil.
Embed yang di-host
Pesan asisten dapat merender konten web yang di-host secara inline dengan shortcode [embed ...]. Kebijakan sandbox iframe dikendalikan oleh gateway.controlUi.embedSandbox:
strict
Menonaktifkan eksekusi skrip di dalam embed yang di-host.
scripts (default)
Mengizinkan embed interaktif sambil mempertahankan isolasi origin; ini adalah default dan biasanya cukup untuk game/widget browser mandiri.
trusted
Menambahkan allow-same-origin di atas allow-scripts untuk dokumen same-site yang sengaja membutuhkan privilege lebih kuat.
Contoh:
{
gateway: {
controlUi: {
embedSandbox: "scripts",
},
},
}
URL embed http(s) eksternal absolut tetap diblokir secara default. Jika Anda sengaja ingin [embed url="https://..."] memuat halaman pihak ketiga, setel gateway.controlUi.allowExternalEmbedUrls: true.
Lebar pesan chat
Pesan chat tergabung menggunakan max-width default yang mudah dibaca. Deployment monitor lebar dapat meng-override ini tanpa mem-patch CSS bundled dengan menyetel gateway.controlUi.chatMessageMaxWidth:
{
gateway: {
controlUi: {
chatMessageMaxWidth: "min(1280px, 82%)",
},
},
}
Nilai divalidasi sebelum mencapai browser. Nilai yang didukung mencakup panjang dan persentase biasa seperti 960px atau 82%, plus ekspresi lebar min(...), max(...), clamp(...), calc(...), dan fit-content(...) yang dibatasi.
Akses tailnet (direkomendasikan)
Integrated Tailscale Serve (preferred)
Pertahankan Gateway pada loopback dan biarkan Tailscale Serve mem-proxy-nya dengan HTTPS:
openclaw gateway --tailscale serve
Buka:
https://<magicdns>/(ataugateway.controlUi.basePathyang Anda konfigurasi)
Secara default, permintaan Control UI/WebSocket Serve dapat berautentikasi melalui header identitas Tailscale (tailscale-user-login) saat gateway.auth.allowTailscale bernilai true. OpenClaw memverifikasi identitas dengan menyelesaikan alamat x-forwarded-for menggunakan tailscale whois dan mencocokkannya ke header, dan hanya menerimanya saat permintaan mengenai loopback dengan header x-forwarded-* Tailscale. Untuk sesi operator Control UI dengan identitas perangkat browser, jalur Serve terverifikasi ini juga melewati round trip pairing perangkat; browser tanpa perangkat dan koneksi peran node tetap mengikuti pemeriksaan perangkat normal. Setel gateway.auth.allowTailscale: false jika Anda ingin mewajibkan kredensial rahasia bersama eksplisit bahkan untuk traffic Serve. Lalu gunakan gateway.auth.mode: "token" atau "password".
Untuk jalur identitas Serve async tersebut, percobaan autentikasi gagal untuk IP klien dan scope auth yang sama diserialisasi sebelum penulisan rate-limit. Karena itu, retry buruk bersamaan dari browser yang sama dapat menampilkan retry later pada permintaan kedua, bukan dua mismatch biasa yang berpacu secara paralel.
Bind to tailnet + token
openclaw gateway --bind tailnet --token "$(openssl rand -hex 32)"
Lalu buka:
http://<tailscale-ip>:18789/(ataugateway.controlUi.basePathyang Anda konfigurasi)
Tempelkan rahasia bersama yang cocok ke pengaturan UI (dikirim sebagai connect.params.auth.token atau connect.params.auth.password).
HTTP Tidak Aman
Jika Anda membuka dasbor melalui HTTP biasa (http://<lan-ip> atau http://<tailscale-ip>), browser berjalan dalam konteks tidak aman dan memblokir WebCrypto. Secara default, OpenClaw memblokir koneksi UI Kontrol tanpa identitas perangkat.
Pengecualian yang didokumentasikan:
- kompatibilitas HTTP tidak aman khusus localhost dengan
gateway.controlUi.allowInsecureAuth=true - autentikasi UI Kontrol operator yang berhasil melalui
gateway.auth.mode: "trusted-proxy" - darurat
gateway.controlUi.dangerouslyDisableDeviceAuth=true
Perbaikan yang direkomendasikan: gunakan HTTPS (Tailscale Serve) atau buka UI secara lokal:
https://<magicdns>/(Serve)http://127.0.0.1:18789/(di host gateway)
Perilaku tombol autentikasi tidak aman
{
gateway: {
controlUi: { allowInsecureAuth: true },
bind: "tailnet",
auth: { mode: "token", token: "replace-me" },
},
}
allowInsecureAuth hanyalah tombol kompatibilitas lokal:
- Ini mengizinkan sesi UI Kontrol localhost untuk berlanjut tanpa identitas perangkat dalam konteks HTTP tidak aman.
- Ini tidak melewati pemeriksaan pairing.
- Ini tidak melonggarkan persyaratan identitas perangkat jarak jauh (non-localhost).
Hanya untuk darurat
{
gateway: {
controlUi: { dangerouslyDisableDeviceAuth: true },
bind: "tailnet",
auth: { mode: "token", token: "replace-me" },
},
}
Catatan proxy tepercaya
- Autentikasi trusted-proxy yang berhasil dapat menerima sesi UI Kontrol operator tanpa identitas perangkat.
- Ini tidak berlaku untuk sesi UI Kontrol peran node.
- Proxy balik loopback pada host yang sama tetap tidak memenuhi autentikasi trusted-proxy; lihat Autentikasi proxy tepercaya.
Lihat Tailscale untuk panduan penyiapan HTTPS.
Kebijakan keamanan konten
UI Kontrol dikirim dengan kebijakan img-src yang ketat: hanya aset same-origin, URL data:, dan URL blob: yang dibuat secara lokal yang diizinkan. URL gambar http(s) jarak jauh dan relatif protokol ditolak oleh browser dan tidak memicu pengambilan jaringan.
Artinya dalam praktik:
- Avatar dan gambar yang disajikan di bawah path relatif (misalnya
/avatars/<id>) tetap dirender, termasuk rute avatar terautentikasi yang diambil UI dan dikonversi menjadi URLblob:lokal. - URL
data:image/...inline tetap dirender (berguna untuk payload dalam protokol). - URL
blob:lokal yang dibuat oleh UI Kontrol tetap dirender. - URL avatar jarak jauh yang dikeluarkan oleh metadata channel dihapus di helper avatar UI Kontrol dan diganti dengan logo/badge bawaan, sehingga channel yang disusupi atau berbahaya tidak dapat memaksa pengambilan gambar jarak jauh sembarang dari browser operator.
Anda tidak perlu mengubah apa pun untuk mendapatkan perilaku ini — perilaku ini selalu aktif dan tidak dapat dikonfigurasi.
Autentikasi rute avatar
Saat autentikasi gateway dikonfigurasi, endpoint avatar UI Kontrol memerlukan token gateway yang sama dengan API lainnya:
GET /avatar/<agentId>mengembalikan gambar avatar hanya kepada pemanggil yang terautentikasi.GET /avatar/<agentId>?meta=1mengembalikan metadata avatar dengan aturan yang sama.- Permintaan tidak terautentikasi ke salah satu rute ditolak (sesuai dengan rute assistant-media yang setara). Ini mencegah rute avatar membocorkan identitas agen pada host yang selain itu terlindungi.
- UI Kontrol sendiri meneruskan token gateway sebagai header bearer saat mengambil avatar, dan menggunakan URL blob terautentikasi agar gambar tetap dirender di dasbor.
Jika Anda menonaktifkan autentikasi gateway (tidak direkomendasikan pada host bersama), rute avatar juga menjadi tidak terautentikasi, sejalan dengan gateway lainnya.
Autentikasi rute media asisten
Saat autentikasi gateway dikonfigurasi, pratinjau media lokal asisten menggunakan rute dua langkah:
GET /__openclaw__/assistant-media?meta=1&source=<path>memerlukan autentikasi operator UI Kontrol normal. Browser mengirim token gateway sebagai header bearer saat memeriksa ketersediaan.- Respons metadata yang berhasil menyertakan
mediaTicketberumur pendek yang dibatasi ke path sumber persis tersebut. - URL gambar, audio, video, dan dokumen yang dirender browser menggunakan
mediaTicket=<ticket>alih-alih token atau kata sandi gateway aktif. Tiket cepat kedaluwarsa dan tidak dapat mengotorisasi sumber lain.
Ini menjaga rendering media normal tetap kompatibel dengan elemen media native browser tanpa menaruh kredensial gateway yang dapat digunakan ulang di URL media yang terlihat.
Membangun UI
Gateway menyajikan file statis dari dist/control-ui. Bangun dengan:
pnpm ui:build
Basis absolut opsional (saat Anda menginginkan URL aset tetap):
OPENCLAW_CONTROL_UI_BASE_PATH=/openclaw/ pnpm ui:build
Untuk pengembangan lokal (server dev terpisah):
pnpm ui:dev
Lalu arahkan UI ke URL WS Gateway Anda (mis. ws://127.0.0.1:18789).
Debugging/pengujian: server dev + Gateway jarak jauh
UI Kontrol adalah file statis; target WebSocket dapat dikonfigurasi dan dapat berbeda dari origin HTTP. Ini berguna saat Anda menginginkan server dev Vite secara lokal tetapi Gateway berjalan di tempat lain.
Mulai server dev UI
pnpm ui:dev
Buka dengan gatewayUrl
http://localhost:5173/?gatewayUrl=ws%3A%2F%2F<gateway-host>%3A18789
Autentikasi satu kali opsional (jika diperlukan):
http://localhost:5173/?gatewayUrl=wss%3A%2F%2F<gateway-host>%3A18789#token=<gateway-token>
Catatan
gatewayUrldisimpan di localStorage setelah dimuat dan dihapus dari URL.- Jika Anda meneruskan endpoint
ws://atauwss://lengkap melaluigatewayUrl, encode nilaigatewayUrlsebagai URL agar browser mengurai string kueri dengan benar. tokensebaiknya diteruskan melalui fragmen URL (#token=...) bila memungkinkan. Fragmen tidak dikirim ke server, sehingga menghindari kebocoran log permintaan dan Referer. Param kueri lama?token=masih diimpor satu kali untuk kompatibilitas, tetapi hanya sebagai fallback, dan segera dihapus setelah bootstrap.passwordhanya disimpan dalam memori.- Saat
gatewayUrlditetapkan, UI tidak melakukan fallback ke kredensial konfigurasi atau lingkungan. Berikantoken(ataupassword) secara eksplisit. Kredensial eksplisit yang hilang adalah error. - Gunakan
wss://saat Gateway berada di belakang TLS (Tailscale Serve, proxy HTTPS, dll.). gatewayUrlhanya diterima di jendela tingkat atas (bukan tertanam) untuk mencegah clickjacking.- Deployment UI Kontrol non-loopback harus menetapkan
gateway.controlUi.allowedOriginssecara eksplisit (origin lengkap). Ini mencakup penyiapan dev jarak jauh. - Startup Gateway dapat menanam origin lokal seperti
http://localhost:<port>danhttp://127.0.0.1:<port>dari bind dan port runtime efektif, tetapi origin browser jarak jauh tetap memerlukan entri eksplisit. - Jangan gunakan
gateway.controlUi.allowedOrigins: ["*"]kecuali untuk pengujian lokal yang dikontrol ketat. Itu berarti mengizinkan origin browser apa pun, bukan "cocokkan host apa pun yang saya gunakan." gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=truemengaktifkan mode fallback origin header Host, tetapi ini adalah mode keamanan yang berbahaya.
Contoh:
{
gateway: {
controlUi: {
allowedOrigins: ["http://localhost:5173"],
},
},
}
Detail penyiapan akses jarak jauh: Akses jarak jauh.
Terkait
- Dasbor — dasbor gateway
- Pemeriksaan Kesehatan — pemantauan kesehatan gateway
- TUI — antarmuka pengguna terminal
- WebChat — antarmuka chat berbasis browser