---
read_when:
    - การดีบักหรือกำหนดค่าการเข้าถึง WebChat
summary: โฮสต์สแตติกของเว็บแชตลูปแบ็กและการใช้งาน Gateway WS สำหรับ UI แชท
title: เว็บแชต
x-i18n:
    generated_at: "2026-05-04T02:28:09Z"
    model: gpt-5.5
    provider: openai
    source_hash: bf435585a13a1cde5885714837017109eeeb61ffa5e33a400017706f676f57ea
    source_path: web/webchat.md
    workflow: 16
---

Status: UI แชต SwiftUI บน macOS/iOS สื่อสารโดยตรงกับ Gateway WebSocket

## คืออะไร

- UI แชตแบบเนทีฟสำหรับ Gateway (ไม่มีเบราว์เซอร์ฝังตัวและไม่มีเซิร์ฟเวอร์สแตติกภายในเครื่อง)
- ใช้เซสชันและกฎการกำหนดเส้นทางเดียวกับช่องทางอื่น
- การกำหนดเส้นทางแบบกำหนดแน่นอน: การตอบกลับจะกลับไปยัง WebChat เสมอ

## เริ่มต้นอย่างรวดเร็ว

1. เริ่ม Gateway
2. เปิด WebChat UI (แอป macOS/iOS) หรือแท็บแชตของ Control UI
3. ตรวจสอบให้แน่ใจว่ามีการกำหนดค่าพาธยืนยันตัวตน Gateway ที่ถูกต้อง (ค่าเริ่มต้นคือ shared-secret,
   แม้บน loopback)

## วิธีทำงาน (พฤติกรรม)

- UI เชื่อมต่อกับ Gateway WebSocket และใช้ `chat.history`, `chat.send` และ `chat.inject`
- `chat.history` ถูกจำกัดขอบเขตเพื่อความเสถียร: Gateway อาจตัดฟิลด์ข้อความยาว ละเว้นเมทาดาทาหนัก และแทนที่รายการที่มีขนาดเกินด้วย `[chat.history omitted: message too large]`
- `chat.history` ติดตามสาขาทรานสคริปต์ที่ใช้งานอยู่สำหรับไฟล์เซสชันแบบ append-only สมัยใหม่ ดังนั้นสาขา rewrite ที่ถูกละทิ้งและสำเนาพรอมป์ที่ถูกแทนที่จะไม่ถูกแสดงใน WebChat
- รายการ Compaction แสดงเป็นตัวแบ่งประวัติที่ถูกย่ออย่างชัดเจน ตัวแบ่งอธิบายว่าเทิร์นก่อนหน้าถูกเก็บรักษาไว้ในเช็คพอยต์ และลิงก์ไปยังตัวควบคุมเช็คพอยต์ของ Sessions ซึ่งผู้ปฏิบัติงานสามารถแตกสาขาหรือกู้คืนมุมมองก่อน Compaction ได้เมื่อสิทธิ์อนุญาต
- Control UI จดจำ Gateway `sessionId` เบื้องหลังที่ส่งกลับโดย `chat.history` และรวมค่าไว้ในการเรียก `chat.send` ต่อเนื่อง ดังนั้นการเชื่อมต่อใหม่และการรีเฟรชหน้าจะดำเนินบทสนทนาที่จัดเก็บไว้เดิมต่อ เว้นแต่ผู้ใช้จะเริ่มหรือรีเซ็ตเซสชัน
- Control UI รวมการส่งที่กำลังดำเนินอยู่ซ้ำสำหรับเซสชัน ข้อความ และไฟล์แนบเดียวกันก่อนสร้าง id การรัน `chat.send` ใหม่; Gateway ยังคงลดคำขอซ้ำที่ใช้คีย์ idempotency เดียวกัน
- ไฟล์เริ่มต้นของเวิร์กสเปซและคำสั่ง `BOOTSTRAP.md` ที่รอดำเนินการจะถูกส่งผ่าน Project Context ในพรอมป์ระบบของเอเจนต์ ไม่ได้คัดลอกเข้าไปในข้อความผู้ใช้ WebChat การตัด bootstrap เพิ่มเพียงประกาศกู้คืนแบบกระชับในพรอมป์ระบบ; จำนวนโดยละเอียดและปุ่มปรับแต่งการกำหนดค่ายังคงอยู่บนพื้นผิววินิจฉัย
- `chat.history` ยังถูกปรับให้เป็นมาตรฐานสำหรับการแสดงผลด้วย: บริบท OpenClaw เฉพาะรันไทม์,
  ตัวห่อ envelope ขาเข้า, แท็กคำสั่งการส่งมอบแบบอินไลน์
  เช่น `[[reply_to_*]]` และ `[[audio_as_voice]]`, เพย์โหลด XML การเรียกเครื่องมือแบบข้อความธรรมดา
  (รวมถึง `<tool_call>...</tool_call>`,
  `<function_call>...</function_call>`, `<tool_calls>...</tool_calls>`,
  `<function_calls>...</function_calls>` และบล็อกการเรียกเครื่องมือที่ถูกตัด), และ
  โทเค็นควบคุมโมเดล ASCII/full-width ที่รั่วไหล จะถูกลบออกจากข้อความที่มองเห็นได้,
  และรายการผู้ช่วยที่ข้อความที่มองเห็นได้ทั้งหมดเป็นเพียงโทเค็นเงียบที่ตรงเป๊ะ
  `NO_REPLY` / `no_reply` จะถูกละเว้น
- เพย์โหลดตอบกลับที่ถูกทำเครื่องหมายเป็นการให้เหตุผล (`isReasoning: true`) จะถูกตัดออกจากเนื้อหาผู้ช่วยของ WebChat, ข้อความ replay ทรานสคริปต์ และบล็อกเนื้อหาเสียง ดังนั้นเพย์โหลดที่เป็นการคิดเท่านั้นจะไม่ปรากฏเป็นข้อความผู้ช่วยที่มองเห็นได้หรือเสียงที่เล่นได้
- `chat.inject` เพิ่มบันทึกผู้ช่วยต่อท้ายทรานสคริปต์โดยตรงและกระจายไปยัง UI (ไม่มีการรันเอเจนต์)
- การรันที่ถูกยกเลิกสามารถคงเอาต์พุตผู้ช่วยบางส่วนให้มองเห็นได้ใน UI
- Gateway เก็บข้อความผู้ช่วยบางส่วนที่ถูกยกเลิกไว้ในประวัติทรานสคริปต์เมื่อมีเอาต์พุตในบัฟเฟอร์ และทำเครื่องหมายรายการเหล่านั้นด้วยเมทาดาทาการยกเลิก
- ประวัติจะถูกดึงจาก Gateway เสมอ (ไม่มีการเฝ้าดูไฟล์ภายในเครื่อง)
- หากเข้าถึง Gateway ไม่ได้ WebChat จะเป็นแบบอ่านอย่างเดียว

### ทรานสคริปต์และโมเดลการส่งมอบ

WebChat มีพาธข้อมูลแยกกันสองพาธ:

- ไฟล์ JSONL ของเซสชันคือทรานสคริปต์โมเดล/รันไทม์แบบถาวร สำหรับการรันเอเจนต์ปกติ Pi จะเก็บข้อความ `user`, `assistant` และ `toolResult` ที่โมเดลมองเห็นได้ผ่านตัวจัดการเซสชันของตน WebChat ไม่เขียนข้อความการส่งมอบ สถานะ หรือข้อความช่วยเหลือใดๆ เข้าไปในทรานสคริปต์นั้นโดยพลการ
- เหตุการณ์ Gateway `ReplyPayload` คือภาพฉายการส่งมอบสด เหตุการณ์เหล่านี้สามารถถูกปรับให้เป็นมาตรฐานสำหรับการแสดง WebChat/ช่องทาง, การสตรีมบล็อก, แท็กคำสั่ง, การฝังสื่อ, แฟล็ก TTS/เสียง และพฤติกรรม fallback ของ UI เหตุการณ์เหล่านี้ไม่ใช่บันทึกเซสชันหลักโดยตัวมันเอง
- WebChat ฉีดรายการทรานสคริปต์ผู้ช่วยเฉพาะเมื่อ Gateway เป็นเจ้าของข้อความที่แสดงนอกเทิร์นผู้ช่วย Pi ปกติ: `chat.inject`, คำตอบคำสั่งที่ไม่ใช่เอเจนต์, เอาต์พุตบางส่วนที่ถูกยกเลิก และส่วนเสริมทรานสคริปต์สื่อที่ WebChat จัดการ
- `chat.history` อ่านทรานสคริปต์เซสชันที่จัดเก็บไว้และใช้ภาพฉายการแสดงผลของ WebChat หากข้อความผู้ช่วยสดปรากฏระหว่างการรันแต่หายไปหลังโหลดประวัติใหม่ ให้ตรวจสอบก่อนว่า JSONL ดิบมีข้อความผู้ช่วยหรือไม่ จากนั้นตรวจสอบว่าโปรเจกชัน `chat.history` ลบข้อความนั้นออกหรือไม่ แล้วจึงตรวจสอบว่าการรวม optimistic-tail ของ Control UI แทนที่สถานะการส่งมอบภายในเครื่องด้วยสแนปช็อตที่คงอยู่หรือไม่

คำตอบสุดท้ายของการรันเอเจนต์ปกติควรคงอยู่ถาวรเพราะ Pi เขียน `message_end` ของผู้ช่วย fallback ใดๆ ที่สะท้อนเพย์โหลดสุดท้ายที่ส่งมอบเข้าไปในทรานสคริปต์ต้องหลีกเลี่ยงการทำซ้ำเทิร์นผู้ช่วยที่ Pi เขียนไว้แล้วก่อน

## แผงเครื่องมือเอเจนต์ของ Control UI

- แผง Tools ของ Control UI `/agents` มีสองมุมมองแยกกัน:
  - **พร้อมใช้งานตอนนี้** ใช้ `tools.effective(sessionKey=...)` และแสดงสิ่งที่เซสชันปัจจุบัน
    ใช้งานได้จริงในรันไทม์ รวมถึงเครื่องมือหลัก, Plugin และเครื่องมือที่ช่องทางเป็นเจ้าของ
  - **การกำหนดค่าเครื่องมือ** ใช้ `tools.catalog` และยังคงเน้นที่โปรไฟล์ การ override และ
    ความหมายของแคตตาล็อก
- ความพร้อมใช้งานในรันไทม์ถูกกำหนดขอบเขตตามเซสชัน การสลับเซสชันบนเอเจนต์เดียวกันสามารถเปลี่ยนรายการ
  **พร้อมใช้งานตอนนี้** ได้
- ตัวแก้ไขการกำหนดค่าไม่ได้บ่งบอกถึงความพร้อมใช้งานในรันไทม์; การเข้าถึงที่มีผลยังคงเป็นไปตามลำดับความสำคัญของนโยบาย
  (`allow`/`deny`, override ต่อเอเจนต์และต่อผู้ให้บริการ/ช่องทาง)

## การใช้งานระยะไกล

- โหมดระยะไกล tunneling Gateway WebSocket ผ่าน SSH/Tailscale
- คุณไม่จำเป็นต้องรันเซิร์ฟเวอร์ WebChat แยกต่างหาก

## อ้างอิงการกำหนดค่า (WebChat)

การกำหนดค่าแบบเต็ม: [การกำหนดค่า](/th/gateway/configuration)

ตัวเลือก WebChat:

- `gateway.webchat.chatHistoryMaxChars`: จำนวนอักขระสูงสุดสำหรับฟิลด์ข้อความในคำตอบ `chat.history` เมื่อรายการทรานสคริปต์เกินขีดจำกัดนี้ Gateway จะตัดฟิลด์ข้อความยาวและอาจแทนที่ข้อความที่มีขนาดเกินด้วย placeholder ลูกค้ายังสามารถส่ง `maxChars` ต่อคำขอเพื่อ override ค่าเริ่มต้นนี้สำหรับการเรียก `chat.history` ครั้งเดียวได้

ตัวเลือกส่วนกลางที่เกี่ยวข้อง:

- `gateway.port`, `gateway.bind`: โฮสต์/พอร์ต WebSocket
- `gateway.auth.mode`, `gateway.auth.token`, `gateway.auth.password`:
  การยืนยันตัวตน WebSocket แบบ shared-secret
- `gateway.auth.allowTailscale`: แท็บแชต Control UI ในเบราว์เซอร์สามารถใช้ส่วนหัวตัวตน Tailscale
  Serve ได้เมื่อเปิดใช้งาน
- `gateway.auth.mode: "trusted-proxy"`: การยืนยันตัวตน reverse-proxy สำหรับลูกค้าเบราว์เซอร์ที่อยู่หลังแหล่งพร็อกซี **ที่ไม่ใช่ loopback** และรับรู้ตัวตน (ดู [Trusted Proxy Auth](/th/gateway/trusted-proxy-auth))
- `gateway.remote.url`, `gateway.remote.token`, `gateway.remote.password`: เป้าหมาย Gateway ระยะไกล
- `session.*`: การจัดเก็บเซสชันและค่าเริ่มต้นของคีย์หลัก

## ที่เกี่ยวข้อง

- [Control UI](/th/web/control-ui)
- [Dashboard](/th/web/dashboard)
