Web interfaces

Giao diện điều khiển

Giao diện điều khiển là một ứng dụng một trang Vite + Lit nhỏ được Gateway phục vụ:

  • mặc định: http://<host>:18789/
  • tiền tố tùy chọn: đặt gateway.controlUi.basePath (ví dụ: /openclaw)

Nó giao tiếp trực tiếp với Gateway WebSocket trên cùng cổng.

Mở nhanh (cục bộ)

Nếu Gateway đang chạy trên cùng máy tính, hãy mở:

Nếu trang không tải được, hãy khởi động Gateway trước: openclaw gateway.

Xác thực được cung cấp trong quá trình bắt tay WebSocket qua:

  • connect.params.auth.token
  • connect.params.auth.password
  • tiêu đề danh tính Tailscale Serve khi gateway.auth.allowTailscale: true
  • tiêu đề danh tính trusted-proxy khi gateway.auth.mode: "trusted-proxy"

Bảng cài đặt của bảng điều khiển giữ một token cho phiên tab trình duyệt hiện tại và URL gateway đã chọn; mật khẩu không được lưu lại. Quy trình thiết lập ban đầu thường tạo một gateway token cho xác thực shared-secret trong lần kết nối đầu tiên, nhưng xác thực bằng mật khẩu cũng hoạt động khi gateway.auth.mode"password".

Ghép nối thiết bị (kết nối đầu tiên)

Khi bạn kết nối tới Giao diện điều khiển từ trình duyệt hoặc thiết bị mới, Gateway thường yêu cầu phê duyệt ghép nối một lần. Đây là biện pháp bảo mật để ngăn truy cập trái phép.

Bạn sẽ thấy: "đã ngắt kết nối (1008): yêu cầu ghép nối"

  • Liệt kê các yêu cầu đang chờ

    openclaw devices list
    
  • Phê duyệt bằng ID yêu cầu

    openclaw devices approve <requestId>
    
  • Nếu trình duyệt thử ghép nối lại với chi tiết xác thực đã thay đổi (vai trò/phạm vi/khóa công khai), yêu cầu đang chờ trước đó sẽ bị thay thế và một requestId mới được tạo. Chạy lại openclaw devices list trước khi phê duyệt.

    Nếu trình duyệt đã được ghép nối và bạn đổi từ quyền truy cập đọc sang quyền truy cập ghi/quản trị, việc này được xử lý như một nâng cấp phê duyệt, không phải kết nối lại âm thầm. OpenClaw giữ phê duyệt cũ vẫn hoạt động, chặn lần kết nối lại với quyền rộng hơn, và yêu cầu bạn phê duyệt rõ ràng bộ phạm vi mới.

    Sau khi được phê duyệt, thiết bị sẽ được ghi nhớ và sẽ không cần phê duyệt lại trừ khi bạn thu hồi bằng openclaw devices revoke --device <id> --role <role>. Xem CLI thiết bị để biết cách xoay vòng và thu hồi token.

    Danh tính cá nhân (cục bộ theo trình duyệt)

    Giao diện điều khiển hỗ trợ danh tính cá nhân theo từng trình duyệt (tên hiển thị và ảnh đại diện) được gắn vào tin nhắn gửi đi để ghi nhận tác giả trong các phiên dùng chung. Danh tính này nằm trong bộ nhớ trình duyệt, được giới hạn trong hồ sơ trình duyệt hiện tại, và không được đồng bộ sang thiết bị khác hoặc lưu lâu dài phía máy chủ ngoài siêu dữ liệu tác giả bản ghi thông thường trên các tin nhắn bạn thực sự gửi. Việc xóa dữ liệu trang hoặc đổi trình duyệt sẽ đặt lại thành trống.

    Mẫu cục bộ theo trình duyệt tương tự áp dụng cho phần ghi đè ảnh đại diện trợ lý. Ảnh đại diện trợ lý đã tải lên chỉ phủ lên danh tính do gateway phân giải trong trình duyệt cục bộ và không bao giờ đi vòng qua config.patch. Trường cấu hình dùng chung ui.assistant.avatar vẫn có sẵn cho các máy khách không phải UI ghi trực tiếp vào trường này (chẳng hạn gateway theo script hoặc bảng điều khiển tùy chỉnh).

    Endpoint cấu hình runtime

    Giao diện điều khiển lấy cài đặt runtime từ /__openclaw/control-ui-config.json. Endpoint đó được bảo vệ bởi cùng cơ chế xác thực gateway như phần còn lại của bề mặt HTTP: trình duyệt chưa xác thực không thể lấy dữ liệu, và một lần lấy dữ liệu thành công yêu cầu gateway token/mật khẩu đã hợp lệ, danh tính Tailscale Serve, hoặc danh tính trusted-proxy.

    Hỗ trợ ngôn ngữ

    Giao diện điều khiển có thể tự bản địa hóa trong lần tải đầu tiên dựa trên locale của trình duyệt. Để ghi đè sau đó, mở Tổng quan -> Truy cập Gateway -> Ngôn ngữ. Bộ chọn locale nằm trong thẻ Truy cập Gateway, không nằm dưới Giao diện.

    • Locale được hỗ trợ: en, zh-CN, zh-TW, pt-BR, de, es, ja-JP, ko, fr, ar, it, tr, uk, id, pl, th, vi, nl, fa
    • Bản dịch không phải tiếng Anh được tải lười trong trình duyệt.
    • Locale đã chọn được lưu trong bộ nhớ trình duyệt và dùng lại trong các lần truy cập sau.
    • Khóa bản dịch bị thiếu sẽ rơi về tiếng Anh.

    Bản dịch tài liệu được tạo cho cùng bộ locale không phải tiếng Anh, nhưng bộ chọn ngôn ngữ Mintlify tích hợp của trang tài liệu bị giới hạn ở các mã locale mà Mintlify chấp nhận. Tài liệu tiếng Thái (th) và tiếng Ba Tư (fa) vẫn được tạo trong repo xuất bản; chúng có thể không xuất hiện trong bộ chọn đó cho đến khi Mintlify hỗ trợ các mã này.

    Chủ đề giao diện

    Bảng Giao diện giữ các chủ đề Claw, Knot và Dash tích hợp sẵn, cộng với một ô nhập tweakcn cục bộ theo trình duyệt. Để nhập một chủ đề, mở trình chỉnh sửa tweakcn, chọn hoặc tạo một chủ đề, nhấp Chia sẻ, và dán liên kết chủ đề đã sao chép vào Giao diện. Bộ nhập cũng chấp nhận URL registry https://tweakcn.com/r/themes/<id>, URL trình chỉnh sửa như https://tweakcn.com/editor/theme?theme=amethyst-haze, đường dẫn tương đối /themes/<id>, ID chủ đề thô, và tên chủ đề mặc định như amethyst-haze.

    Chủ đề đã nhập chỉ được lưu trong hồ sơ trình duyệt hiện tại. Chúng không được ghi vào cấu hình gateway và không đồng bộ giữa các thiết bị. Thay thế chủ đề đã nhập sẽ cập nhật một ô cục bộ đó; xóa nó sẽ chuyển chủ đề đang hoạt động về Claw nếu chủ đề đã nhập đang được chọn.

    Những gì nó có thể làm (hiện tại)

    Trò chuyện và nói chuyện
    • Trò chuyện với mô hình qua Gateway WS (chat.history, chat.send, chat.abort, chat.inject).
    • Làm mới lịch sử trò chuyện yêu cầu một cửa sổ gần đây có giới hạn với giới hạn văn bản theo từng tin nhắn, để các phiên lớn không buộc trình duyệt phải render toàn bộ payload bản ghi trước khi trò chuyện trở nên dùng được.
    • Nói chuyện qua các phiên realtime của trình duyệt. OpenAI dùng WebRTC trực tiếp, Google Live dùng token trình duyệt một lần bị giới hạn qua WebSocket, và các plugin giọng nói realtime chỉ backend dùng giao thức chuyển tiếp Gateway. Các phiên nhà cung cấp do máy khách sở hữu bắt đầu bằng talk.client.create; các phiên chuyển tiếp Gateway bắt đầu bằng talk.session.create. Bộ chuyển tiếp giữ thông tin xác thực nhà cung cấp trên Gateway trong khi trình duyệt stream PCM từ micro qua talk.session.appendAudio và chuyển tiếp các lệnh gọi công cụ nhà cung cấp openclaw_agent_consult qua talk.client.toolCall cho chính sách Gateway và mô hình OpenClaw lớn hơn đã cấu hình.
    • Stream lệnh gọi công cụ + thẻ đầu ra công cụ trực tiếp trong Trò chuyện (sự kiện tác tử).
    Kênh, instance, phiên, dream
    • Kênh: trạng thái kênh tích hợp sẵn cùng plugin đóng gói/bên ngoài, đăng nhập QR, và cấu hình theo kênh (channels.status, web.login.*, config.patch).
    • Làm mới thăm dò kênh giữ ảnh chụp trước đó hiển thị trong khi các kiểm tra nhà cung cấp chậm hoàn tất, và ảnh chụp một phần được gắn nhãn khi một lượt thăm dò hoặc kiểm tra vượt quá ngân sách UI.
    • Instance: danh sách hiện diện + làm mới (system-presence).
    • Phiên: danh sách + ghi đè theo phiên cho model/thinking/fast/verbose/trace/reasoning (sessions.list, sessions.patch).
    • Dream: trạng thái dreaming, công tắc bật/tắt, và trình đọc Nhật ký Dream (doctor.memory.status, doctor.memory.dreamDiary, config.patch).
    Cron, Skills, Node, phê duyệt exec
    • Tác vụ Cron: liệt kê/thêm/sửa/chạy/bật/tắt + lịch sử chạy (cron.*).
    • Skills: trạng thái, bật/tắt, cài đặt, cập nhật khóa API (skills.*).
    • Node: danh sách + giới hạn khả năng (node.list).
    • Phê duyệt exec: chỉnh sửa allowlist gateway hoặc node + chính sách hỏi cho exec host=gateway/node (exec.approvals.*).
    Cấu hình
    • Xem/sửa ~/.openclaw/openclaw.json (config.get, config.set).
    • Áp dụng + khởi động lại với xác thực (config.apply) và đánh thức phiên hoạt động gần nhất.
    • Thao tác ghi bao gồm bộ bảo vệ base-hash để tránh ghi đè các chỉnh sửa đồng thời.
    • Thao tác ghi (config.set/config.apply/config.patch) kiểm tra trước việc phân giải SecretRef đang hoạt động cho các ref trong payload cấu hình đã gửi; các ref đã gửi đang hoạt động nhưng không phân giải được sẽ bị từ chối trước khi ghi.
    • Schema + render biểu mẫu (config.schema / config.schema.lookup, bao gồm trường title / description, gợi ý UI khớp, tóm tắt con trực tiếp, siêu dữ liệu tài liệu trên các node object/wildcard/array/composition lồng nhau, cộng với schema plugin + kênh khi có); trình chỉnh sửa Raw JSON chỉ có sẵn khi ảnh chụp có vòng khứ hồi thô an toàn.
    • Nếu một ảnh chụp không thể đi vòng thô một cách an toàn, Giao diện điều khiển buộc chế độ Biểu mẫu và vô hiệu hóa chế độ Thô cho ảnh chụp đó.
    • "Đặt lại về bản đã lưu" của trình chỉnh sửa Raw JSON giữ nguyên hình dạng được soạn thô (định dạng, chú thích, bố cục $include) thay vì render lại một ảnh chụp đã làm phẳng, nên các chỉnh sửa bên ngoài vẫn sống sót sau khi đặt lại khi ảnh chụp có thể đi vòng an toàn.
    • Các giá trị object SecretRef có cấu trúc được render chỉ đọc trong đầu vào văn bản của biểu mẫu để ngăn vô tình làm hỏng object thành chuỗi.
    Gỡ lỗi, nhật ký, cập nhật
    • Gỡ lỗi: ảnh chụp trạng thái/sức khỏe/mô hình + nhật ký sự kiện + lệnh gọi RPC thủ công (status, health, models.list).
    • Nhật ký sự kiện bao gồm thời gian làm mới/RPC của Giao diện điều khiển, thời gian render trò chuyện/cấu hình chậm, và các mục độ phản hồi của trình duyệt cho frame hoạt ảnh dài hoặc tác vụ dài khi trình duyệt cung cấp các loại mục PerformanceObserver đó.
    • Nhật ký: theo dõi trực tiếp nhật ký tệp gateway với lọc/xuất (logs.tail).
    • Cập nhật: chạy cập nhật package/git + khởi động lại (update.run) với báo cáo khởi động lại, sau đó thăm dò update.status sau khi kết nối lại để xác minh phiên bản gateway đang chạy.
    Ghi chú bảng tác vụ Cron
    • Với tác vụ cô lập, gửi mặc định là thông báo tóm tắt. Bạn có thể chuyển sang không gửi nếu muốn các lần chạy chỉ nội bộ.
    • Trường kênh/đích xuất hiện khi thông báo được chọn.
    • Chế độ Webhook dùng delivery.mode = "webhook" với delivery.to được đặt thành một URL Webhook HTTP(S) hợp lệ.
    • Với tác vụ phiên chính, các chế độ gửi Webhook và không gửi đều có sẵn.
    • Điều khiển chỉnh sửa nâng cao bao gồm xóa sau khi chạy, xóa ghi đè tác tử, tùy chọn cron chính xác/rải thời gian, ghi đè model/thinking của tác tử, và công tắc gửi best-effort.
    • Xác thực biểu mẫu nằm inline với lỗi cấp trường; giá trị không hợp lệ sẽ vô hiệu hóa nút lưu cho đến khi được sửa.
    • Đặt cron.webhookToken để gửi bearer token chuyên dụng; nếu bỏ qua, Webhook được gửi không có tiêu đề xác thực.
    • Dự phòng đã ngừng dùng: các tác vụ legacy đã lưu với notify: true vẫn có thể dùng cron.webhook cho đến khi được di chuyển.

    Hành vi trò chuyện

    Ngữ nghĩa gửi và lịch sử
    • chat.sendkhông chặn: nó xác nhận ngay với { runId, status: "started" } và phản hồi được truyền trực tuyến qua các sự kiện chat.
    • Tải lên trong trò chuyện chấp nhận hình ảnh cùng các tệp không phải video. Hình ảnh giữ đường dẫn hình ảnh gốc; các tệp khác được lưu dưới dạng phương tiện được quản lý và hiển thị trong lịch sử dưới dạng liên kết tệp đính kèm.
    • Gửi lại với cùng idempotencyKey trả về { status: "in_flight" } khi đang chạy, và { status: "ok" } sau khi hoàn tất.
    • Phản hồi chat.history được giới hạn kích thước để an toàn cho UI. Khi các mục bản ghi hội thoại quá lớn, Gateway có thể cắt bớt các trường văn bản dài, bỏ qua các khối siêu dữ liệu nặng, và thay thế các tin nhắn quá cỡ bằng một placeholder ([chat.history omitted: message too large]).
    • Hình ảnh do trợ lý/tạo sinh tạo ra được lưu bền dưới dạng tham chiếu phương tiện được quản lý và được phục vụ lại qua URL phương tiện Gateway có xác thực, nên các lần tải lại không phụ thuộc vào việc payload hình ảnh base64 thô vẫn còn trong phản hồi lịch sử trò chuyện.
    • Khi kết xuất chat.history, Control UI loại bỏ các thẻ chỉ thị nội tuyến chỉ dùng để hiển thị khỏi văn bản trợ lý nhìn thấy được (ví dụ [[reply_to_*]][[audio_as_voice]]), các payload XML lời gọi công cụ dạng văn bản thuần (bao gồm <tool_call>...</tool_call>, <function_call>...</function_call>, <tool_calls>...</tool_calls>, <function_calls>...</function_calls>, và các khối lời gọi công cụ bị cắt ngắn), cùng các token điều khiển mô hình ASCII/toàn chiều bị rò rỉ, và bỏ qua các mục trợ lý mà toàn bộ văn bản nhìn thấy được chỉ là token im lặng chính xác NO_REPLY / no_reply hoặc token xác nhận Heartbeat HEARTBEAT_OK.
    • Trong khi một lần gửi đang hoạt động và lần làm mới lịch sử cuối cùng, khung xem trò chuyện giữ các tin nhắn người dùng/trợ lý lạc quan cục bộ hiển thị nếu chat.history trong chốc lát trả về một ảnh chụp cũ hơn; bản ghi hội thoại chuẩn sẽ thay thế các tin nhắn cục bộ đó khi lịch sử Gateway bắt kịp.
    • Các sự kiện chat trực tiếp là trạng thái phân phối, trong khi chat.history được dựng lại từ bản ghi hội thoại phiên bền vững. Sau các sự kiện kết thúc công cụ, Control UI tải lại lịch sử và chỉ hợp nhất một phần đuôi lạc quan nhỏ; ranh giới bản ghi hội thoại được ghi tài liệu trong WebChat.
    • chat.inject thêm một ghi chú trợ lý vào bản ghi hội thoại phiên và phát một sự kiện chat cho các cập nhật chỉ dành cho UI (không chạy agent, không phân phối qua kênh).
    • Tiêu đề trò chuyện hiển thị bộ lọc agent trước bộ chọn phiên, và bộ chọn phiên được giới hạn theo agent đã chọn. Chuyển đổi agent chỉ hiển thị các phiên gắn với agent đó và quay về phiên chính của agent đó khi nó chưa có phiên bảng điều khiển đã lưu.
    • Trên chiều rộng desktop, các điều khiển trò chuyện ở trên một hàng nhỏ gọn và thu gọn khi cuộn xuống bản ghi hội thoại; cuộn lên, quay lại đầu trang, hoặc đến cuối sẽ khôi phục các điều khiển.
    • Các tin nhắn chỉ có văn bản trùng lặp liên tiếp được kết xuất thành một bong bóng với huy hiệu số lượng. Các tin nhắn mang hình ảnh, tệp đính kèm, đầu ra công cụ, hoặc bản xem trước canvas được giữ nguyên không thu gọn.
    • Bộ chọn mô hình và suy nghĩ ở tiêu đề trò chuyện vá phiên hoạt động ngay lập tức qua sessions.patch; chúng là các ghi đè phiên bền vững, không phải tùy chọn gửi chỉ cho một lượt.
    • /new trong Control UI tạo và chuyển sang cùng phiên bảng điều khiển mới như New Chat. Gõ /reset giữ thao tác đặt lại tại chỗ rõ ràng của Gateway cho phiên hiện tại.
    • Bộ chọn mô hình trò chuyện yêu cầu khung nhìn mô hình đã cấu hình của Gateway. Nếu có agents.defaults.models, danh sách cho phép đó điều khiển bộ chọn. Nếu không, bộ chọn hiển thị các mục models.providers.*.models rõ ràng cộng với các nhà cung cấp có xác thực dùng được. Danh mục đầy đủ vẫn có sẵn qua RPC gỡ lỗi models.list với view: "all".
    • Khi báo cáo sử dụng phiên Gateway mới cho thấy áp lực ngữ cảnh cao, khu vực trình soạn trò chuyện hiển thị thông báo ngữ cảnh và, ở các mức Compaction được khuyến nghị, một nút nhỏ gọn chạy đường dẫn Compaction phiên bình thường. Các ảnh chụp token cũ được ẩn cho đến khi Gateway báo cáo mức sử dụng mới trở lại.
    Chế độ Talk (thời gian thực trên trình duyệt)

    Chế độ Talk sử dụng một nhà cung cấp thoại thời gian thực đã đăng ký. Cấu hình OpenAI với talk.realtime.provider: "openai" cộng với talk.realtime.providers.openai.apiKey, hoặc cấu hình Google với talk.realtime.provider: "google" cộng với talk.realtime.providers.google.apiKey. Trình duyệt không bao giờ nhận khóa API nhà cung cấp tiêu chuẩn. OpenAI nhận một bí mật máy khách Realtime tạm thời cho WebRTC. Google Live nhận một token xác thực Live API bị ràng buộc dùng một lần cho phiên WebSocket trình duyệt, với hướng dẫn và khai báo công cụ được Gateway khóa vào token. Các nhà cung cấp chỉ cung cấp cầu nối thời gian thực backend chạy qua transport chuyển tiếp Gateway, nên thông tin xác thực và socket của nhà cung cấp vẫn ở phía máy chủ trong khi âm thanh trình duyệt đi qua các RPC Gateway đã xác thực. Lời nhắc phiên Realtime được Gateway lắp ráp; talk.client.create không chấp nhận ghi đè hướng dẫn do bên gọi cung cấp.

    Trong trình soạn Chat, điều khiển Talk là nút sóng bên cạnh nút chính tả bằng micro. Khi Talk bắt đầu, hàng trạng thái trình soạn hiển thị Connecting Talk..., sau đó Talk live khi âm thanh đã kết nối, hoặc Asking OpenClaw... khi một lời gọi công cụ thời gian thực đang tham vấn mô hình lớn hơn đã cấu hình qua talk.client.toolCall.

    Smoke trực tiếp cho maintainer: OPENAI_API_KEY=... GEMINI_API_KEY=... node --import tsx scripts/dev/realtime-talk-live-smoke.ts xác minh trao đổi SDP WebRTC trình duyệt của OpenAI, thiết lập WebSocket trình duyệt bằng token bị ràng buộc của Google Live, và adapter trình duyệt chuyển tiếp Gateway với phương tiện micro giả. Lệnh chỉ in trạng thái nhà cung cấp và không ghi nhật ký bí mật.

    Dừng và hủy bỏ
    • Nhấp Dừng (gọi chat.abort).
    • Khi một lần chạy đang hoạt động, các lượt tiếp theo bình thường sẽ xếp hàng. Nhấp Điều hướng trên một tin nhắn đã xếp hàng để chèn lượt tiếp theo đó vào lượt đang chạy.
    • /stop (hoặc các cụm hủy bỏ độc lập như stop, stop action, stop run, stop openclaw, please stop) để hủy bỏ ngoài băng.
    • chat.abort hỗ trợ { sessionKey } (không có runId) để hủy bỏ tất cả các lần chạy đang hoạt động cho phiên đó.
    Giữ lại phần hủy bỏ chưa hoàn tất
    • Khi một lần chạy bị hủy bỏ, văn bản trợ lý chưa hoàn tất vẫn có thể được hiển thị trong UI.
    • Gateway lưu bền văn bản trợ lý chưa hoàn tất đã bị hủy bỏ vào lịch sử bản ghi hội thoại khi có đầu ra đã được đệm.
    • Các mục đã lưu bao gồm siêu dữ liệu hủy bỏ để người tiêu thụ bản ghi hội thoại có thể phân biệt phần hủy bỏ chưa hoàn tất với đầu ra hoàn tất bình thường.

    Cài đặt PWA và Web Push

    Control UI đi kèm một manifest.webmanifest và một service worker, nên các trình duyệt hiện đại có thể cài đặt nó dưới dạng PWA độc lập. Web Push cho phép Gateway đánh thức PWA đã cài đặt bằng thông báo ngay cả khi tab hoặc cửa sổ trình duyệt không mở.

    Bề mặt Chức năng
    ui/public/manifest.webmanifest Manifest PWA. Trình duyệt đề xuất "Cài đặt ứng dụng" khi có thể truy cập.
    ui/public/sw.js Service worker xử lý các sự kiện push và nhấp vào thông báo.
    push/vapid-keys.json (trong thư mục trạng thái OpenClaw) Cặp khóa VAPID được tự động tạo, dùng để ký payload Web Push.
    push/web-push-subscriptions.json Các endpoint đăng ký trình duyệt đã được lưu bền.

    Ghi đè cặp khóa VAPID thông qua biến môi trường trên tiến trình Gateway khi bạn muốn ghim khóa (cho triển khai nhiều máy chủ, xoay vòng bí mật, hoặc kiểm thử):

    • OPENCLAW_VAPID_PUBLIC_KEY
    • OPENCLAW_VAPID_PRIVATE_KEY
    • OPENCLAW_VAPID_SUBJECT (mặc định là mailto:openclaw@localhost)

    Control UI sử dụng các phương thức Gateway được giới hạn theo scope này để đăng ký và kiểm thử đăng ký trình duyệt:

    • push.web.vapidPublicKey — lấy khóa công khai VAPID đang hoạt động.
    • push.web.subscribe — đăng ký một endpoint cộng với keys.p256dh/keys.auth.
    • push.web.unsubscribe — xóa một endpoint đã đăng ký.
    • push.web.test — gửi thông báo kiểm thử tới đăng ký của bên gọi.

    Nhúng được lưu trữ

    Tin nhắn trợ lý có thể kết xuất nội dung web được lưu trữ nội tuyến bằng shortcode [embed ...]. Chính sách sandbox iframe được điều khiển bởi gateway.controlUi.embedSandbox:

    nghiêm ngặt

    Tắt thực thi script bên trong nội dung nhúng được lưu trữ.

    scripts (mặc định)

    Cho phép nội dung nhúng tương tác trong khi vẫn giữ cách ly origin; đây là mặc định và thường đủ cho các trò chơi/widget trình duyệt độc lập.

    đáng tin cậy

    Thêm allow-same-origin bên trên allow-scripts cho các tài liệu cùng site chủ ý cần đặc quyền mạnh hơn.

    Ví dụ:

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

    URL nhúng http(s) bên ngoài tuyệt đối vẫn bị chặn theo mặc định. Nếu bạn chủ ý muốn [embed url="https://..."] tải các trang bên thứ ba, hãy đặt gateway.controlUi.allowExternalEmbedUrls: true.

    Chiều rộng tin nhắn trò chuyện

    Các tin nhắn trò chuyện được nhóm dùng max-width mặc định dễ đọc. Triển khai trên màn hình rộng có thể ghi đè mà không cần vá CSS đi kèm bằng cách đặt gateway.controlUi.chatMessageMaxWidth:

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

    Giá trị được xác thực trước khi tới trình duyệt. Các giá trị được hỗ trợ bao gồm độ dài và phần trăm thuần như 960px hoặc 82%, cộng với các biểu thức chiều rộng bị ràng buộc min(...), max(...), clamp(...), calc(...), và fit-content(...).

    Truy cập tailnet (khuyến nghị)

    Tailscale Serve tích hợp (ưu tiên)

    Giữ Gateway trên loopback và để Tailscale Serve proxy nó bằng HTTPS:

    openclaw gateway --tailscale serve
    

    Mở:

    • https://<magicdns>/ (hoặc gateway.controlUi.basePath đã cấu hình của bạn)

    Theo mặc định, các yêu cầu Control UI/WebSocket Serve có thể xác thực qua header danh tính Tailscale (tailscale-user-login) khi gateway.auth.allowTailscaletrue. OpenClaw xác minh danh tính bằng cách phân giải địa chỉ x-forwarded-for với tailscale whois và khớp nó với header, và chỉ chấp nhận các yêu cầu này khi yêu cầu chạm tới loopback với các header x-forwarded-* của Tailscale. Với các phiên người vận hành Control UI có danh tính thiết bị trình duyệt, đường dẫn Serve đã xác minh này cũng bỏ qua vòng ghép đôi thiết bị; trình duyệt không có thiết bị và kết nối vai trò node vẫn theo các kiểm tra thiết bị bình thường. Đặt gateway.auth.allowTailscale: false nếu bạn muốn yêu cầu thông tin xác thực bằng bí mật dùng chung rõ ràng ngay cả với lưu lượng Serve. Sau đó dùng gateway.auth.mode: "token" hoặc "password".

    Với đường dẫn danh tính Serve bất đồng bộ đó, các lần xác thực thất bại cho cùng IP máy khách và scope xác thực được tuần tự hóa trước khi ghi giới hạn tốc độ. Vì vậy, các lần thử lại sai đồng thời từ cùng trình duyệt có thể hiển thị retry later trên yêu cầu thứ hai thay vì hai lỗi không khớp đơn thuần chạy đua song song.

    Bind tới tailnet + token

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

    Sau đó mở:

    • http://<tailscale-ip>:18789/ (hoặc gateway.controlUi.basePath đã cấu hình của bạn)

    Dán bí mật dùng chung tương ứng vào phần cài đặt UI (được gửi dưới dạng connect.params.auth.token hoặc connect.params.auth.password).

    HTTP không an toàn

    Nếu bạn mở bảng điều khiển qua HTTP thuần (http://<lan-ip> hoặc http://<tailscale-ip>), trình duyệt chạy trong một ngữ cảnh không bảo mật và chặn WebCrypto. Theo mặc định, OpenClaw chặn các kết nối Control UI không có danh tính thiết bị.

    Các ngoại lệ đã được ghi lại:

    • khả năng tương thích HTTP không an toàn chỉ dành cho localhost với gateway.controlUi.allowInsecureAuth=true
    • xác thực Control UI của operator thành công thông qua gateway.auth.mode: "trusted-proxy"
    • trường hợp khẩn cấp gateway.controlUi.dangerouslyDisableDeviceAuth=true

    Cách khắc phục được khuyến nghị: dùng HTTPS (Tailscale Serve) hoặc mở UI cục bộ:

    • https://<magicdns>/ (Serve)
    • http://127.0.0.1:18789/ (trên máy chủ Gateway)
    Hành vi của nút bật/tắt xác thực không an toàn
    {
      gateway: {
        controlUi: { allowInsecureAuth: true },
        bind: "tailnet",
        auth: { mode: "token", token: "replace-me" },
      },
    }
    

    allowInsecureAuth chỉ là nút bật/tắt tương thích cục bộ:

    • Nó cho phép các phiên Control UI trên localhost tiếp tục mà không cần danh tính thiết bị trong ngữ cảnh HTTP không bảo mật.
    • Nó không bỏ qua các bước kiểm tra ghép cặp.
    • Nó không nới lỏng yêu cầu danh tính thiết bị từ xa (không phải localhost).
    Chỉ dùng trong trường hợp khẩn cấp
    {
      gateway: {
        controlUi: { dangerouslyDisableDeviceAuth: true },
        bind: "tailnet",
        auth: { mode: "token", token: "replace-me" },
      },
    }
    
    Ghi chú về proxy đáng tin cậy
    • Xác thực trusted-proxy thành công có thể cho phép các phiên Control UI của operator không cần danh tính thiết bị.
    • Điều này không mở rộng cho các phiên Control UI có vai trò node.
    • Proxy ngược loopback cùng máy chủ vẫn không đáp ứng xác thực trusted-proxy; xem Xác thực proxy đáng tin cậy.

    Xem Tailscale để biết hướng dẫn thiết lập HTTPS.

    Chính sách bảo mật nội dung

    Control UI được phát hành với chính sách img-src chặt chẽ: chỉ cho phép tài nguyên cùng nguồn, URL data: và URL blob: được tạo cục bộ. URL hình ảnh http(s) từ xa và URL hình ảnh dạng tương đối giao thức bị trình duyệt từ chối và không phát sinh yêu cầu mạng.

    Điều này có nghĩa trong thực tế:

    • Avatar và hình ảnh được phục vụ dưới các đường dẫn tương đối (ví dụ /avatars/<id>) vẫn hiển thị, bao gồm các route avatar đã xác thực mà UI tải và chuyển đổi thành URL blob: cục bộ.
    • URL data:image/... nội tuyến vẫn hiển thị (hữu ích cho payload trong giao thức).
    • URL blob: cục bộ do Control UI tạo vẫn hiển thị.
    • URL avatar từ xa do siêu dữ liệu kênh phát ra sẽ bị loại bỏ tại các helper avatar của Control UI và được thay bằng logo/huy hiệu tích hợp sẵn, vì vậy một kênh bị xâm phạm hoặc độc hại không thể ép trình duyệt của operator tải hình ảnh từ xa tùy ý.

    Bạn không cần thay đổi gì để có hành vi này — nó luôn bật và không thể cấu hình.

    Xác thực route avatar

    Khi xác thực Gateway được cấu hình, endpoint avatar của Control UI yêu cầu cùng token Gateway như phần còn lại của API:

    • GET /avatar/<agentId> chỉ trả về hình ảnh avatar cho bên gọi đã xác thực. GET /avatar/<agentId>?meta=1 trả về siêu dữ liệu avatar theo cùng quy tắc.
    • Các yêu cầu chưa xác thực tới một trong hai route đều bị từ chối (khớp với route assistant-media cùng cấp). Điều này ngăn route avatar làm rò rỉ danh tính agent trên các máy chủ vốn được bảo vệ.
    • Bản thân Control UI chuyển tiếp token Gateway dưới dạng header bearer khi tải avatar, và dùng URL blob đã xác thực để hình ảnh vẫn hiển thị trong bảng điều khiển.

    Nếu bạn tắt xác thực Gateway (không khuyến nghị trên máy chủ dùng chung), route avatar cũng trở thành không cần xác thực, phù hợp với phần còn lại của Gateway.

    Xác thực route media của assistant

    Khi xác thực Gateway được cấu hình, phần xem trước media cục bộ của assistant dùng một route hai bước:

    • GET /__openclaw__/assistant-media?meta=1&source=<path> yêu cầu xác thực operator Control UI thông thường. Trình duyệt gửi token Gateway dưới dạng header bearer khi kiểm tra tính sẵn có.
    • Phản hồi siêu dữ liệu thành công bao gồm một mediaTicket tồn tại trong thời gian ngắn và được giới hạn cho đúng đường dẫn nguồn đó.
    • URL hình ảnh, âm thanh, video và tài liệu do trình duyệt hiển thị dùng mediaTicket=<ticket> thay vì token hoặc mật khẩu Gateway đang hoạt động. Vé hết hạn nhanh và không thể ủy quyền cho một nguồn khác.

    Điều này giữ cho việc hiển thị media thông thường tương thích với các phần tử media gốc của trình duyệt mà không đưa thông tin đăng nhập Gateway có thể tái sử dụng vào các URL media hiển thị được.

    Xây dựng UI

    Gateway phục vụ các tệp tĩnh từ dist/control-ui. Xây dựng chúng bằng:

    pnpm ui:build
    

    Base tuyệt đối tùy chọn (khi bạn muốn URL tài nguyên cố định):

    OPENCLAW_CONTROL_UI_BASE_PATH=/openclaw/ pnpm ui:build
    

    Để phát triển cục bộ (máy chủ dev riêng):

    pnpm ui:dev
    

    Sau đó trỏ UI tới URL Gateway WS của bạn (ví dụ ws://127.0.0.1:18789).

    Gỡ lỗi/kiểm thử: máy chủ dev + Gateway từ xa

    Control UI là các tệp tĩnh; đích WebSocket có thể cấu hình và có thể khác với origin HTTP. Điều này tiện lợi khi bạn muốn chạy máy chủ dev Vite cục bộ nhưng Gateway chạy ở nơi khác.

  • Khởi động máy chủ dev UI

    pnpm ui:dev
    
  • Mở bằng gatewayUrl

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

    Xác thực một lần tùy chọn (nếu cần):

    http://localhost:5173/?gatewayUrl=wss%3A%2F%2F<gateway-host>%3A18789#token=<gateway-token>
    
  • Ghi chú
    • gatewayUrl được lưu trong localStorage sau khi tải và bị xóa khỏi URL.
    • Nếu bạn truyền một endpoint ws:// hoặc wss:// đầy đủ qua gatewayUrl, hãy mã hóa URL giá trị gatewayUrl để trình duyệt phân tích chuỗi truy vấn chính xác.
    • Nên truyền token qua fragment URL (#token=...) bất cứ khi nào có thể. Fragment không được gửi tới máy chủ, giúp tránh rò rỉ qua nhật ký yêu cầu và Referer. Tham số truy vấn ?token= cũ vẫn được nhập một lần để tương thích, nhưng chỉ như phương án dự phòng, và bị xóa ngay sau khi bootstrap.
    • password chỉ được giữ trong bộ nhớ.
    • Khi gatewayUrl được đặt, UI không quay về thông tin đăng nhập từ cấu hình hoặc môi trường. Cung cấp rõ ràng token (hoặc password). Thiếu thông tin đăng nhập rõ ràng là một lỗi.
    • Dùng wss:// khi Gateway đứng sau TLS (Tailscale Serve, proxy HTTPS, v.v.).
    • gatewayUrl chỉ được chấp nhận trong cửa sổ cấp cao nhất (không nhúng) để ngăn clickjacking.
    • Các triển khai Control UI không phải loopback phải đặt rõ ràng gateway.controlUi.allowedOrigins (origin đầy đủ). Điều này bao gồm các thiết lập dev từ xa.
    • Khi khởi động, Gateway có thể gieo các origin cục bộ như http://localhost:<port>http://127.0.0.1:<port> từ bind và cổng runtime hiệu lực, nhưng origin trình duyệt từ xa vẫn cần các mục nhập rõ ràng.
    • Không dùng gateway.controlUi.allowedOrigins: ["*"] trừ khi kiểm thử cục bộ được kiểm soát chặt chẽ. Nó có nghĩa là cho phép mọi origin trình duyệt, không phải "khớp với bất kỳ máy chủ nào tôi đang dùng."
    • gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true bật chế độ dự phòng origin theo header Host, nhưng đây là một chế độ bảo mật nguy hiểm.

    Ví dụ:

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

    Chi tiết thiết lập truy cập từ xa: Truy cập từ xa.

    Liên quan