Web interfaces
เว็บแชต
สถานะ: UI แชต SwiftUI บน macOS/iOS สื่อสารกับ Gateway WebSocket โดยตรง ไม่มีเบราว์เซอร์แบบฝังและไม่มีเซิร์ฟเวอร์สแตติกภายในเครื่อง
คืออะไร
- UI แชตแบบเนทีฟสำหรับ Gateway
- ใช้เซสชันและกฎการกำหนดเส้นทางเดียวกับช่องทางอื่น
- การกำหนดเส้นทางแบบกำหนดผลลัพธ์แน่นอน: การตอบกลับจะกลับไปยัง WebChat เสมอ
- ประวัติจะถูกดึงจาก Gateway เสมอ (ไม่มีการเฝ้าดูไฟล์ภายในเครื่อง) หากไม่สามารถเข้าถึง Gateway ได้ WebChat จะเป็นแบบอ่านอย่างเดียว
เริ่มต้นอย่างรวดเร็ว
- เริ่ม Gateway
- เปิด UI ของ WebChat (แอป macOS/iOS) หรือแท็บแชตของ Control UI
- ตรวจสอบว่าได้กำหนดค่าเส้นทางการยืนยันตัวตนของ Gateway ที่ถูกต้องแล้ว (ค่าเริ่มต้นใช้ข้อมูลลับร่วมกัน แม้จะเชื่อมต่อผ่านลูปแบ็ก)
วิธีการทำงาน
- UI เชื่อมต่อกับ Gateway WebSocket และใช้เมธอด RPC
chat.history,chat.send,chat.injectและchat.message.get chat.historyมีการจำกัดขนาดเพื่อความเสถียร: Gateway อาจตัดทอนช่องข้อความที่ยาว ละเว้นเมทาดาทาขนาดใหญ่ และแทนที่รายการที่มีขนาดเกินด้วย[chat.history omitted: message too large]ไคลเอนต์ API สามารถส่งmaxCharsต่อคำขอเพื่อแทนที่ขีดจำกัดเริ่มต้นสำหรับการเรียกหนึ่งครั้ง- เมื่อข้อความผู้ช่วยที่มองเห็นได้ถูกตัดทอนใน
chat.historyControl UI สามารถเปิดแผงอ่านด้านข้างและดึงรายการฉบับเต็มที่ปรับรูปแบบเพื่อการแสดงผลแล้วตามคำขอผ่านchat.message.getโดยไม่เพิ่มเพย์โหลดประวัติเริ่มต้นchat.message.getใช้สาขาทรานสคริปต์และกฎการแสดงผลเดียวกับchat.historyแต่ระบุเป้าหมายเป็นรายการเดียวด้วยmessageIdและส่งคืนเหตุผลที่ตรงไปตรงมาว่าไม่พร้อมใช้งาน เมื่อไม่สามารถส่งคืนเนื้อหาฉบับเต็มได้อีกต่อไป chat.historyติดตามสาขาทรานสคริปต์ที่ใช้งานอยู่สำหรับไฟล์เซสชันแบบเพิ่มต่อท้ายเท่านั้น ดังนั้นสาขาที่เลิกใช้จากการเขียนใหม่และสำเนาพรอมต์ที่ถูกแทนที่จะไม่แสดงผลใน WebChat- รายการ Compaction จะแสดงเป็นตัวแบ่ง "ประวัติที่ผ่านการ Compaction" ซึ่งอธิบายว่าทรานสคริปต์ที่ผ่านการ Compaction ถูกเก็บรักษาไว้เป็นจุดตรวจ พร้อมการดำเนินการเพื่อเปิดจุดตรวจของเซสชัน (สร้างสาขาหรือกู้คืน เมื่อสิทธิ์อนุญาต)
- Control UI จดจำ
sessionIdของ Gateway ที่รองรับอยู่ซึ่งส่งคืนโดยchat.historyและรวมค่าไว้ในการเรียกchat.sendครั้งถัดไป ดังนั้นการเชื่อมต่อใหม่และการรีเฟรชหน้าจะดำเนินการสนทนาที่จัดเก็บไว้เดิมต่อไป เว้นแต่ผู้ใช้จะเริ่มหรือรีเซ็ตเซสชัน chat.sendรับคีย์ไอดอมโพเทนซี (Control UI ใช้ ID การรัน) Gateway จะกำจัดคำขอซ้ำที่ใช้คีย์เดียวกัน ดังนั้นการส่งที่ลองใหม่หรือซ้ำซึ่งยังอยู่ระหว่างดำเนินการสำหรับเซสชัน/ข้อความ/ไฟล์แนบเดียวกันจะไม่สร้างการรันครั้งที่สอง- การตอบกลับข้อความที่ระบุ (คลิกขวา → Reply) จะส่ง ID ทรานสคริปต์ของเป้าหมายเป็น
replyToIdบนchat.sendGateway จะค้นหาข้อความนั้นจากประวัติเซสชันและเติมเมทาดาทาบริบทการตอบกลับแบบไม่ขึ้นกับช่องทางชุดเดียวกับที่การตอบกลับของ Discord ใช้: เอเจนต์จะเห็นhas_reply_contextพร้อมบล็อก "เป้าหมายการตอบกลับของข้อความผู้ใช้ปัจจุบัน" ที่ไม่น่าเชื่อถือ ซึ่งมีป้ายกำกับผู้ส่งและเนื้อหาข้อความ (พรอมต์ Webchat ยังคงระงับ ID การสนทนาที่เปลี่ยนแปลงได้ เช่นreply_to_idตามนโยบายพรอมต์ที่รักษาไบต์ให้คงที่ซึ่งมีอยู่แล้วสำหรับเซสชัน Webchat โดยตรง) เป้าหมายการตอบกลับที่ไม่มี ID ทรานสคริปต์ที่จัดเก็บถาวร (เช่น การส่งที่รอดำเนินการ) จะใช้ข้อความอ้างอิงแบบอินไลน์ในเนื้อหาข้อความแทน - ไฟล์เริ่มต้นของเวิร์กสเปซและคำสั่ง
BOOTSTRAP.mdที่รอดำเนินการจะถูกส่งผ่านส่วน# Project Contextของพรอมต์ระบบเอเจนต์ ไม่ได้คัดลอกลงในข้อความผู้ใช้ของ WebChat หากเนื้อหาบูตสแตรปถูกตัดทอน พรอมต์ระบบจะได้รับ "ประกาศเกี่ยวกับบริบทบูตสแตรป" แบบสั้นแทน ส่วนจำนวนโดยละเอียดและตัวเลือกการกำหนดค่าจะยังคงอยู่บนพื้นผิวการวินิจฉัย - การปรับรูปแบบเพื่อการแสดงผลใน
chat.historyจะตัดสิ่งต่อไปนี้ออก: บริบท OpenClaw ที่ใช้เฉพาะขณะรันไทม์ ตัวห่อเอนเวโลปขาเข้า แท็กคำสั่งการส่งแบบอินไลน์ เช่น[[reply_to_current]],[[reply_to:<id>]]และ[[audio_as_voice]], เพย์โหลด XML ของการเรียกเครื่องมือแบบข้อความล้วน (<tool_call>,<function_call>,<tool_calls>,<function_calls>รวมถึงบล็อกที่ถูกตัดทอน) และโทเค็นควบคุมโมเดลแบบ ASCII/ตัวเต็มที่รั่วไหล รายการผู้ช่วยที่ข้อความซึ่งมองเห็นได้ทั้งหมดมีเพียงโทเค็นเงียบNO_REPLY(ไม่คำนึงถึงตัวพิมพ์เล็กและใหญ่) จะถูกละเว้น - เพย์โหลดการตอบกลับที่มีแฟล็กการให้เหตุผล (
isReasoning: true) จะถูกแยกออกจากเนื้อหาผู้ช่วยของ WebChat ข้อความการเล่นทรานสคริปต์ซ้ำ และบล็อกเนื้อหาเสียง ดังนั้นเพย์โหลดที่มีเฉพาะกระบวนการคิดจะไม่ปรากฏเป็นข้อความผู้ช่วยที่มองเห็นได้หรือเสียงที่เล่นได้ chat.injectเพิ่มหมายเหตุของผู้ช่วยต่อท้ายทรานสคริปต์โดยตรงและเผยแพร่ไปยัง UI (ไม่มีการรันเอเจนต์)- การรันที่ถูกยกเลิกสามารถคงเอาต์พุตบางส่วนของผู้ช่วยให้มองเห็นได้ใน UI Gateway จะจัดเก็บข้อความบางส่วนนั้นลงในประวัติทรานสคริปต์เมื่อมีเอาต์พุตในบัฟเฟอร์ และทำเครื่องหมายรายการด้วยเมทาดาทาการยกเลิก
โมเดลทรานสคริปต์และการส่ง
WebChat มีเส้นทางข้อมูลแยกกันสองเส้นทาง:
- แถวทรานสคริปต์ SQLite เป็นทรานสคริปต์ถาวรของโมเดล/รันไทม์ สำหรับการรันเอเจนต์ปกติ รันไทม์ OpenClaw แบบฝังจะจัดเก็บข้อความ
user,assistantและtoolResultที่โมเดลมองเห็นผ่านตัวเข้าถึงเซสชัน WebChat จะไม่เขียนข้อความการส่ง สถานะ หรือข้อความช่วยเหลือตามอำเภอใจลงในทรานสคริปต์นั้น - เหตุการณ์
ReplyPayloadของ Gateway คือการฉายภาพการส่งแบบสด: ปรับรูปแบบสำหรับการแสดงผล WebChat/ช่องทาง การสตรีมแบบบล็อก แท็กคำสั่ง การฝังสื่อ แฟล็ก TTS/เสียง และพฤติกรรมสำรองของ UI เหตุการณ์เหล่านี้ไม่ใช่บันทึกเซสชันหลักในตัวเอง - ชุดทดสอบที่ต้องการการตอบกลับที่มองเห็นได้ผ่าน
tools.messageยังคงใช้ WebChat เป็นปลายทางรับการตอบกลับจากแหล่งภายในสำหรับการรันปัจจุบันmessage.sendที่ไม่มีเป้าหมายจากการรัน WebChat ที่ใช้งานอยู่นั้นจะถูกฉายเข้าไปในแชตเดียวกันและทำสำเนาไปยังทรานสคริปต์เซสชัน WebChat จะไม่กลายเป็นช่องทางขาออกที่นำกลับมาใช้ใหม่ได้และจะไม่สืบทอดlastChannel - WebChat จะแทรกรายการทรานสคริปต์ของผู้ช่วยเฉพาะเมื่อ Gateway เป็นเจ้าของข้อความที่แสดงอยู่นอกเทิร์นเอเจนต์แบบฝังปกติ ได้แก่
chat.injectการตอบกลับคำสั่งที่ไม่ใช่เอเจนต์ เอาต์พุตบางส่วนที่ถูกยกเลิก และส่วนเสริมทรานสคริปต์สื่อที่ WebChat จัดการ - หากข้อความผู้ช่วยแบบสดปรากฏระหว่างการรันแต่หายไปหลังโหลดประวัติใหม่ ให้ตรวจสอบตามลำดับดังนี้: ทรานสคริปต์ SQLite มีข้อความผู้ช่วยหรือไม่ การฉายภาพการแสดงผล
chat.historyตัดข้อความนั้นออกหรือไม่ จากนั้นตรวจสอบว่าการผสานส่วนท้ายแบบคาดการณ์ล่วงหน้าของ Control UI แทนที่สถานะการส่งภายในเครื่องด้วยสแนปช็อตที่จัดเก็บถาวรหรือไม่
คำตอบสุดท้ายจากการรันเอเจนต์ปกติควรคงอยู่ถาวร เนื่องจากรันไทม์แบบฝังเขียน message_end ของผู้ช่วย ทางเลือกสำรองใด ๆ ที่ทำสำเนาเพย์โหลดสุดท้ายซึ่งส่งแล้วลงในทรานสคริปต์ ต้องหลีกเลี่ยงการทำซ้ำเทิร์นผู้ช่วยที่รันไทม์แบบฝังเขียนไว้แล้วก่อน
แผงเครื่องมือเอเจนต์ของ Control UI
- แผง Tools ของ
/agentsใน Control UI มีมุมมอง "พร้อมใช้งานขณะนี้" ซึ่งรองรับโดยtools.effective(sessionKey=...): การฉายภาพรายการเครื่องมือของเซสชันปัจจุบันแบบอ่านอย่างเดียวที่ได้มาจากเซิร์ฟเวอร์ รวมถึงเครื่องมือหลัก เครื่องมือของ Plugin เครื่องมือที่ช่องทางเป็นเจ้าของ และเครื่องมือเซิร์ฟเวอร์ MCP ที่ค้นพบแล้ว - มุมมองแก้ไขการกำหนดค่าที่แยกต่างหาก (รองรับโดย
tools.catalog) ครอบคลุมโปรไฟล์ การแทนที่รายเอเจนต์ และความหมายของแค็ตตาล็อก - ความพร้อมใช้งานขณะรันไทม์มีขอบเขตระดับเซสชัน การสลับเซสชันบนเอเจนต์เดียวกันสามารถเปลี่ยนรายการ "พร้อมใช้งานขณะนี้" ได้ หากเซิร์ฟเวอร์ MCP ที่กำหนดค่าไว้ยังไม่ได้เชื่อมต่อหรือมีการเปลี่ยนแปลงนับจากการค้นพบครั้งล่าสุด แผงจะแสดงประกาศแทนที่จะเริ่มทรานสปอร์ต MCP จากเส้นทางการอ่านโดยไม่แจ้งให้ทราบ
- ตัวแก้ไขการกำหนดค่าไม่ได้หมายความว่าพร้อมใช้งานขณะรันไทม์ การเข้าถึงที่มีผลจริงยังคงเป็นไปตามลำดับความสำคัญของนโยบาย (
allow/denyการแทนที่รายเอเจนต์และรายผู้ให้บริการ/ช่องทาง)
การใช้งานระยะไกล
- โหมดระยะไกลสร้างทันเนลสำหรับ Gateway WebSocket ผ่าน SSH/Tailscale
- ไม่จำเป็นต้องเรียกใช้เซิร์ฟเวอร์ WebChat แยกต่างหาก
เอกสารอ้างอิงการกำหนดค่า (WebChat)
การกำหนดค่าฉบับเต็ม: การกำหนดค่า
WebChat ไม่มีส่วนการกำหนดค่าที่จัดเก็บถาวร Gateway ใช้ขีดจำกัดการแสดงผล chat.history ในตัว ไคลเอนต์ API สามารถส่ง maxChars ต่อคำขอเพื่อแทนที่ขีดจำกัดดังกล่าวสำหรับการเรียกหนึ่งครั้ง การกำหนดค่า channels.webchat และ gateway.webchat แบบเดิมถูกยกเลิกแล้ว ให้เรียกใช้ openclaw doctor --fix เพื่อลบออก
ตัวเลือกส่วนกลางที่เกี่ยวข้อง:
gateway.port,gateway.bind: โฮสต์/พอร์ต WebSocketgateway.auth.mode,gateway.auth.token,gateway.auth.password: การยืนยันตัวตน WebSocket ด้วยข้อมูลลับร่วมกันgateway.auth.allowTailscale: แท็บแชต Control UI ในเบราว์เซอร์สามารถใช้ส่วนหัวข้อมูลประจำตัว ของ Tailscale Serve เมื่อเปิดใช้งานgateway.auth.mode: "trusted-proxy": การยืนยันตัวตนผ่านพร็อกซีย้อนกลับสำหรับไคลเอนต์เบราว์เซอร์ที่อยู่หลังแหล่งที่มาของพร็อกซี ที่ไม่ใช่ลูปแบ็ก ซึ่งรับรู้ข้อมูลประจำตัว (ดู การยืนยันตัวตนของพร็อกซีที่เชื่อถือได้)gateway.remote.url,gateway.remote.token,gateway.remote.password: เป้าหมาย Gateway ระยะไกลsession.*: พื้นที่จัดเก็บเซสชันและค่าเริ่มต้นของคีย์หลัก