chore(i18n): refresh th translations
This commit is contained in:
parent
e8ba7a0820
commit
f30f456210
File diff suppressed because it is too large
Load Diff
@ -1,47 +1,47 @@
|
||||
---
|
||||
read_when:
|
||||
- การตั้งค่า Slack หรือการดีบักโหมดซ็อกเก็ต/HTTP ของ Slack
|
||||
summary: การตั้งค่า Slack และพฤติกรรมระหว่างการทำงาน (โหมดซ็อกเก็ต + URL คำขอ HTTP)
|
||||
- การตั้งค่า Slack หรือการดีบักโหมด socket/HTTP ของ Slack
|
||||
summary: การตั้งค่า Slack และพฤติกรรมขณะรัน (โหมด Socket + URL ของคำขอ HTTP)
|
||||
title: Slack
|
||||
x-i18n:
|
||||
generated_at: "2026-05-04T02:22:24Z"
|
||||
generated_at: "2026-05-04T07:02:53Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 2be45f03511a64373b1f4316c59800eeeef8baccb4c00454b49999258b2e546b
|
||||
source_hash: d4a91fc1ae5f1e03f714308be54e164ef204809e74efabed8dc75c3035c14228
|
||||
source_path: channels/slack.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
พร้อมใช้งานระดับโปรดักชันสำหรับ DM และช่องผ่านการผสานรวมแอป Slack โหมดเริ่มต้นคือ Socket Mode และรองรับ HTTP Request URLs ด้วย
|
||||
พร้อมใช้งานระดับโปรดักชันสำหรับ DM และช่องผ่านการผสานรวม Slack app โหมดเริ่มต้นคือ Socket Mode และยังรองรับ HTTP Request URLs ด้วย
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="Pairing" icon="link" href="/th/channels/pairing">
|
||||
Slack DM ใช้โหมดจับคู่เป็นค่าเริ่มต้น
|
||||
<Card title="การจับคู่" icon="link" href="/th/channels/pairing">
|
||||
Slack DM ใช้โหมดการจับคู่เป็นค่าเริ่มต้น
|
||||
</Card>
|
||||
<Card title="Slash commands" icon="terminal" href="/th/tools/slash-commands">
|
||||
พฤติกรรมคำสั่งแบบเนทีฟและแคตตาล็อกคำสั่ง
|
||||
<Card title="คำสั่ง Slash" icon="terminal" href="/th/tools/slash-commands">
|
||||
ลักษณะการทำงานของคำสั่งแบบเนทีฟและแค็ตตาล็อกคำสั่ง
|
||||
</Card>
|
||||
<Card title="Channel troubleshooting" icon="wrench" href="/th/channels/troubleshooting">
|
||||
การวินิจฉัยข้ามช่องและคู่มือการซ่อมแซม
|
||||
<Card title="การแก้ไขปัญหาช่อง" icon="wrench" href="/th/channels/troubleshooting">
|
||||
การวินิจฉัยข้ามช่องและคู่มือปฏิบัติการซ่อมแซม
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## การตั้งค่าแบบรวดเร็ว
|
||||
## ตั้งค่าอย่างรวดเร็ว
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Socket Mode (default)">
|
||||
<Tab title="Socket Mode (ค่าเริ่มต้น)">
|
||||
<Steps>
|
||||
<Step title="Create a new Slack app">
|
||||
ในการตั้งค่าแอป Slack ให้กดปุ่ม **[Create New App](https://api.slack.com/apps/new)**:
|
||||
<Step title="สร้าง Slack app ใหม่">
|
||||
ในการตั้งค่า Slack app ให้กดปุ่ม **[Create New App](https://api.slack.com/apps/new)**:
|
||||
|
||||
- เลือก **from a manifest** และเลือกเวิร์กสเปซสำหรับแอปของคุณ
|
||||
- วาง [แมนิเฟสต์ตัวอย่าง](#manifest-and-scope-checklist) ด้านล่าง แล้วดำเนินการต่อเพื่อสร้าง
|
||||
- สร้าง **App-Level Token** (`xapp-...`) ที่มี `connections:write`
|
||||
- เลือก **from a manifest** และเลือก workspace สำหรับแอปของคุณ
|
||||
- วาง [manifest ตัวอย่าง](#manifest-and-scope-checklist) ด้านล่างและดำเนินการต่อเพื่อสร้าง
|
||||
- สร้าง **App-Level Token** (`xapp-...`) พร้อม `connections:write`
|
||||
- ติดตั้งแอปและคัดลอก **Bot Token** (`xoxb-...`) ที่แสดง
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Configure OpenClaw">
|
||||
<Step title="กำหนดค่า OpenClaw">
|
||||
|
||||
การตั้งค่า SecretRef ที่แนะนำ:
|
||||
|
||||
@ -64,7 +64,7 @@ openclaw config patch --file ./slack.socket.patch.json5 --dry-run
|
||||
openclaw config patch --file ./slack.socket.patch.json5
|
||||
```
|
||||
|
||||
ทางเลือกสำรอง Env (เฉพาะบัญชีเริ่มต้น):
|
||||
Env สำรอง (เฉพาะบัญชีเริ่มต้นเท่านั้น):
|
||||
|
||||
```bash
|
||||
SLACK_APP_TOKEN=xapp-...
|
||||
@ -73,7 +73,7 @@ SLACK_BOT_TOKEN=xoxb-...
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Start gateway">
|
||||
<Step title="เริ่ม Gateway">
|
||||
|
||||
```bash
|
||||
openclaw gateway
|
||||
@ -86,17 +86,17 @@ openclaw gateway
|
||||
|
||||
<Tab title="HTTP Request URLs">
|
||||
<Steps>
|
||||
<Step title="Create a new Slack app">
|
||||
ในการตั้งค่าแอป Slack ให้กดปุ่ม **[Create New App](https://api.slack.com/apps/new)**:
|
||||
<Step title="สร้าง Slack app ใหม่">
|
||||
ในการตั้งค่า Slack app ให้กดปุ่ม **[Create New App](https://api.slack.com/apps/new)**:
|
||||
|
||||
- เลือก **from a manifest** และเลือกเวิร์กสเปซสำหรับแอปของคุณ
|
||||
- วาง [แมนิเฟสต์ตัวอย่าง](#manifest-and-scope-checklist) และอัปเดต URL ก่อนสร้าง
|
||||
- เลือก **from a manifest** และเลือก workspace สำหรับแอปของคุณ
|
||||
- วาง [manifest ตัวอย่าง](#manifest-and-scope-checklist) และอัปเดต URL ก่อนสร้าง
|
||||
- บันทึก **Signing Secret** สำหรับการตรวจสอบคำขอ
|
||||
- ติดตั้งแอปและคัดลอก **Bot Token** (`xoxb-...`) ที่แสดง
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Configure OpenClaw">
|
||||
<Step title="กำหนดค่า OpenClaw">
|
||||
|
||||
การตั้งค่า SecretRef ที่แนะนำ:
|
||||
|
||||
@ -121,14 +121,14 @@ openclaw config patch --file ./slack.http.patch.json5
|
||||
```
|
||||
|
||||
<Note>
|
||||
ใช้เส้นทาง Webhook ที่ไม่ซ้ำกันสำหรับ HTTP แบบหลายบัญชี
|
||||
ใช้ webhook path ที่ไม่ซ้ำกันสำหรับ HTTP หลายบัญชี
|
||||
|
||||
กำหนด `webhookPath` แยกกันให้แต่ละบัญชี (ค่าเริ่มต้น `/slack/events`) เพื่อไม่ให้การลงทะเบียนชนกัน
|
||||
กำหนด `webhookPath` ที่แตกต่างกันให้แต่ละบัญชี (ค่าเริ่มต้น `/slack/events`) เพื่อไม่ให้การลงทะเบียนชนกัน
|
||||
</Note>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Start gateway">
|
||||
<Step title="เริ่ม Gateway">
|
||||
|
||||
```bash
|
||||
openclaw gateway
|
||||
@ -140,9 +140,9 @@ openclaw gateway
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## การปรับแต่งการส่งผ่าน Socket Mode
|
||||
## การปรับแต่งการส่งข้อมูลของ Socket Mode
|
||||
|
||||
OpenClaw ตั้งค่าระยะหมดเวลารอ pong ของไคลเอนต์ Slack SDK เป็น 15 วินาทีโดยค่าเริ่มต้นสำหรับ Socket Mode ให้แทนที่การตั้งค่าการส่งผ่านเฉพาะเมื่อคุณต้องปรับแต่งตามเวิร์กสเปซหรือโฮสต์เท่านั้น:
|
||||
OpenClaw ตั้งค่า pong timeout ของไคลเอนต์ Slack SDK เป็น 15 วินาทีโดยค่าเริ่มต้นสำหรับ Socket Mode ให้แทนที่การตั้งค่าการส่งข้อมูลเฉพาะเมื่อคุณต้องปรับแต่งตาม workspace หรือโฮสต์เท่านั้น:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -159,13 +159,13 @@ OpenClaw ตั้งค่าระยะหมดเวลารอ pong ข
|
||||
}
|
||||
```
|
||||
|
||||
ใช้ตัวเลือกนี้เฉพาะกับเวิร์กสเปซ Socket Mode ที่บันทึก timeout ของ Slack websocket pong/server-ping หรือทำงานบนโฮสต์ที่ทราบว่ามีภาวะ event-loop starvation `clientPingTimeout` คือเวลารอ pong หลังจาก SDK ส่ง client ping; `serverPingTimeout` คือเวลารอ ping จากเซิร์ฟเวอร์ Slack ข้อความและอีเวนต์ของแอปยังคงเป็นสถานะแอปพลิเคชัน ไม่ใช่สัญญาณความพร้อมใช้งานของการส่งผ่าน
|
||||
ใช้ตัวเลือกนี้เฉพาะกับ workspace ของ Socket Mode ที่บันทึก Slack websocket pong/server-ping timeout หรือทำงานบนโฮสต์ที่มีปัญหา event-loop starvation ที่ทราบอยู่แล้ว `clientPingTimeout` คือเวลารอ pong หลังจาก SDK ส่ง client ping ส่วน `serverPingTimeout` คือเวลารอ ping จากเซิร์ฟเวอร์ Slack ข้อความและเหตุการณ์ของแอปยังคงเป็นสถานะแอปพลิเคชัน ไม่ใช่สัญญาณความพร้อมของการส่งข้อมูล
|
||||
|
||||
## รายการตรวจสอบแมนิเฟสต์และขอบเขต
|
||||
## รายการตรวจสอบ manifest และ scope
|
||||
|
||||
แมนิเฟสต์แอป Slack พื้นฐานเหมือนกันสำหรับ Socket Mode และ HTTP Request URLs มีเพียงบล็อก `settings` (และ `url` ของ slash command) ที่แตกต่างกัน
|
||||
Slack app manifest พื้นฐานเหมือนกันสำหรับ Socket Mode และ HTTP Request URLs มีเฉพาะบล็อก `settings` (และ `url` ของคำสั่ง slash) ที่ต่างกัน
|
||||
|
||||
แมนิเฟสต์พื้นฐาน (ค่าเริ่มต้น Socket Mode):
|
||||
manifest พื้นฐาน (ค่าเริ่มต้น Socket Mode):
|
||||
|
||||
```json
|
||||
{
|
||||
@ -240,7 +240,7 @@ OpenClaw ตั้งค่าระยะหมดเวลารอ pong ข
|
||||
}
|
||||
```
|
||||
|
||||
สำหรับ **โหมด HTTP Request URLs** ให้แทนที่ `settings` ด้วยตัวแปร HTTP และเพิ่ม `url` ให้แต่ละ slash command ต้องมี URL สาธารณะ:
|
||||
สำหรับ **โหมด HTTP Request URLs** ให้แทนที่ `settings` ด้วยตัวแปร HTTP และเพิ่ม `url` ในแต่ละคำสั่ง slash ต้องมี URL สาธารณะ:
|
||||
|
||||
```json
|
||||
{
|
||||
@ -282,24 +282,24 @@ OpenClaw ตั้งค่าระยะหมดเวลารอ pong ข
|
||||
}
|
||||
```
|
||||
|
||||
### การตั้งค่าแมนิเฟสต์เพิ่มเติม
|
||||
### การตั้งค่า manifest เพิ่มเติม
|
||||
|
||||
แสดงฟีเจอร์ต่าง ๆ ที่ขยายค่าเริ่มต้นด้านบน
|
||||
|
||||
แมนิเฟสต์เริ่มต้นเปิดใช้แท็บ **Home** ของ Slack App Home และสมัครรับ `app_home_opened` เมื่อสมาชิกเวิร์กสเปซเปิดแท็บ Home, OpenClaw จะเผยแพร่มุมมอง Home เริ่มต้นที่ปลอดภัยด้วย `views.publish`; ไม่มีเพย์โหลดการสนทนาหรือการกำหนดค่าส่วนตัวรวมอยู่ แท็บ **Messages** ยังคงเปิดใช้งานสำหรับ Slack DM
|
||||
manifest เริ่มต้นเปิดใช้แท็บ **Home** ของ Slack App Home และสมัครรับ `app_home_opened` เมื่อสมาชิก workspace เปิดแท็บ Home, OpenClaw จะเผยแพร่มุมมอง Home เริ่มต้นที่ปลอดภัยด้วย `views.publish` โดยไม่รวม payload การสนทนาหรือการกำหนดค่าส่วนตัว แท็บ **Messages** ยังคงเปิดใช้สำหรับ Slack DM
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Optional native slash commands">
|
||||
<Accordion title="คำสั่ง slash แบบเนทีฟที่ไม่บังคับ">
|
||||
|
||||
สามารถใช้ [slash command แบบเนทีฟ](#commands-and-slash-behavior) หลายรายการแทนคำสั่งที่กำหนดค่าไว้รายการเดียวได้ โดยมีรายละเอียดดังนี้:
|
||||
สามารถใช้ [คำสั่ง slash แบบเนทีฟ](#commands-and-slash-behavior) หลายคำสั่งแทนคำสั่งเดียวที่กำหนดค่าไว้พร้อมรายละเอียดปลีกย่อยได้:
|
||||
|
||||
- ใช้ `/agentstatus` แทน `/status` เพราะคำสั่ง `/status` ถูกสงวนไว้
|
||||
- ทำให้มี slash command ใช้งานได้พร้อมกันไม่เกิน 25 รายการ
|
||||
- สามารถเปิดให้ใช้คำสั่ง slash ได้พร้อมกันไม่เกิน 25 คำสั่ง
|
||||
|
||||
แทนที่ส่วน `features.slash_commands` เดิมของคุณด้วยชุดย่อยของ [คำสั่งที่มีให้ใช้](/th/tools/slash-commands#command-list):
|
||||
แทนที่ส่วน `features.slash_commands` ที่มีอยู่ด้วยชุดย่อยของ [คำสั่งที่มีให้ใช้](/th/tools/slash-commands#command-list):
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Socket Mode (default)">
|
||||
<Tab title="Socket Mode (ค่าเริ่มต้น)">
|
||||
|
||||
```json
|
||||
{
|
||||
@ -423,7 +423,7 @@ OpenClaw ตั้งค่าระยะหมดเวลารอ pong ข
|
||||
|
||||
</Tab>
|
||||
<Tab title="HTTP Request URLs">
|
||||
ใช้รายการ `slash_commands` เดียวกับ Socket Mode ด้านบน และเพิ่ม `"url": "https://gateway-host.example.com/slack/events"` ให้ทุกรายการ ตัวอย่าง:
|
||||
ใช้รายการ `slash_commands` เดียวกับ Socket Mode ด้านบน และเพิ่ม `"url": "https://gateway-host.example.com/slack/events"` ในทุกรายการ ตัวอย่าง:
|
||||
|
||||
```json
|
||||
{
|
||||
@ -449,14 +449,14 @@ OpenClaw ตั้งค่าระยะหมดเวลารอ pong ข
|
||||
</Tabs>
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Optional authorship scopes (write operations)">
|
||||
เพิ่มขอบเขตบอท `chat:write.customize` หากคุณต้องการให้ข้อความขาออกใช้ตัวตนของเอเจนต์ที่ใช้งานอยู่ (ชื่อผู้ใช้และไอคอนแบบกำหนดเอง) แทนตัวตนเริ่มต้นของแอป Slack
|
||||
<Accordion title="ขอบเขตผู้เขียนเพิ่มเติม (การดำเนินการเขียน)">
|
||||
เพิ่มขอบเขตบอต `chat:write.customize` หากคุณต้องการให้ข้อความขาออกใช้อัตลักษณ์ของเอเจนต์ที่ใช้งานอยู่ (ชื่อผู้ใช้และไอคอนแบบกำหนดเอง) แทนอัตลักษณ์เริ่มต้นของแอป Slack
|
||||
|
||||
หากคุณใช้ไอคอนอีโมจิ Slack คาดหวังไวยากรณ์ `:emoji_name:`
|
||||
หากคุณใช้ไอคอนอีโมจิ Slack คาดหวังไวยากรณ์แบบ `:emoji_name:`
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Optional user-token scopes (read operations)">
|
||||
หากคุณกำหนดค่า `channels.slack.userToken` ขอบเขตการอ่านทั่วไปคือ:
|
||||
<Accordion title="ขอบเขตโทเค็นผู้ใช้เพิ่มเติม (การดำเนินการอ่าน)">
|
||||
หากคุณกำหนดค่า `channels.slack.userToken` ขอบเขตการอ่านโดยทั่วไปคือ:
|
||||
|
||||
- `channels:history`, `groups:history`, `im:history`, `mpim:history`
|
||||
- `channels:read`, `groups:read`, `im:read`, `mpim:read`
|
||||
@ -464,41 +464,41 @@ OpenClaw ตั้งค่าระยะหมดเวลารอ pong ข
|
||||
- `reactions:read`
|
||||
- `pins:read`
|
||||
- `emoji:read`
|
||||
- `search:read` (หากคุณพึ่งพาการอ่านจากการค้นหาของ Slack)
|
||||
- `search:read` (หากคุณพึ่งพาการอ่านการค้นหาของ Slack)
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## โมเดลโทเค็น
|
||||
|
||||
- ต้องมี `botToken` + `appToken` สำหรับ Socket Mode
|
||||
- โหมด HTTP ต้องมี `botToken` + `signingSecret`
|
||||
- `botToken`, `appToken`, `signingSecret` และ `userToken` รับสตริงข้อความล้วน
|
||||
- จำเป็นต้องมี `botToken` + `appToken` สำหรับ Socket Mode
|
||||
- โหมด HTTP ต้องใช้ `botToken` + `signingSecret`
|
||||
- `botToken`, `appToken`, `signingSecret` และ `userToken` รับสตริงข้อความธรรมดา
|
||||
หรือออบเจ็กต์ SecretRef
|
||||
- โทเค็นในค่ากำหนดจะแทนที่ env fallback
|
||||
- env fallback `SLACK_BOT_TOKEN` / `SLACK_APP_TOKEN` ใช้กับบัญชีเริ่มต้นเท่านั้น
|
||||
- `userToken` (`xoxp-...`) กำหนดค่าได้ผ่าน config เท่านั้น (ไม่มี env fallback) และค่าเริ่มต้นเป็นพฤติกรรมแบบอ่านอย่างเดียว (`userTokenReadOnly: true`)
|
||||
- โทเค็นในคอนฟิกจะแทนที่ env fallback
|
||||
- env fallback ของ `SLACK_BOT_TOKEN` / `SLACK_APP_TOKEN` ใช้กับบัญชีเริ่มต้นเท่านั้น
|
||||
- `userToken` (`xoxp-...`) เป็นแบบคอนฟิกเท่านั้น (ไม่มี env fallback) และมีค่าเริ่มต้นเป็นพฤติกรรมอ่านอย่างเดียว (`userTokenReadOnly: true`)
|
||||
|
||||
พฤติกรรมสแนปช็อตสถานะ:
|
||||
|
||||
- การตรวจสอบบัญชี Slack ติดตามฟิลด์ `*Source` และ `*Status`
|
||||
ต่อข้อมูลรับรอง (`botToken`, `appToken`, `signingSecret`, `userToken`)
|
||||
ต่อข้อมูลประจำตัว (`botToken`, `appToken`, `signingSecret`, `userToken`)
|
||||
- สถานะคือ `available`, `configured_unavailable` หรือ `missing`
|
||||
- `configured_unavailable` หมายความว่าบัญชีถูกกำหนดค่าผ่าน SecretRef
|
||||
หรือแหล่งข้อมูลลับแบบไม่ฝังในบรรทัดแบบอื่น แต่เส้นทางคำสั่ง/รันไทม์ปัจจุบัน
|
||||
ไม่สามารถ resolve ค่าจริงได้
|
||||
- ในโหมด HTTP จะรวม `signingSecretStatus`; ใน Socket Mode
|
||||
หรือแหล่งความลับแบบไม่ฝังในบรรทัดอื่น แต่เส้นทางคำสั่ง/รันไทม์ปัจจุบัน
|
||||
ไม่สามารถแก้ค่าแท้จริงได้
|
||||
- ในโหมด HTTP จะรวม `signingSecretStatus` ไว้ด้วย; ใน Socket Mode
|
||||
คู่ที่จำเป็นคือ `botTokenStatus` + `appTokenStatus`
|
||||
|
||||
<Tip>
|
||||
สำหรับ actions/การอ่าน directory สามารถเลือกใช้โทเค็นผู้ใช้ก่อนเมื่อกำหนดค่าไว้ สำหรับการเขียน โทเค็นบอทยังคงเป็นตัวเลือกหลัก; การเขียนด้วยโทเค็นผู้ใช้จะอนุญาตเฉพาะเมื่อ `userTokenReadOnly: false` และไม่มีโทเค็นบอทให้ใช้
|
||||
สำหรับการอ่านแอ็กชัน/ไดเรกทอรี สามารถเลือกใช้โทเค็นผู้ใช้ก่อนเมื่อกำหนดค่าไว้ สำหรับการเขียน โทเค็นบอตยังคงเป็นตัวเลือกหลัก; การเขียนด้วยโทเค็นผู้ใช้จะอนุญาตเฉพาะเมื่อ `userTokenReadOnly: false` และโทเค็นบอตไม่พร้อมใช้งาน
|
||||
</Tip>
|
||||
|
||||
## Actions และ gates
|
||||
## แอ็กชันและเกต
|
||||
|
||||
Slack actions ถูกควบคุมโดย `channels.slack.actions.*`
|
||||
แอ็กชัน Slack ควบคุมโดย `channels.slack.actions.*`
|
||||
|
||||
กลุ่ม action ที่มีในเครื่องมือ Slack ปัจจุบัน:
|
||||
กลุ่มแอ็กชันที่พร้อมใช้งานในเครื่องมือ Slack ปัจจุบัน:
|
||||
|
||||
| กลุ่ม | ค่าเริ่มต้น |
|
||||
| ---------- | ------- |
|
||||
@ -508,12 +508,12 @@ Slack actions ถูกควบคุมโดย `channels.slack.actions.*`
|
||||
| memberInfo | เปิดใช้งาน |
|
||||
| emojiList | เปิดใช้งาน |
|
||||
|
||||
action ข้อความ Slack ปัจจุบันประกอบด้วย `send`, `upload-file`, `download-file`, `read`, `edit`, `delete`, `pin`, `unpin`, `list-pins`, `member-info` และ `emoji-list` `download-file` รับ ID ไฟล์ Slack ที่แสดงใน placeholder ไฟล์ขาเข้า และส่งคืนตัวอย่างภาพสำหรับรูปภาพหรือ metadata ของไฟล์ภายในเครื่องสำหรับไฟล์ชนิดอื่น
|
||||
แอ็กชันข้อความ Slack ปัจจุบันประกอบด้วย `send`, `upload-file`, `download-file`, `read`, `edit`, `delete`, `pin`, `unpin`, `list-pins`, `member-info` และ `emoji-list` `download-file` รับ ID ไฟล์ Slack ที่แสดงในตัวแทนที่ไฟล์ขาเข้า และคืนค่าตัวอย่างรูปภาพสำหรับรูปภาพ หรือเมตาดาต้าไฟล์ในเครื่องสำหรับไฟล์ประเภทอื่น
|
||||
|
||||
## การควบคุมการเข้าถึงและการกำหนดเส้นทาง
|
||||
|
||||
<Tabs>
|
||||
<Tab title="DM policy">
|
||||
<Tab title="นโยบาย DM">
|
||||
`channels.slack.dmPolicy` ควบคุมการเข้าถึง DM `channels.slack.allowFrom` คือ allowlist ของ DM ตามมาตรฐาน
|
||||
|
||||
- `pairing` (ค่าเริ่มต้น)
|
||||
@ -526,40 +526,40 @@ action ข้อความ Slack ปัจจุบันประกอบด
|
||||
- `dm.enabled` (ค่าเริ่มต้น true)
|
||||
- `channels.slack.allowFrom`
|
||||
- `dm.allowFrom` (เดิม)
|
||||
- `dm.groupEnabled` (DM กลุ่มมีค่าเริ่มต้นเป็น false)
|
||||
- `dm.groupChannels` (allowlist MPIM แบบไม่บังคับ)
|
||||
- `dm.groupEnabled` (DM แบบกลุ่มมีค่าเริ่มต้น false)
|
||||
- `dm.groupChannels` (allowlist MPIM เพิ่มเติม)
|
||||
|
||||
ลำดับความสำคัญแบบหลายบัญชี:
|
||||
ลำดับความสำคัญของหลายบัญชี:
|
||||
|
||||
- `channels.slack.accounts.default.allowFrom` ใช้กับบัญชี `default` เท่านั้น
|
||||
- บัญชีที่มีชื่อจะสืบทอด `channels.slack.allowFrom` เมื่อไม่ได้ตั้งค่า `allowFrom` ของตัวเอง
|
||||
- บัญชีที่มีชื่อจะไม่สืบทอด `channels.slack.accounts.default.allowFrom`
|
||||
|
||||
`channels.slack.dm.policy` และ `channels.slack.dm.allowFrom` แบบเดิมยังอ่านได้เพื่อความเข้ากันได้ `openclaw doctor --fix` จะย้ายค่าเหล่านี้ไปเป็น `dmPolicy` และ `allowFrom` เมื่อทำได้โดยไม่เปลี่ยนการเข้าถึง
|
||||
ยังคงอ่าน `channels.slack.dm.policy` และ `channels.slack.dm.allowFrom` เดิมเพื่อความเข้ากันได้ `openclaw doctor --fix` จะย้ายค่าเหล่านี้ไปยัง `dmPolicy` และ `allowFrom` เมื่อทำได้โดยไม่เปลี่ยนการเข้าถึง
|
||||
|
||||
การจับคู่ใน DM ใช้ `openclaw pairing approve slack <code>`
|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab title="Channel policy">
|
||||
<Tab title="นโยบายช่อง">
|
||||
`channels.slack.groupPolicy` ควบคุมการจัดการช่อง:
|
||||
|
||||
- `open`
|
||||
- `allowlist`
|
||||
- `disabled`
|
||||
|
||||
allowlist ของช่องอยู่ใต้ `channels.slack.channels` และ **ต้องใช้ ID ช่อง Slack ที่เสถียร** (เช่น `C12345678`) เป็นคีย์ config
|
||||
allowlist ของช่องอยู่ภายใต้ `channels.slack.channels` และ**ต้องใช้ ID ช่อง Slack ที่เสถียร** (เช่น `C12345678`) เป็นคีย์คอนฟิก
|
||||
|
||||
หมายเหตุรันไทม์: หากไม่มี `channels.slack` เลย (การตั้งค่าแบบ env เท่านั้น) รันไทม์จะ fallback ไปที่ `groupPolicy="allowlist"` และบันทึกคำเตือน (แม้ว่าจะตั้งค่า `channels.defaults.groupPolicy` ไว้ก็ตาม)
|
||||
หมายเหตุรันไทม์: หาก `channels.slack` หายไปทั้งหมด (การตั้งค่าแบบ env-only) รันไทม์จะ fallback ไปเป็น `groupPolicy="allowlist"` และบันทึกคำเตือน (แม้จะตั้งค่า `channels.defaults.groupPolicy` ไว้ก็ตาม)
|
||||
|
||||
การ resolve ชื่อ/ID:
|
||||
การแก้ชื่อ/ID:
|
||||
|
||||
- รายการ allowlist ของช่องและรายการ allowlist ของ DM จะถูก resolve ตอนเริ่มทำงานเมื่อการเข้าถึงโทเค็นอนุญาต
|
||||
- รายการชื่อช่องที่ resolve ไม่ได้จะถูกเก็บไว้ตามที่กำหนดค่า แต่จะถูกละเว้นสำหรับการกำหนดเส้นทางโดยค่าเริ่มต้น
|
||||
- การอนุญาตขาเข้าและการกำหนดเส้นทางช่องจะใช้ ID ก่อนโดยค่าเริ่มต้น; การจับคู่ชื่อผู้ใช้/slug โดยตรงต้องใช้ `channels.slack.dangerouslyAllowNameMatching: true`
|
||||
- รายการ allowlist ของช่องและรายการ allowlist ของ DM จะถูกแก้ตอนเริ่มต้นเมื่อการเข้าถึงโทเค็นอนุญาต
|
||||
- รายการชื่อช่องที่แก้ไม่ได้จะคงไว้ตามที่กำหนดค่า แต่จะถูกละเว้นสำหรับการกำหนดเส้นทางโดยค่าเริ่มต้น
|
||||
- การอนุญาตขาเข้าและการกำหนดเส้นทางช่องจะใช้ ID เป็นหลักโดยค่าเริ่มต้น; การจับคู่ชื่อผู้ใช้/slug โดยตรงต้องใช้ `channels.slack.dangerouslyAllowNameMatching: true`
|
||||
|
||||
<Warning>
|
||||
คีย์ตามชื่อ (`#channel-name` หรือ `channel-name`) **จะไม่** ตรงกันภายใต้ `groupPolicy: "allowlist"` การค้นหาช่องใช้ ID ก่อนโดยค่าเริ่มต้น ดังนั้นคีย์ตามชื่อจะไม่สามารถกำหนดเส้นทางสำเร็จได้เลย และข้อความทั้งหมดในช่องนั้นจะถูกบล็อกอย่างเงียบ ๆ ซึ่งต่างจาก `groupPolicy: "open"` ที่ไม่ต้องใช้คีย์ช่องสำหรับการกำหนดเส้นทาง และคีย์ตามชื่อดูเหมือนจะใช้งานได้
|
||||
คีย์ตามชื่อ (`#channel-name` หรือ `channel-name`) จะ**ไม่**จับคู่ภายใต้ `groupPolicy: "allowlist"` การค้นหาช่องใช้ ID เป็นหลักโดยค่าเริ่มต้น ดังนั้นคีย์ตามชื่อจะไม่มีทางกำหนดเส้นทางสำเร็จ และข้อความทั้งหมดในช่องนั้นจะถูกบล็อกอย่างเงียบ ๆ ซึ่งแตกต่างจาก `groupPolicy: "open"` ที่ไม่จำเป็นต้องใช้คีย์ช่องสำหรับการกำหนดเส้นทาง และคีย์ตามชื่อดูเหมือนจะใช้งานได้
|
||||
|
||||
ใช้ ID ช่อง Slack เป็นคีย์เสมอ วิธีค้นหา: คลิกขวาที่ช่องใน Slack → **Copy link** — ID (`C...`) จะปรากฏที่ท้าย URL
|
||||
|
||||
@ -597,16 +597,16 @@ action ข้อความ Slack ปัจจุบันประกอบด
|
||||
</Tab>
|
||||
|
||||
<Tab title="Mentions and channel users">
|
||||
ข้อความในช่องถูกกั้นด้วยการกล่าวถึงโดยค่าเริ่มต้น
|
||||
ข้อความในช่องทางถูกควบคุมด้วยการกล่าวถึงโดยค่าเริ่มต้น
|
||||
|
||||
แหล่งที่มาของการกล่าวถึง:
|
||||
|
||||
- การกล่าวถึงแอปอย่างชัดเจน (`<@botId>`)
|
||||
- การกล่าวถึงกลุ่มผู้ใช้ Slack (`<!subteam^S...>`) เมื่อผู้ใช้บอทเป็นสมาชิกของกลุ่มผู้ใช้นั้น; ต้องมี `usergroups:read`
|
||||
- รูปแบบ regex สำหรับการกล่าวถึง (`agents.list[].groupChat.mentionPatterns`, fallback `messages.groupChat.mentionPatterns`)
|
||||
- พฤติกรรม thread แบบตอบกลับถึงบอทโดยนัย (ปิดใช้งานเมื่อ `thread.requireExplicitMention` เป็น `true`)
|
||||
- การกล่าวถึงกลุ่มผู้ใช้ Slack (`<!subteam^S...>`) เมื่อผู้ใช้บอทเป็นสมาชิกของกลุ่มผู้ใช้นั้น ต้องใช้ `usergroups:read`
|
||||
- รูปแบบ regex สำหรับการกล่าวถึง (`agents.list[].groupChat.mentionPatterns`, สำรองเป็น `messages.groupChat.mentionPatterns`)
|
||||
- พฤติกรรมเธรดตอบกลับถึงบอทโดยนัย (ปิดใช้งานเมื่อ `thread.requireExplicitMention` เป็น `true`)
|
||||
|
||||
การควบคุมรายช่อง (`channels.slack.channels.<id>`; ชื่อใช้ได้เฉพาะผ่านการ resolve ตอนเริ่มทำงานหรือ `dangerouslyAllowNameMatching`):
|
||||
การควบคุมรายช่องทาง (`channels.slack.channels.<id>`; ใช้ชื่อได้เฉพาะผ่านการแก้ค่าเมื่อเริ่มต้นหรือ `dangerouslyAllowNameMatching`):
|
||||
|
||||
- `requireMention`
|
||||
- `users` (allowlist)
|
||||
@ -614,55 +614,55 @@ action ข้อความ Slack ปัจจุบันประกอบด
|
||||
- `skills`
|
||||
- `systemPrompt`
|
||||
- `tools`, `toolsBySender`
|
||||
- รูปแบบคีย์ `toolsBySender`: `id:`, `e164:`, `username:`, `name:` หรือ wildcard `"*"`
|
||||
(คีย์เดิมที่ไม่มี prefix ยัง map ไปที่ `id:` เท่านั้น)
|
||||
- รูปแบบคีย์ของ `toolsBySender`: `id:`, `e164:`, `username:`, `name:`, หรือ wildcard `"*"`
|
||||
(คีย์แบบเดิมที่ไม่มีคำนำหน้ายังคงแมปไปยัง `id:` เท่านั้น)
|
||||
|
||||
`allowBots` เป็นแบบระมัดระวังสำหรับช่องและช่องส่วนตัว: ข้อความในห้องที่เขียนโดยบอทจะถูกรับเฉพาะเมื่อบอทผู้ส่งอยู่ใน allowlist `users` ของห้องนั้นอย่างชัดเจน หรือเมื่อมี ID เจ้าของ Slack ที่ชัดเจนอย่างน้อยหนึ่งรายการจาก `channels.slack.allowFrom` เป็นสมาชิกห้องอยู่ในปัจจุบัน wildcard และรายการเจ้าของแบบชื่อที่แสดงไม่ถือว่าตอบสนองเงื่อนไขการมีอยู่ของเจ้าของ การมีอยู่ของเจ้าของใช้ Slack `conversations.members`; ตรวจสอบให้แน่ใจว่าแอปมีขอบเขตการอ่านที่ตรงกับชนิดห้อง (`channels:read` สำหรับช่องสาธารณะ, `groups:read` สำหรับช่องส่วนตัว) หากการค้นหาสมาชิกล้มเหลว OpenClaw จะทิ้งข้อความในห้องที่เขียนโดยบอท
|
||||
`allowBots` มีความระมัดระวังสำหรับช่องทางและช่องทางส่วนตัว: ข้อความในห้องที่เขียนโดยบอทจะถูกรับเฉพาะเมื่อบอทผู้ส่งถูกระบุไว้อย่างชัดเจนใน allowlist `users` ของห้องนั้น หรือเมื่อมี ID เจ้าของ Slack ที่ชัดเจนอย่างน้อยหนึ่งรายการจาก `channels.slack.allowFrom` เป็นสมาชิกห้องอยู่ในขณะนั้น wildcard และรายการเจ้าของที่เป็นชื่อที่แสดงไม่ถือว่าเป็นการมีอยู่ของเจ้าของ การมีอยู่ของเจ้าของใช้ Slack `conversations.members`; ตรวจสอบให้แน่ใจว่าแอปมี scope อ่านที่ตรงกับประเภทห้อง (`channels:read` สำหรับช่องทางสาธารณะ, `groups:read` สำหรับช่องทางส่วนตัว) หากการค้นหาสมาชิกล้มเหลว OpenClaw จะทิ้งข้อความในห้องที่เขียนโดยบอท
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Threading, sessions และแท็กตอบกลับ
|
||||
## เธรด เซสชัน และแท็กตอบกลับ
|
||||
|
||||
- DM กำหนดเส้นทางเป็น `direct`; ช่องเป็น `channel`; MPIM เป็น `group`
|
||||
- การผูกเส้นทาง Slack รับ ID peer แบบดิบ รวมถึงรูปแบบเป้าหมาย Slack เช่น `channel:C12345678`, `user:U12345678` และ `<@U12345678>`
|
||||
- ด้วยค่าเริ่มต้น `session.dmScope=main` DM ของ Slack จะถูกรวมไปที่ session หลักของเอเจนต์
|
||||
- session ช่อง: `agent:<agentId>:slack:channel:<channelId>`
|
||||
- การตอบกลับใน thread สามารถสร้าง suffix ของ session thread (`:thread:<threadTs>`) ได้เมื่อเกี่ยวข้อง
|
||||
- DM กำหนดเส้นทางเป็น `direct`; ช่องทางเป็น `channel`; MPIM เป็น `group`
|
||||
- การผูกเส้นทางของ Slack รับ ID เพียร์ดิบ รวมถึงรูปแบบเป้าหมาย Slack เช่น `channel:C12345678`, `user:U12345678`, และ `<@U12345678>`
|
||||
- ด้วยค่าเริ่มต้น `session.dmScope=main` DM ของ Slack จะยุบรวมเข้าเซสชันหลักของเอเจนต์
|
||||
- เซสชันช่องทาง: `agent:<agentId>:slack:channel:<channelId>`
|
||||
- การตอบกลับในเธรดสามารถสร้างส่วนท้ายเซสชันของเธรด (`:thread:<threadTs>`) เมื่อใช้ได้
|
||||
- ค่าเริ่มต้นของ `channels.slack.thread.historyScope` คือ `thread`; ค่าเริ่มต้นของ `thread.inheritParent` คือ `false`
|
||||
- `channels.slack.thread.initialHistoryLimit` ควบคุมจำนวนข้อความ thread ที่มีอยู่ซึ่งจะถูกดึงเมื่อ session thread ใหม่เริ่มต้น (ค่าเริ่มต้น `20`; ตั้ง `0` เพื่อปิดใช้งาน)
|
||||
- `channels.slack.thread.requireExplicitMention` (ค่าเริ่มต้น `false`): เมื่อเป็น `true` จะระงับการกล่าวถึง thread โดยนัย เพื่อให้บอทตอบกลับเฉพาะการกล่าวถึง `@bot` อย่างชัดเจนภายใน thread แม้ว่าบอทจะเคยเข้าร่วมใน thread แล้วก็ตาม หากไม่มีค่านี้ การตอบกลับใน thread ที่บอทเคยเข้าร่วมจะข้าม gating ของ `requireMention`
|
||||
- `channels.slack.thread.initialHistoryLimit` ควบคุมจำนวนข้อความเธรดที่มีอยู่ซึ่งจะถูกดึงเมื่อเซสชันเธรดใหม่เริ่มต้น (ค่าเริ่มต้น `20`; ตั้งเป็น `0` เพื่อปิดใช้งาน)
|
||||
- `channels.slack.thread.requireExplicitMention` (ค่าเริ่มต้น `false`): เมื่อเป็น `true` จะระงับการกล่าวถึงเธรดโดยนัย เพื่อให้บอทตอบเฉพาะการกล่าวถึง `@bot` อย่างชัดเจนภายในเธรด แม้ว่าบอทจะเคยเข้าร่วมเธรดนั้นแล้วก็ตาม หากไม่มีค่านี้ การตอบกลับในเธรดที่บอทเคยเข้าร่วมจะข้ามการควบคุม `requireMention`
|
||||
|
||||
การควบคุม reply threading:
|
||||
การควบคุมเธรดการตอบกลับ:
|
||||
|
||||
- `channels.slack.replyToMode`: `off|first|all|batched` (ค่าเริ่มต้น `off`)
|
||||
- `channels.slack.replyToModeByChatType`: ต่อ `direct|group|channel`
|
||||
- fallback เดิมสำหรับแชทโดยตรง: `channels.slack.dm.replyToMode`
|
||||
- `channels.slack.replyToModeByChatType`: แยกตาม `direct|group|channel`
|
||||
- ค่าสำรองเดิมสำหรับแชทโดยตรง: `channels.slack.dm.replyToMode`
|
||||
|
||||
รองรับแท็กตอบกลับแบบแมนนวล:
|
||||
รองรับแท็กตอบกลับแบบกำหนดเอง:
|
||||
|
||||
- `[[reply_to_current]]`
|
||||
- `[[reply_to:<id>]]`
|
||||
|
||||
<Note>
|
||||
`replyToMode="off"` ปิดใช้งาน reply threading **ทั้งหมด** ใน Slack รวมถึงแท็ก `[[reply_to_*]]` ที่ระบุอย่างชัดเจน ซึ่งต่างจาก Telegram ที่แท็กชัดเจนยังคงทำงานในโหมด `"off"` thread ของ Slack ซ่อนข้อความจากช่อง ขณะที่การตอบกลับของ Telegram ยังคงมองเห็นแบบ inline
|
||||
`replyToMode="off"` ปิดใช้งานเธรดการตอบกลับ **ทั้งหมด** ใน Slack รวมถึงแท็ก `[[reply_to_*]]` ที่ชัดเจน ซึ่งต่างจาก Telegram ที่ยังคงใช้แท็กที่ชัดเจนในโหมด `"off"` อยู่ เธรดของ Slack ซ่อนข้อความจากช่องทาง ขณะที่การตอบกลับของ Telegram ยังคงมองเห็นแบบอินไลน์
|
||||
</Note>
|
||||
|
||||
## รีแอ็กชันตอบรับ
|
||||
## รีแอ็กชันรับทราบ
|
||||
|
||||
`ackReaction` ส่งอีโมจิยืนยันขณะที่ OpenClaw กำลังประมวลผลข้อความขาเข้า
|
||||
`ackReaction` ส่งอีโมจิรับทราบขณะที่ OpenClaw กำลังประมวลผลข้อความขาเข้า
|
||||
|
||||
ลำดับการ resolve:
|
||||
ลำดับการแก้ค่า:
|
||||
|
||||
- `channels.slack.accounts.<accountId>.ackReaction`
|
||||
- `channels.slack.ackReaction`
|
||||
- `messages.ackReaction`
|
||||
- fallback อีโมจิตัวตนของเอเจนต์ (`agents.list[].identity.emoji`, มิฉะนั้น "👀")
|
||||
- อีโมจิสำรองจากตัวตนของเอเจนต์ (`agents.list[].identity.emoji`, มิฉะนั้นเป็น "👀")
|
||||
|
||||
หมายเหตุ:
|
||||
|
||||
- Slack คาดหวัง shortcode (เช่น `"eyes"`)
|
||||
- ใช้ `""` เพื่อปิดใช้งานรีแอ็กชันสำหรับบัญชี Slack หรือทั้งระบบ
|
||||
- ใช้ `""` เพื่อปิดใช้งานรีแอ็กชันสำหรับบัญชี Slack หรือทั่วทั้งระบบ
|
||||
|
||||
## การสตรีมข้อความ
|
||||
|
||||
@ -670,20 +670,39 @@ action ข้อความ Slack ปัจจุบันประกอบด
|
||||
|
||||
- `off`: ปิดใช้งานการสตรีมตัวอย่างสด
|
||||
- `partial` (ค่าเริ่มต้น): แทนที่ข้อความตัวอย่างด้วยผลลัพธ์บางส่วนล่าสุด
|
||||
- `block`: ต่อท้ายการอัปเดตตัวอย่างแบบแบ่ง chunk
|
||||
- `progress`: แสดงข้อความสถานะความคืบหน้าขณะสร้าง จากนั้นส่งข้อความสุดท้าย
|
||||
- `streaming.preview.toolProgress`: เมื่อตัวอย่างฉบับร่างทำงานอยู่ ให้กำหนดเส้นทางการอัปเดตเครื่องมือ/ความคืบหน้าเข้าไปในข้อความตัวอย่างที่แก้ไขข้อความเดียวกัน (ค่าเริ่มต้น: `true`) ตั้งเป็น `false` เพื่อคงข้อความเครื่องมือ/ความคืบหน้าแยกกัน
|
||||
- `block`: ต่อท้ายการอัปเดตตัวอย่างเป็นชิ้น ๆ
|
||||
- `progress`: แสดงข้อความสถานะความคืบหน้าระหว่างสร้าง แล้วจึงส่งข้อความสุดท้าย
|
||||
- `streaming.preview.toolProgress`: เมื่อตัวอย่างฉบับร่างทำงาน ให้กำหนดเส้นทางการอัปเดตเครื่องมือ/ความคืบหน้าเข้าไปยังข้อความตัวอย่างที่ถูกแก้ไขเดียวกัน (ค่าเริ่มต้น: `true`) ตั้งเป็น `false` เพื่อแยกข้อความเครื่องมือ/ความคืบหน้าออกต่างหาก
|
||||
- `streaming.preview.commandText` / `streaming.progress.commandText`: ตั้งเป็น `status` เพื่อคงบรรทัดความคืบหน้าของเครื่องมือแบบกะทัดรัด พร้อมซ่อนข้อความคำสั่ง/การดำเนินการดิบ (ค่าเริ่มต้น: `raw`)
|
||||
|
||||
`channels.slack.streaming.nativeTransport` ควบคุมการสตรีมข้อความ native ของ Slack เมื่อ `channels.slack.streaming.mode` เป็น `partial` (ค่าเริ่มต้น: `true`)
|
||||
ซ่อนข้อความคำสั่ง/การดำเนินการดิบ พร้อมคงบรรทัดความคืบหน้าแบบกะทัดรัด:
|
||||
|
||||
- ต้องมี thread ตอบกลับเพื่อให้การสตรีมข้อความ native และสถานะ thread assistant ของ Slack ปรากฏ การเลือก thread ยังคงทำตาม `replyToMode`
|
||||
- ช่อง, แชทกลุ่ม และราก DM ระดับบนสุดยังสามารถใช้ตัวอย่างฉบับร่างปกติได้เมื่อ native streaming ไม่พร้อมใช้งานหรือไม่มี thread ตอบกลับ
|
||||
- DM ของ Slack ระดับบนสุดจะอยู่นอก thread โดยค่าเริ่มต้น ดังนั้นจึงไม่แสดงตัวอย่าง native stream/status แบบ thread-style ของ Slack; OpenClaw จะโพสต์และแก้ไขตัวอย่างฉบับร่างใน DM แทน
|
||||
- payload สื่อและที่ไม่ใช่ข้อความจะ fallback ไปยังการส่งมอบปกติ
|
||||
- ผลสุดท้ายของสื่อ/ข้อผิดพลาดจะยกเลิกการแก้ไขตัวอย่างที่ค้างอยู่; ผลสุดท้ายแบบข้อความ/บล็อกที่เข้าเกณฑ์จะ flush เฉพาะเมื่อสามารถแก้ไขตัวอย่างในตำแหน่งเดิมได้
|
||||
- หากการสตรีมล้มเหลวระหว่างตอบกลับ OpenClaw จะ fallback ไปยังการส่งมอบปกติสำหรับ payload ที่เหลือ
|
||||
```json
|
||||
{
|
||||
"channels": {
|
||||
"slack": {
|
||||
"streaming": {
|
||||
"mode": "progress",
|
||||
"progress": {
|
||||
"toolProgress": true,
|
||||
"commandText": "status"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
ใช้ตัวอย่างฉบับร่างแทนการสตรีมข้อความ native ของ Slack:
|
||||
`channels.slack.streaming.nativeTransport` ควบคุมการสตรีมข้อความแบบเนทีฟของ Slack เมื่อ `channels.slack.streaming.mode` เป็น `partial` (ค่าเริ่มต้น: `true`)
|
||||
|
||||
- ต้องมีเธรดตอบกลับสำหรับการสตรีมข้อความแบบเนทีฟและเพื่อให้สถานะเธรดผู้ช่วยของ Slack ปรากฏ การเลือกเธรดยังคงเป็นไปตาม `replyToMode`
|
||||
- รากของช่องทาง แชทกลุ่ม และ DM ระดับบนยังคงใช้ตัวอย่างฉบับร่างปกติได้เมื่อการสตรีมแบบเนทีฟใช้ไม่ได้หรือไม่มีเธรดตอบกลับ
|
||||
- DM ระดับบนของ Slack ยังคงอยู่นอกเธรดโดยค่าเริ่มต้น ดังนั้นจึงไม่แสดงตัวอย่างสตรีม/สถานะแบบเนทีฟสไตล์เธรดของ Slack; OpenClaw จะโพสต์และแก้ไขตัวอย่างฉบับร่างใน DM แทน
|
||||
- สื่อและ payload ที่ไม่ใช่ข้อความจะย้อนกลับไปใช้การส่งตามปกติ
|
||||
- ผลลัพธ์สุดท้ายของสื่อ/ข้อผิดพลาดจะยกเลิกการแก้ไขตัวอย่างที่ค้างอยู่; ผลลัพธ์สุดท้ายของข้อความ/บล็อกที่เข้าเกณฑ์จะ flush เฉพาะเมื่อสามารถแก้ไขตัวอย่างเดิมได้
|
||||
- หากการสตรีมล้มเหลวระหว่างการตอบกลับ OpenClaw จะย้อนกลับไปใช้การส่งตามปกติสำหรับ payload ที่เหลือ
|
||||
|
||||
ใช้ตัวอย่างฉบับร่างแทนการสตรีมข้อความแบบเนทีฟของ Slack:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -700,58 +719,58 @@ action ข้อความ Slack ปัจจุบันประกอบด
|
||||
|
||||
คีย์เดิม:
|
||||
|
||||
- `channels.slack.streamMode` (`replace | status_final | append`) ถูกย้ายอัตโนมัติไปเป็น `channels.slack.streaming.mode`
|
||||
- boolean `channels.slack.streaming` ถูกย้ายอัตโนมัติไปเป็น `channels.slack.streaming.mode` และ `channels.slack.streaming.nativeTransport`
|
||||
- `channels.slack.nativeStreaming` เดิมถูกย้ายอัตโนมัติไปเป็น `channels.slack.streaming.nativeTransport`
|
||||
- `channels.slack.streamMode` (`replace | status_final | append`) จะถูกย้ายโดยอัตโนมัติไปยัง `channels.slack.streaming.mode`
|
||||
- boolean `channels.slack.streaming` จะถูกย้ายโดยอัตโนมัติไปยัง `channels.slack.streaming.mode` และ `channels.slack.streaming.nativeTransport`
|
||||
- `channels.slack.nativeStreaming` แบบเดิมจะถูกย้ายโดยอัตโนมัติไปยัง `channels.slack.streaming.nativeTransport`
|
||||
|
||||
## fallback ของรีแอ็กชันการพิมพ์
|
||||
## ค่าสำรองรีแอ็กชันการพิมพ์
|
||||
|
||||
`typingReaction` เพิ่มรีแอ็กชันชั่วคราวให้กับข้อความ Slack ขาเข้าขณะที่ OpenClaw กำลังประมวลผลการตอบกลับ จากนั้นลบออกเมื่อการรันเสร็จสิ้น สิ่งนี้มีประโยชน์มากที่สุดภายนอกการตอบกลับใน thread ซึ่งใช้ตัวบ่งชี้สถานะเริ่มต้น "is typing..."
|
||||
`typingReaction` จะเพิ่มรีแอคชันชั่วคราวให้กับข้อความ Slack ขาเข้าขณะที่ OpenClaw กำลังประมวลผลคำตอบ แล้วลบออกเมื่อการรันเสร็จสิ้น วิธีนี้มีประโยชน์มากที่สุดนอกเหนือจากการตอบกลับในเธรด ซึ่งใช้ตัวบ่งชี้สถานะเริ่มต้นว่า "กำลังพิมพ์..."
|
||||
|
||||
ลำดับการ resolve:
|
||||
ลำดับการแก้ไขค่า:
|
||||
|
||||
- `channels.slack.accounts.<accountId>.typingReaction`
|
||||
- `channels.slack.typingReaction`
|
||||
|
||||
หมายเหตุ:
|
||||
|
||||
- Slack คาดหวัง shortcode (เช่น `"hourglass_flowing_sand"`)
|
||||
- reaction เป็นแบบ best-effort และจะพยายามล้างข้อมูลอัตโนมัติหลังจากเส้นทางการตอบกลับหรือความล้มเหลวเสร็จสิ้น
|
||||
- Slack คาดหวัง shortcodes (ตัวอย่างเช่น `"hourglass_flowing_sand"`)
|
||||
- รีแอคชันเป็นแบบพยายามอย่างดีที่สุด และจะพยายามล้างค่าโดยอัตโนมัติหลังจากเส้นทางการตอบกลับหรือความล้มเหลวเสร็จสมบูรณ์
|
||||
|
||||
## สื่อ, การแบ่งชิ้นส่วน, และการส่งมอบ
|
||||
## สื่อ การแบ่งชิ้น และการส่งมอบ
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Inbound attachments">
|
||||
ไฟล์แนบของ Slack จะถูกดาวน์โหลดจาก URL ส่วนตัวที่โฮสต์โดย Slack (โฟลว์คำขอที่ยืนยันตัวตนด้วย token) และเขียนลง media store เมื่อ fetch สำเร็จและขีดจำกัดขนาดอนุญาต placeholder ของไฟล์จะมี Slack `fileId` เพื่อให้ agent สามารถ fetch ไฟล์ต้นฉบับด้วย `download-file`
|
||||
<Accordion title="ไฟล์แนบขาเข้า">
|
||||
ไฟล์แนบ Slack จะถูกดาวน์โหลดจาก URL ส่วนตัวที่ Slack โฮสต์ไว้ (โฟลว์คำขอที่ตรวจสอบสิทธิ์ด้วยโทเค็น) และเขียนลงในที่เก็บสื่อเมื่อดึงข้อมูลสำเร็จและข้อจำกัดขนาดอนุญาต ตัวแทนไฟล์มี `fileId` ของ Slack เพื่อให้เอเจนต์ดึงไฟล์ต้นฉบับด้วย `download-file` ได้
|
||||
|
||||
การดาวน์โหลดใช้ timeout ทั้งแบบ idle และ total ที่มีขอบเขตจำกัด หากการดึงไฟล์ Slack ค้างหรือล้มเหลว OpenClaw จะประมวลผลข้อความต่อไปและ fallback ไปยัง placeholder ของไฟล์
|
||||
การดาวน์โหลดใช้ timeout แบบ idle และรวมที่มีขอบเขตจำกัด หากการดึงไฟล์ Slack ค้างหรือล้มเหลว OpenClaw จะประมวลผลข้อความต่อไปและถอยกลับไปใช้ตัวแทนไฟล์
|
||||
|
||||
ค่าเริ่มต้นของขีดจำกัดขนาด inbound ระหว่าง runtime คือ `20MB` เว้นแต่จะถูก override ด้วย `channels.slack.mediaMaxMb`
|
||||
ขีดจำกัดขนาดขาเข้าขณะรันมีค่าเริ่มต้นเป็น `20MB` เว้นแต่จะถูกแทนที่ด้วย `channels.slack.mediaMaxMb`
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Outbound text and files">
|
||||
- ชิ้นส่วนข้อความใช้ `channels.slack.textChunkLimit` (ค่าเริ่มต้น 4000)
|
||||
- `channels.slack.chunkMode="newline"` เปิดใช้การแบ่งแบบย่อหน้าก่อน
|
||||
- การส่งไฟล์ใช้ Slack upload APIs และสามารถรวมการตอบกลับใน thread (`thread_ts`)
|
||||
- ขีดจำกัดสื่อ outbound จะทำตาม `channels.slack.mediaMaxMb` เมื่อกำหนดค่าไว้ มิฉะนั้นการส่งผ่าน channel จะใช้ค่าเริ่มต้นตามชนิด MIME จาก media pipeline
|
||||
<Accordion title="ข้อความและไฟล์ขาออก">
|
||||
- ชิ้นข้อความใช้ `channels.slack.textChunkLimit` (ค่าเริ่มต้น 4000)
|
||||
- `channels.slack.chunkMode="newline"` เปิดใช้การแบ่งแบบยึดย่อหน้าเป็นหลัก
|
||||
- การส่งไฟล์ใช้ API อัปโหลดของ Slack และสามารถรวมการตอบกลับในเธรด (`thread_ts`) ได้
|
||||
- ขีดจำกัดสื่อขาออกใช้ `channels.slack.mediaMaxMb` เมื่อกำหนดค่าไว้ มิฉะนั้นการส่งของช่องทางจะใช้ค่าเริ่มต้นตามชนิด MIME จากไปป์ไลน์สื่อ
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Delivery targets">
|
||||
เป้าหมายแบบชัดเจนที่แนะนำ:
|
||||
<Accordion title="เป้าหมายการส่งมอบ">
|
||||
เป้าหมายแบบระบุชัดเจนที่แนะนำ:
|
||||
|
||||
- `user:<id>` สำหรับ DM
|
||||
- `channel:<id>` สำหรับ channel
|
||||
- `channel:<id>` สำหรับช่องทาง
|
||||
|
||||
Slack DM ที่เป็นข้อความ/บล็อกเท่านั้นสามารถโพสต์ไปยัง user ID ได้โดยตรง ส่วนการอัปโหลดไฟล์และการส่งแบบ thread จะเปิด DM ผ่าน Slack conversation APIs ก่อน เพราะเส้นทางเหล่านั้นต้องใช้ conversation ID ที่เป็นรูปธรรม
|
||||
DM ของ Slack ที่เป็นข้อความ/บล็อกอย่างเดียวสามารถโพสต์ไปยัง ID ผู้ใช้ได้โดยตรง ส่วนการอัปโหลดไฟล์และการส่งในเธรดจะเปิด DM ผ่าน API การสนทนาของ Slack ก่อน เพราะเส้นทางเหล่านั้นต้องใช้ ID การสนทนาที่เป็นรูปธรรม
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## คำสั่งและพฤติกรรม slash
|
||||
|
||||
คำสั่ง slash จะปรากฏใน Slack เป็นคำสั่งเดียวที่กำหนดค่าไว้ หรือเป็นหลายคำสั่ง native กำหนดค่า `channels.slack.slashCommand` เพื่อเปลี่ยนค่าเริ่มต้นของคำสั่ง:
|
||||
คำสั่ง slash ปรากฏใน Slack เป็นคำสั่งที่กำหนดค่าไว้คำสั่งเดียวหรือคำสั่ง native หลายคำสั่ง กำหนดค่า `channels.slack.slashCommand` เพื่อเปลี่ยนค่าเริ่มต้นของคำสั่ง:
|
||||
|
||||
- `enabled: false`
|
||||
- `name: "openclaw"`
|
||||
@ -762,32 +781,32 @@ action ข้อความ Slack ปัจจุบันประกอบด
|
||||
/openclaw /help
|
||||
```
|
||||
|
||||
คำสั่ง native ต้องใช้ [การตั้งค่า manifest เพิ่มเติม](#additional-manifest-settings) ในแอป Slack ของคุณ และเปิดใช้ด้วย `channels.slack.commands.native: true` หรือ `commands.native: true` ในการกำหนดค่าระดับ global แทน
|
||||
คำสั่ง native ต้องใช้ [การตั้งค่า manifest เพิ่มเติม](#additional-manifest-settings) ในแอป Slack ของคุณ และเปิดใช้ด้วย `channels.slack.commands.native: true` หรือ `commands.native: true` ในการกำหนดค่าส่วนกลางแทน
|
||||
|
||||
- โหมดอัตโนมัติของคำสั่ง native จะ **ปิด** สำหรับ Slack ดังนั้น `commands.native: "auto"` จะไม่เปิดใช้คำสั่ง native ของ Slack
|
||||
- โหมดอัตโนมัติของคำสั่ง native **ปิดอยู่** สำหรับ Slack ดังนั้น `commands.native: "auto"` จึงไม่เปิดใช้คำสั่ง native ของ Slack
|
||||
|
||||
```txt
|
||||
/help
|
||||
```
|
||||
|
||||
เมนู argument แบบ native ใช้กลยุทธ์การ render แบบ adaptive ที่แสดง modal ยืนยันก่อน dispatch ค่า option ที่เลือก:
|
||||
เมนูอาร์กิวเมนต์ native ใช้กลยุทธ์การเรนเดอร์แบบปรับตามบริบท ซึ่งแสดงโมดัลยืนยันก่อน dispatch ค่าตัวเลือกที่เลือก:
|
||||
|
||||
- สูงสุด 5 options: บล็อกปุ่ม
|
||||
- 6-100 options: เมนู static select
|
||||
- มากกว่า 100 options: external select พร้อมการกรอง option แบบ async เมื่อมีตัวจัดการ interactivity options
|
||||
- เกินขีดจำกัดของ Slack: ค่า option ที่เข้ารหัสจะ fallback ไปเป็นปุ่ม
|
||||
- สูงสุด 5 ตัวเลือก: บล็อกปุ่ม
|
||||
- 6-100 ตัวเลือก: เมนู static select
|
||||
- มากกว่า 100 ตัวเลือก: external select พร้อมการกรองตัวเลือกแบบ async เมื่อมีตัวจัดการตัวเลือก interactivity
|
||||
- เกินขีดจำกัดของ Slack: ค่าตัวเลือกที่เข้ารหัสจะถอยกลับไปใช้ปุ่ม
|
||||
|
||||
```txt
|
||||
/think
|
||||
```
|
||||
|
||||
session แบบ slash ใช้คีย์แยก เช่น `agent:<agentId>:slack:slash:<userId>` และยังคง route การรันคำสั่งไปยัง session การสนทนาเป้าหมายโดยใช้ `CommandTargetSessionKey`
|
||||
เซสชัน slash ใช้คีย์แยกกัน เช่น `agent:<agentId>:slack:slash:<userId>` และยังคงกำหนดเส้นทางการดำเนินคำสั่งไปยังเซสชันการสนทนาเป้าหมายโดยใช้ `CommandTargetSessionKey`
|
||||
|
||||
## การตอบกลับแบบ interactive
|
||||
## การตอบกลับแบบอินเทอร์แอคทีฟ
|
||||
|
||||
Slack สามารถ render คอนโทรลการตอบกลับแบบ interactive ที่ agent เขียนได้ แต่ฟีเจอร์นี้ถูกปิดไว้โดยค่าเริ่มต้น
|
||||
Slack สามารถเรนเดอร์ตัวควบคุมการตอบกลับแบบอินเทอร์แอคทีฟที่เอเจนต์เขียนได้ แต่ฟีเจอร์นี้ถูกปิดไว้โดยค่าเริ่มต้น
|
||||
|
||||
เปิดใช้แบบ global:
|
||||
เปิดใช้แบบทั่วทั้งระบบ:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -801,7 +820,7 @@ Slack สามารถ render คอนโทรลการตอบกลั
|
||||
}
|
||||
```
|
||||
|
||||
หรือเปิดใช้เฉพาะบัญชี Slack หนึ่งบัญชี:
|
||||
หรือเปิดใช้เฉพาะบัญชี Slack บัญชีเดียว:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -819,44 +838,44 @@ Slack สามารถ render คอนโทรลการตอบกลั
|
||||
}
|
||||
```
|
||||
|
||||
เมื่อเปิดใช้แล้ว agent สามารถ emit directive การตอบกลับเฉพาะ Slack ได้:
|
||||
เมื่อเปิดใช้ เอเจนต์สามารถปล่อย directive การตอบกลับเฉพาะ Slack ได้:
|
||||
|
||||
- `[[slack_buttons: Approve:approve, Reject:reject]]`
|
||||
- `[[slack_select: Choose a target | Canary:canary, Production:production]]`
|
||||
|
||||
directive เหล่านี้จะ compile เป็น Slack Block Kit และ route การคลิกหรือการเลือกกลับผ่านเส้นทาง event interaction ของ Slack ที่มีอยู่
|
||||
Directive เหล่านี้คอมไพล์เป็น Slack Block Kit และกำหนดเส้นทางการคลิกหรือการเลือกกลับผ่านเส้นทางเหตุการณ์การโต้ตอบ Slack ที่มีอยู่
|
||||
|
||||
หมายเหตุ:
|
||||
|
||||
- นี่คือ UI เฉพาะ Slack channel อื่นจะไม่แปล directive ของ Slack Block Kit เป็นระบบปุ่มของตนเอง
|
||||
- ค่า callback แบบ interactive เป็น opaque token ที่ OpenClaw สร้างขึ้น ไม่ใช่ค่าดิบที่ agent เขียน
|
||||
- หากบล็อก interactive ที่สร้างขึ้นจะเกินขีดจำกัดของ Slack Block Kit, OpenClaw จะ fallback ไปยังข้อความตอบกลับเดิมแทนการส่ง payload blocks ที่ไม่ถูกต้อง
|
||||
- นี่คือ UI เฉพาะ Slack ช่องทางอื่นจะไม่แปล directive ของ Slack Block Kit เป็นระบบปุ่มของตนเอง
|
||||
- ค่าคอลแบ็กแบบอินเทอร์แอคทีฟเป็นโทเค็นทึบที่ OpenClaw สร้างขึ้น ไม่ใช่ค่าดิบที่เอเจนต์เขียน
|
||||
- หากบล็อกอินเทอร์แอคทีฟที่สร้างขึ้นจะเกินขีดจำกัด Slack Block Kit OpenClaw จะถอยกลับไปใช้ข้อความตอบกลับเดิมแทนการส่ง payload บล็อกที่ไม่ถูกต้อง
|
||||
|
||||
## การอนุมัติ exec ใน Slack
|
||||
## การอนุมัติ Exec ใน Slack
|
||||
|
||||
Slack สามารถทำหน้าที่เป็น client การอนุมัติ native พร้อมปุ่มและ interaction แบบ interactive แทนการ fallback ไปยัง Web UI หรือ terminal
|
||||
Slack สามารถทำหน้าที่เป็นไคลเอนต์อนุมัติ native ที่มีปุ่มและการโต้ตอบแบบอินเทอร์แอคทีฟ แทนการถอยกลับไปใช้ Web UI หรือเทอร์มินัล
|
||||
|
||||
- การอนุมัติ exec ใช้ `channels.slack.execApprovals.*` สำหรับการ route DM/channel แบบ native
|
||||
- การอนุมัติ Plugin ยังสามารถ resolve ผ่านพื้นผิวปุ่ม native ของ Slack เดียวกันได้ เมื่อคำขอมาถึง Slack อยู่แล้วและชนิด approval id คือ `plugin:`
|
||||
- การตรวจสอบสิทธิ์ผู้อนุมัติยังคงถูกบังคับใช้: เฉพาะผู้ใช้ที่ระบุเป็น approver เท่านั้นที่สามารถ approve หรือ deny คำขอผ่าน Slack ได้
|
||||
- การอนุมัติ Exec ใช้ `channels.slack.execApprovals.*` สำหรับการกำหนดเส้นทาง DM/ช่องทางแบบ native
|
||||
- การอนุมัติ Plugin ยังสามารถแก้ไขผ่านพื้นผิวปุ่ม Slack-native เดียวกันได้ เมื่อคำขอมาถึง Slack อยู่แล้วและชนิด approval id เป็น `plugin:`
|
||||
- การให้สิทธิ์ผู้อนุมัติยังคงถูกบังคับใช้: เฉพาะผู้ใช้ที่ระบุว่าเป็นผู้อนุมัติเท่านั้นที่สามารถอนุมัติหรือปฏิเสธคำขอผ่าน Slack ได้
|
||||
|
||||
สิ่งนี้ใช้พื้นผิวปุ่มการอนุมัติร่วมแบบเดียวกับ channel อื่น เมื่อเปิดใช้ `interactivity` ในการตั้งค่าแอป Slack ของคุณ prompt การอนุมัติจะ render เป็นปุ่ม Block Kit โดยตรงในการสนทนา
|
||||
สิ่งนี้ใช้พื้นผิวปุ่มอนุมัติแบบใช้ร่วมกันเดียวกับช่องทางอื่น เมื่อเปิดใช้ `interactivity` ในการตั้งค่าแอป Slack ของคุณ พรอมป์อนุมัติจะเรนเดอร์เป็นปุ่ม Block Kit โดยตรงในการสนทนา
|
||||
เมื่อมีปุ่มเหล่านั้น ปุ่มเหล่านั้นคือ UX การอนุมัติหลัก OpenClaw
|
||||
ควรรวมคำสั่ง `/approve` แบบ manual เฉพาะเมื่อผลลัพธ์ของเครื่องมือบอกว่าการอนุมัติผ่าน chat
|
||||
ไม่พร้อมใช้งาน หรือการอนุมัติแบบ manual เป็นเส้นทางเดียวเท่านั้น
|
||||
ควรรวมคำสั่ง `/approve` แบบแมนนวลเฉพาะเมื่อผลลัพธ์ของเครื่องมือบอกว่าการอนุมัติผ่านแชต
|
||||
ไม่พร้อมใช้งาน หรือการอนุมัติแบบแมนนวลเป็นเส้นทางเดียวเท่านั้น
|
||||
|
||||
เส้นทาง config:
|
||||
เส้นทางการกำหนดค่า:
|
||||
|
||||
- `channels.slack.execApprovals.enabled`
|
||||
- `channels.slack.execApprovals.approvers` (ไม่บังคับ; fallback ไปยัง `commands.ownerAllowFrom` เมื่อเป็นไปได้)
|
||||
- `channels.slack.execApprovals.approvers` (ไม่บังคับ; ถอยกลับไปใช้ `commands.ownerAllowFrom` เมื่อเป็นไปได้)
|
||||
- `channels.slack.execApprovals.target` (`dm` | `channel` | `both`, ค่าเริ่มต้น: `dm`)
|
||||
- `agentFilter`, `sessionFilter`
|
||||
|
||||
Slack จะเปิดใช้การอนุมัติ exec แบบ native โดยอัตโนมัติเมื่อไม่ได้ตั้งค่า `enabled` หรือเป็น `"auto"` และ resolve
|
||||
approver ได้อย่างน้อยหนึ่งรายการ ตั้งค่า `enabled: false` เพื่อปิดใช้ Slack เป็น client การอนุมัติ native อย่างชัดเจน
|
||||
ตั้งค่า `enabled: true` เพื่อบังคับเปิดการอนุมัติ native เมื่อ resolve approver ได้
|
||||
Slack จะเปิดใช้การอนุมัติ exec แบบ native โดยอัตโนมัติเมื่อไม่ได้ตั้งค่า `enabled` หรือเป็น `"auto"` และแก้ไขผู้อนุมัติได้อย่างน้อยหนึ่งราย
|
||||
ตั้งค่า `enabled: false` เพื่อปิดใช้ Slack เป็นไคลเอนต์อนุมัติ native อย่างชัดเจน
|
||||
ตั้งค่า `enabled: true` เพื่อบังคับเปิดการอนุมัติ native เมื่อแก้ไขผู้อนุมัติได้
|
||||
|
||||
พฤติกรรมเริ่มต้นเมื่อไม่มี config การอนุมัติ exec ของ Slack ที่ชัดเจน:
|
||||
พฤติกรรมเริ่มต้นเมื่อไม่มีการกำหนดค่าการอนุมัติ exec ของ Slack อย่างชัดเจน:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -866,8 +885,8 @@ approver ได้อย่างน้อยหนึ่งรายการ
|
||||
}
|
||||
```
|
||||
|
||||
config แบบ Slack-native ที่ชัดเจนจำเป็นเฉพาะเมื่อคุณต้องการ override approver, เพิ่ม filter, หรือ
|
||||
เลือกใช้การส่งมอบไปยัง chat ต้นทาง:
|
||||
การกำหนดค่า Slack-native แบบชัดเจนจำเป็นเฉพาะเมื่อคุณต้องการแทนที่ผู้อนุมัติ เพิ่มตัวกรอง หรือ
|
||||
เลือกใช้การส่งมอบไปยังแชตต้นทาง:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -883,52 +902,52 @@ config แบบ Slack-native ที่ชัดเจนจำเป็นเ
|
||||
}
|
||||
```
|
||||
|
||||
การส่งต่อ `approvals.exec` แบบ shared แยกต่างหาก ใช้เฉพาะเมื่อ prompt การอนุมัติ exec ต้อง
|
||||
route ไปยัง chat อื่นหรือเป้าหมาย out-of-band ที่ชัดเจนด้วย การส่งต่อ `approvals.plugin` แบบ shared ก็
|
||||
แยกต่างหากเช่นกัน ปุ่ม Slack-native ยังคงสามารถ resolve การอนุมัติ Plugin ได้เมื่อคำขอเหล่านั้นมาถึง
|
||||
การส่งต่อ `approvals.exec` แบบใช้ร่วมกันแยกต่างหาก ใช้เฉพาะเมื่อพรอมป์อนุมัติ exec ต้อง
|
||||
กำหนดเส้นทางไปยังแชตอื่นหรือเป้าหมายนอกแบนด์ที่ระบุชัดเจนด้วย การส่งต่อ `approvals.plugin` แบบใช้ร่วมกันก็
|
||||
แยกต่างหากเช่นกัน ปุ่ม Slack-native ยังสามารถแก้ไขการอนุมัติ Plugin ได้เมื่อคำขอเหล่านั้นมาถึง
|
||||
Slack อยู่แล้ว
|
||||
|
||||
`/approve` ใน chat เดียวกันยังทำงานใน channel และ DM ของ Slack ที่รองรับคำสั่งอยู่แล้ว ดู [การอนุมัติ exec](/th/tools/exec-approvals) สำหรับโมเดลการส่งต่อการอนุมัติแบบเต็ม
|
||||
`/approve` ในแชตเดียวกันยังใช้ได้ในช่องทาง Slack และ DM ที่รองรับคำสั่งอยู่แล้ว ดู [การอนุมัติ Exec](/th/tools/exec-approvals) สำหรับโมเดลการส่งต่อการอนุมัติฉบับเต็ม
|
||||
|
||||
## Events และพฤติกรรมการปฏิบัติการ
|
||||
## เหตุการณ์และพฤติกรรมการปฏิบัติการ
|
||||
|
||||
- การแก้ไข/ลบข้อความจะถูก map เป็น system events
|
||||
- thread broadcast (การตอบกลับ thread แบบ "Also send to channel") จะถูกประมวลผลเป็นข้อความผู้ใช้ปกติ
|
||||
- event การเพิ่ม/ลบ reaction จะถูก map เป็น system events
|
||||
- event สมาชิกเข้าร่วม/ออก, channel ถูกสร้าง/เปลี่ยนชื่อ, และ pin ถูกเพิ่ม/ลบ จะถูก map เป็น system events
|
||||
- `channel_id_changed` สามารถ migrate คีย์ config ของ channel ได้เมื่อเปิดใช้ `configWrites`
|
||||
- metadata ของหัวข้อ/วัตถุประสงค์ channel จะถูกปฏิบัติเป็น context ที่ไม่น่าเชื่อถือ และสามารถ inject เข้าไปใน routing context ได้
|
||||
- thread starter และการ seed context จากประวัติ thread เริ่มต้นจะถูกกรองด้วย allowlist ผู้ส่งที่กำหนดค่าไว้เมื่อเกี่ยวข้อง
|
||||
- block actions และ modal interactions จะ emit system events แบบมีโครงสร้าง `Slack interaction: ...` พร้อมฟิลด์ payload ที่ละเอียด:
|
||||
- block actions: ค่าที่เลือก, label, ค่า picker, และ metadata `workflow_*`
|
||||
- event modal `view_submission` และ `view_closed` พร้อม metadata channel ที่ถูก route และ input ของฟอร์ม
|
||||
- การแก้ไข/ลบข้อความถูกแมปเป็นเหตุการณ์ระบบ
|
||||
- การ broadcast เธรด (การตอบกลับในเธรดแบบ "ส่งไปยังช่องทางด้วย") ถูกประมวลผลเป็นข้อความผู้ใช้ปกติ
|
||||
- เหตุการณ์เพิ่ม/ลบรีแอคชันถูกแมปเป็นเหตุการณ์ระบบ
|
||||
- เหตุการณ์สมาชิกเข้าร่วม/ออก ช่องทางถูกสร้าง/เปลี่ยนชื่อ และการเพิ่ม/ลบ pin ถูกแมปเป็นเหตุการณ์ระบบ
|
||||
- `channel_id_changed` สามารถย้ายคีย์การกำหนดค่าช่องทางเมื่อเปิดใช้ `configWrites`
|
||||
- เมตาดาต้า topic/purpose ของช่องทางถือเป็นบริบทที่ไม่น่าเชื่อถือและสามารถถูกฉีดเข้าไปในบริบทการกำหนดเส้นทางได้
|
||||
- การ seed บริบทของผู้เริ่มเธรดและประวัติเธรดเริ่มต้นจะถูกกรองตาม allowlist ผู้ส่งที่กำหนดค่าไว้เมื่อเกี่ยวข้อง
|
||||
- Block actions และการโต้ตอบ modal ปล่อยเหตุการณ์ระบบ `Slack interaction: ...` แบบมีโครงสร้าง พร้อมฟิลด์ payload ที่สมบูรณ์:
|
||||
- block actions: ค่าที่เลือก, labels, ค่า picker และเมตาดาต้า `workflow_*`
|
||||
- เหตุการณ์ modal `view_submission` และ `view_closed` พร้อมเมตาดาต้าช่องทางที่กำหนดเส้นทางและอินพุตฟอร์ม
|
||||
|
||||
## ข้อมูลอ้างอิงการกำหนดค่า
|
||||
|
||||
ข้อมูลอ้างอิงหลัก: [ข้อมูลอ้างอิงการกำหนดค่า - Slack](/th/gateway/config-channels#slack)
|
||||
|
||||
<Accordion title="High-signal Slack fields">
|
||||
<Accordion title="ฟิลด์ Slack ที่มีสัญญาณสูง">
|
||||
|
||||
- mode/auth: `mode`, `botToken`, `appToken`, `signingSecret`, `webhookPath`, `accounts.*`
|
||||
- การเข้าถึง DM: `dm.enabled`, `dmPolicy`, `allowFrom` (legacy: `dm.policy`, `dm.allowFrom`), `dm.groupEnabled`, `dm.groupChannels`
|
||||
- toggle ความเข้ากันได้: `dangerouslyAllowNameMatching` (break-glass; ปิดไว้เว้นแต่จำเป็น)
|
||||
- การเข้าถึง channel: `groupPolicy`, `channels.*`, `channels.*.users`, `channels.*.requireMention`
|
||||
- threading/history: `replyToMode`, `replyToModeByChatType`, `thread.*`, `historyLimit`, `dmHistoryLimit`, `dms.*.historyLimit`
|
||||
- delivery: `textChunkLimit`, `chunkMode`, `mediaMaxMb`, `streaming`, `streaming.nativeTransport`, `streaming.preview.toolProgress`
|
||||
- ops/features: `configWrites`, `commands.native`, `slashCommand.*`, `actions.*`, `userToken`, `userTokenReadOnly`
|
||||
- สวิตช์ความเข้ากันได้: `dangerouslyAllowNameMatching` (break-glass; ปิดไว้เว้นแต่จำเป็น)
|
||||
- การเข้าถึงช่องทาง: `groupPolicy`, `channels.*`, `channels.*.users`, `channels.*.requireMention`
|
||||
- เธรด/ประวัติ: `replyToMode`, `replyToModeByChatType`, `thread.*`, `historyLimit`, `dmHistoryLimit`, `dms.*.historyLimit`
|
||||
- การส่งมอบ: `textChunkLimit`, `chunkMode`, `mediaMaxMb`, `streaming`, `streaming.nativeTransport`, `streaming.preview.toolProgress`
|
||||
- ops/ฟีเจอร์: `configWrites`, `commands.native`, `slashCommand.*`, `actions.*`, `userToken`, `userTokenReadOnly`
|
||||
|
||||
</Accordion>
|
||||
|
||||
## การแก้ไขปัญหา
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="No replies in channels">
|
||||
<Accordion title="ไม่มีการตอบกลับในช่องทาง">
|
||||
ตรวจสอบตามลำดับ:
|
||||
|
||||
- `groupPolicy`
|
||||
- allowlist ของ channel (`channels.slack.channels`) — **คีย์ต้องเป็น channel ID** (`C12345678`) ไม่ใช่ชื่อ (`#channel-name`) คีย์ที่อิงชื่อจะล้มเหลวแบบเงียบภายใต้ `groupPolicy: "allowlist"` เพราะค่าเริ่มต้นของการ route channel ใช้ ID ก่อน วิธีหา ID: คลิกขวาที่ channel ใน Slack → **Copy link** — ค่า `C...` ที่ท้าย URL คือ channel ID
|
||||
- allowlist ของช่องทาง (`channels.slack.channels`) — **คีย์ต้องเป็น ID ช่องทาง** (`C12345678`) ไม่ใช่ชื่อ (`#channel-name`) คีย์แบบอิงชื่อจะล้มเหลวแบบเงียบภายใต้ `groupPolicy: "allowlist"` เพราะการกำหนดเส้นทางช่องทางใช้ ID เป็นหลักโดยค่าเริ่มต้น วิธีหา ID: คลิกขวาที่ช่องทางใน Slack → **Copy link** — ค่า `C...` ที่ท้าย URL คือ ID ช่องทาง
|
||||
- `requireMention`
|
||||
- allowlist `users` ต่อ channel
|
||||
- allowlist `users` รายช่องทาง
|
||||
|
||||
คำสั่งที่มีประโยชน์:
|
||||
|
||||
@ -940,15 +959,15 @@ openclaw doctor
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="DM messages ignored">
|
||||
<Accordion title="ข้อความ DM ถูกละเว้น">
|
||||
ตรวจสอบ:
|
||||
|
||||
- `channels.slack.dm.enabled`
|
||||
- `channels.slack.dmPolicy` (หรือ legacy `channels.slack.dm.policy`)
|
||||
- การอนุมัติ pairing / รายการ allowlist
|
||||
- event DM ของ Slack Assistant: log แบบ verbose ที่กล่าวถึง `drop message_changed`
|
||||
มักหมายความว่า Slack ส่ง event thread ของ Assistant ที่ถูกแก้ไขโดยไม่มี
|
||||
ผู้ส่งมนุษย์ที่กู้คืนได้ใน metadata ของข้อความ
|
||||
- การอนุมัติการจับคู่ / รายการ allowlist
|
||||
- เหตุการณ์ DM ของ Slack Assistant: บันทึก verbose ที่กล่าวถึง `drop message_changed`
|
||||
มักหมายความว่า Slack ส่งเหตุการณ์เธรด Assistant ที่ถูกแก้ไขโดยไม่มี
|
||||
ผู้ส่งที่เป็นมนุษย์ซึ่งกู้คืนได้ในเมตาดาต้าข้อความ
|
||||
|
||||
```bash
|
||||
openclaw pairing list slack
|
||||
@ -956,105 +975,105 @@ openclaw pairing list slack
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Socket mode not connecting">
|
||||
ตรวจสอบ bot + app token และการเปิดใช้ Socket Mode ในการตั้งค่าแอป Slack
|
||||
<Accordion title="Socket mode ไม่เชื่อมต่อ">
|
||||
ตรวจสอบ bot + app tokens และการเปิดใช้ Socket Mode ในการตั้งค่าแอป Slack
|
||||
|
||||
หาก `openclaw channels status --probe --json` แสดง `botTokenStatus` หรือ
|
||||
`appTokenStatus: "configured_unavailable"` แสดงว่าบัญชี Slack ถูก
|
||||
กำหนดค่าแล้ว แต่ runtime ปัจจุบันไม่สามารถ resolve ค่า
|
||||
`appTokenStatus: "configured_unavailable"` แสดงว่าบัญชี Slack
|
||||
ถูกกำหนดค่าไว้ แต่ runtime ปัจจุบันไม่สามารถแก้ไขค่า
|
||||
ที่รองรับด้วย SecretRef ได้
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="HTTP mode not receiving events">
|
||||
<Accordion title="HTTP mode ไม่ได้รับเหตุการณ์">
|
||||
ตรวจสอบ:
|
||||
|
||||
- signing secret
|
||||
- path ของ Webhook
|
||||
- webhook path
|
||||
- Slack Request URLs (Events + Interactivity + Slash Commands)
|
||||
- `webhookPath` ที่ไม่ซ้ำกันต่อบัญชี HTTP
|
||||
|
||||
หาก `signingSecretStatus: "configured_unavailable"` ปรากฏใน snapshot
|
||||
ของบัญชี แสดงว่าบัญชี HTTP ถูกกำหนดค่าแล้ว แต่ runtime ปัจจุบันไม่สามารถ
|
||||
resolve signing secret ที่รองรับด้วย SecretRef ได้
|
||||
ของบัญชี แสดงว่าบัญชี HTTP ถูกกำหนดค่าไว้ แต่ runtime ปัจจุบันไม่สามารถ
|
||||
แก้ไข signing secret ที่รองรับด้วย SecretRef ได้
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Native/slash commands not firing">
|
||||
ตรวจสอบว่าคุณตั้งใจใช้:
|
||||
<Accordion title="คำสั่ง native/slash ไม่ทำงาน">
|
||||
ตรวจสอบว่าคุณตั้งใจใช้แบบใด:
|
||||
|
||||
- โหมดคำสั่ง native (`channels.slack.commands.native: true`) พร้อมคำสั่ง slash ที่ตรงกันซึ่งลงทะเบียนใน Slack
|
||||
- หรือโหมดคำสั่ง slash เดี่ยว (`channels.slack.slashCommand.enabled: true`)
|
||||
- หรือโหมดคำสั่ง slash เดียว (`channels.slack.slashCommand.enabled: true`)
|
||||
|
||||
ตรวจสอบ `commands.useAccessGroups` และ allowlist ของ channel/user ด้วย
|
||||
ตรวจสอบ `commands.useAccessGroups` และ allowlist ของช่องทาง/ผู้ใช้ด้วย
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## ข้อมูลอ้างอิง vision สำหรับไฟล์แนบ
|
||||
## ข้อมูลอ้างอิง vision ของไฟล์แนบ
|
||||
|
||||
Slack สามารถแนบสื่อที่ดาวน์โหลดแล้วเข้ากับ turn ของ agent เมื่อการดาวน์โหลดไฟล์ Slack สำเร็จและขีดจำกัดขนาดอนุญาต ไฟล์รูปภาพสามารถส่งผ่านเส้นทางการเข้าใจสื่อ หรือส่งตรงไปยังโมเดลตอบกลับที่รองรับ vision ได้ ส่วนไฟล์อื่นจะถูกเก็บเป็นบริบทไฟล์ที่ดาวน์โหลดได้ แทนที่จะถูกปฏิบัติเป็น input รูปภาพ
|
||||
Slack สามารถแนบสื่อที่ดาวน์โหลดแล้วเข้ากับรอบของเอเจนต์ได้เมื่อการดาวน์โหลดไฟล์ Slack สำเร็จและข้อจำกัดขนาดอนุญาต ไฟล์ภาพสามารถส่งผ่านเส้นทางการทำความเข้าใจสื่อหรือส่งตรงไปยังโมเดลตอบกลับที่รองรับ vision ได้ ส่วนไฟล์อื่นจะถูกเก็บไว้เป็นบริบทไฟล์ที่ดาวน์โหลดได้ แทนที่จะถูกปฏิบัติเป็นอินพุตรูปภาพ
|
||||
|
||||
### ประเภทสื่อที่รองรับ
|
||||
|
||||
| ประเภทสื่อ | แหล่งที่มา | พฤติกรรมปัจจุบัน | หมายเหตุ |
|
||||
| ประเภทสื่อ | แหล่งที่มา | ลักษณะการทำงานปัจจุบัน | หมายเหตุ |
|
||||
| ------------------------------ | -------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
|
||||
| รูปภาพ JPEG / PNG / GIF / WebP | URL ไฟล์ Slack | ดาวน์โหลดและแนบเข้ากับรอบสนทนาเพื่อให้จัดการด้วยความสามารถด้านวิชันได้ | ขีดจำกัดต่อไฟล์: `channels.slack.mediaMaxMb` (ค่าเริ่มต้น 20 MB) |
|
||||
| ไฟล์ PDF | URL ไฟล์ Slack | ดาวน์โหลดและเปิดเผยเป็นบริบทไฟล์สำหรับเครื่องมือ เช่น `download-file` หรือ `pdf` | ขาเข้า Slack ไม่แปลง PDF เป็นอินพุตภาพสำหรับวิชันโดยอัตโนมัติ |
|
||||
| ไฟล์อื่น ๆ | URL ไฟล์ Slack | ดาวน์โหลดเมื่อเป็นไปได้และเปิดเผยเป็นบริบทไฟล์ | ไฟล์ไบนารีจะไม่ถูกถือเป็นอินพุตรูปภาพ |
|
||||
| การตอบกลับในเธรด | ไฟล์ของข้อความเริ่มเธรด | ไฟล์จากข้อความรากสามารถเติมเป็นบริบทได้เมื่อการตอบกลับไม่มีสื่อโดยตรง | ข้อความเริ่มที่มีเฉพาะไฟล์ใช้ตัวยึดตำแหน่งไฟล์แนบ |
|
||||
| รูปภาพ JPEG / PNG / GIF / WebP | URL ไฟล์ Slack | ดาวน์โหลดและแนบเข้ากับเทิร์นเพื่อการจัดการที่รองรับการมองเห็น | ขีดจำกัดต่อไฟล์: `channels.slack.mediaMaxMb` (ค่าเริ่มต้น 20 MB) |
|
||||
| ไฟล์ PDF | URL ไฟล์ Slack | ดาวน์โหลดและแสดงเป็นบริบทไฟล์สำหรับเครื่องมือ เช่น `download-file` หรือ `pdf` | ขาเข้าของ Slack ไม่แปลง PDF เป็นอินพุตการมองเห็นภาพโดยอัตโนมัติ |
|
||||
| ไฟล์อื่น | URL ไฟล์ Slack | ดาวน์โหลดเมื่อเป็นไปได้และแสดงเป็นบริบทไฟล์ | ไฟล์ไบนารีจะไม่ถูกปฏิบัติเป็นอินพุตรูปภาพ |
|
||||
| การตอบกลับในเธรด | ไฟล์ของข้อความเริ่มเธรด | ไฟล์ของข้อความรากสามารถถูกเติมเป็นบริบทได้เมื่อการตอบกลับไม่มีสื่อโดยตรง | ข้อความเริ่มต้นที่มีเฉพาะไฟล์ใช้ตัวยึดตำแหน่งไฟล์แนบ |
|
||||
| ข้อความหลายรูปภาพ | ไฟล์ Slack หลายไฟล์ | แต่ละไฟล์จะถูกประเมินแยกกัน | การประมวลผล Slack จำกัดไว้ที่แปดไฟล์ต่อข้อความ |
|
||||
|
||||
### ไปป์ไลน์ขาเข้า
|
||||
|
||||
เมื่อมีข้อความ Slack พร้อมไฟล์แนบเข้ามา:
|
||||
เมื่อข้อความ Slack ที่มีไฟล์แนบมาถึง:
|
||||
|
||||
1. OpenClaw ดาวน์โหลดไฟล์จาก URL ส่วนตัวของ Slack โดยใช้โทเค็นบอต (`xoxb-...`)
|
||||
2. เมื่อสำเร็จ ไฟล์จะถูกเขียนลงในที่เก็บสื่อ
|
||||
3. พาธสื่อที่ดาวน์โหลดและประเภทเนื้อหาจะถูกเพิ่มลงในบริบทขาเข้า
|
||||
4. พาธของโมเดล/เครื่องมือที่รองรับรูปภาพสามารถใช้ไฟล์แนบรูปภาพจากบริบทนั้นได้
|
||||
5. ไฟล์ที่ไม่ใช่รูปภาพยังคงพร้อมใช้งานเป็นเมตาดาต้าไฟล์หรือการอ้างอิงสื่อสำหรับเครื่องมือที่จัดการไฟล์เหล่านั้นได้
|
||||
2. ไฟล์จะถูกเขียนลงในที่จัดเก็บสื่อเมื่อสำเร็จ
|
||||
3. เส้นทางสื่อที่ดาวน์โหลดแล้วและชนิดเนื้อหาจะถูกเพิ่มลงในบริบทขาเข้า
|
||||
4. เส้นทางโมเดล/เครื่องมือที่รองรับรูปภาพสามารถใช้ไฟล์แนบรูปภาพจากบริบทนั้นได้
|
||||
5. ไฟล์ที่ไม่ใช่รูปภาพยังคงพร้อมใช้งานเป็นเมตาดาต้าไฟล์หรือข้อมูลอ้างอิงสื่อสำหรับเครื่องมือที่จัดการได้
|
||||
|
||||
### การสืบทอดไฟล์แนบจากรากเธรด
|
||||
### การสืบทอดไฟล์แนบจากรากของเธรด
|
||||
|
||||
เมื่อมีข้อความเข้ามาในเธรด (มีพาเรนต์ `thread_ts`):
|
||||
เมื่อข้อความมาถึงในเธรด (มีพาเรนต์ `thread_ts`):
|
||||
|
||||
- หากตัวการตอบกลับเองไม่มีสื่อโดยตรง และข้อความรากที่รวมมามีไฟล์ Slack สามารถเติมไฟล์รากเป็นบริบทข้อความเริ่มเธรดได้
|
||||
- หากการตอบกลับเองไม่มีสื่อโดยตรง และข้อความรากที่รวมมามีไฟล์ Slack สามารถเติมไฟล์รากเป็นบริบทเริ่มต้นของเธรดได้
|
||||
- ไฟล์แนบของการตอบกลับโดยตรงมีลำดับความสำคัญเหนือไฟล์แนบของข้อความราก
|
||||
- ข้อความรากที่มีเฉพาะไฟล์และไม่มีข้อความจะแสดงด้วยตัวยึดตำแหน่งไฟล์แนบ เพื่อให้กลไกสำรองยังสามารถรวมไฟล์ของข้อความนั้นได้
|
||||
- ข้อความรากที่มีเฉพาะไฟล์และไม่มีข้อความจะแสดงด้วยตัวยึดตำแหน่งไฟล์แนบ เพื่อให้ตัวสำรองยังคงรวมไฟล์ของข้อความนั้นได้
|
||||
|
||||
### การจัดการไฟล์แนบหลายรายการ
|
||||
|
||||
เมื่อข้อความ Slack เดียวมีไฟล์แนบหลายรายการ:
|
||||
|
||||
- ไฟล์แนบแต่ละรายการจะถูกประมวลผลแยกกันผ่านไปป์ไลน์สื่อ
|
||||
- การอ้างอิงสื่อที่ดาวน์โหลดจะถูกรวมไว้ในบริบทข้อความ
|
||||
- ข้อมูลอ้างอิงสื่อที่ดาวน์โหลดแล้วจะถูกรวบรวมลงในบริบทข้อความ
|
||||
- ลำดับการประมวลผลเป็นไปตามลำดับไฟล์ของ Slack ในเพย์โหลดเหตุการณ์
|
||||
- ความล้มเหลวในการดาวน์โหลดไฟล์แนบหนึ่งรายการจะไม่บล็อกรายการอื่น
|
||||
- ความล้มเหลวในการดาวน์โหลดไฟล์แนบหนึ่งรายการไม่บล็อกรายการอื่น
|
||||
|
||||
### ขีดจำกัดขนาด การดาวน์โหลด และโมเดล
|
||||
### ขนาด การดาวน์โหลด และขีดจำกัดของโมเดล
|
||||
|
||||
- **ขีดจำกัดขนาด**: ค่าเริ่มต้น 20 MB ต่อไฟล์ กำหนดค่าได้ผ่าน `channels.slack.mediaMaxMb`
|
||||
- **ความล้มเหลวในการดาวน์โหลด**: ไฟล์ที่ Slack ให้บริการไม่ได้, URL หมดอายุ, ไฟล์ที่เข้าถึงไม่ได้, ไฟล์เกินขนาด และการตอบกลับ HTML สำหรับการตรวจสอบสิทธิ์/เข้าสู่ระบบของ Slack จะถูกข้ามแทนที่จะถูกรายงานว่าเป็นรูปแบบที่ไม่รองรับ
|
||||
- **โมเดลวิชัน**: การวิเคราะห์รูปภาพใช้โมเดลตอบกลับที่ใช้งานอยู่เมื่อรองรับวิชัน หรือใช้โมเดลรูปภาพที่กำหนดค่าไว้ที่ `agents.defaults.imageModel`
|
||||
- **ความล้มเหลวในการดาวน์โหลด**: ไฟล์ที่ Slack ให้บริการไม่ได้, URL หมดอายุ, ไฟล์ที่เข้าถึงไม่ได้, ไฟล์เกินขนาด และการตอบกลับ HTML สำหรับการยืนยันตัวตน/เข้าสู่ระบบ Slack จะถูกข้ามแทนที่จะถูกรายงานว่าเป็นรูปแบบที่ไม่รองรับ
|
||||
- **โมเดลการมองเห็น**: การวิเคราะห์รูปภาพใช้โมเดลตอบกลับที่ใช้งานอยู่เมื่อโมเดลนั้นรองรับการมองเห็น หรือใช้โมเดลรูปภาพที่กำหนดค่าไว้ที่ `agents.defaults.imageModel`
|
||||
|
||||
### ขีดจำกัดที่ทราบ
|
||||
|
||||
| สถานการณ์ | พฤติกรรมปัจจุบัน | วิธีแก้ไขชั่วคราว |
|
||||
| สถานการณ์ | ลักษณะการทำงานปัจจุบัน | วิธีแก้ไข |
|
||||
| -------------------------------------- | ---------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
|
||||
| URL ไฟล์ Slack หมดอายุ | ข้ามไฟล์; ไม่แสดงข้อผิดพลาด | อัปโหลดไฟล์ใหม่ใน Slack |
|
||||
| ไม่ได้กำหนดค่าโมเดลวิชัน | ไฟล์แนบรูปภาพถูกจัดเก็บเป็นการอ้างอิงสื่อ แต่ไม่ถูกวิเคราะห์เป็นรูปภาพ | กำหนดค่า `agents.defaults.imageModel` หรือใช้โมเดลตอบกลับที่รองรับวิชัน |
|
||||
| URL ไฟล์ Slack หมดอายุ | ข้ามไฟล์; ไม่แสดงข้อผิดพลาด | อัปโหลดไฟล์ใน Slack อีกครั้ง |
|
||||
| ยังไม่ได้กำหนดค่าโมเดลการมองเห็น | ไฟล์แนบรูปภาพจะถูกจัดเก็บเป็นข้อมูลอ้างอิงสื่อ แต่ไม่ได้วิเคราะห์เป็นรูปภาพ | กำหนดค่า `agents.defaults.imageModel` หรือใช้โมเดลตอบกลับที่รองรับการมองเห็น |
|
||||
| รูปภาพขนาดใหญ่มาก (> 20 MB โดยค่าเริ่มต้น) | ข้ามตามขีดจำกัดขนาด | เพิ่ม `channels.slack.mediaMaxMb` หาก Slack อนุญาต |
|
||||
| ไฟล์แนบที่ส่งต่อ/แชร์ | ข้อความและสื่อรูปภาพ/ไฟล์ที่โฮสต์บน Slack เป็นแบบพยายามให้ดีที่สุด | แชร์ใหม่โดยตรงในเธรด OpenClaw |
|
||||
| ไฟล์แนบ PDF | จัดเก็บเป็นบริบทไฟล์/สื่อ ไม่ได้ถูกส่งผ่านวิชันรูปภาพโดยอัตโนมัติ | ใช้ `download-file` สำหรับเมตาดาต้าไฟล์ หรือเครื่องมือ `pdf` สำหรับการวิเคราะห์ PDF |
|
||||
| ไฟล์แนบ PDF | จัดเก็บเป็นบริบทไฟล์/สื่อ ไม่ได้ส่งผ่านการมองเห็นรูปภาพโดยอัตโนมัติ | ใช้ `download-file` สำหรับเมตาดาต้าไฟล์ หรือเครื่องมือ `pdf` สำหรับการวิเคราะห์ PDF |
|
||||
|
||||
### เอกสารที่เกี่ยวข้อง
|
||||
|
||||
- [ไปป์ไลน์การทำความเข้าใจสื่อ](/th/nodes/media-understanding)
|
||||
- [ไปป์ไลน์การเข้าใจสื่อ](/th/nodes/media-understanding)
|
||||
- [เครื่องมือ PDF](/th/tools/pdf)
|
||||
- มหากาพย์: [#51349](https://github.com/openclaw/openclaw/issues/51349) — การเปิดใช้วิชันสำหรับไฟล์แนบ Slack
|
||||
- มหากาพย์: [#51349](https://github.com/openclaw/openclaw/issues/51349) — การเปิดใช้การมองเห็นไฟล์แนบ Slack
|
||||
- การทดสอบรีเกรสชัน: [#51353](https://github.com/openclaw/openclaw/issues/51353)
|
||||
- การยืนยันแบบสด: [#51354](https://github.com/openclaw/openclaw/issues/51354)
|
||||
- การตรวจสอบแบบสด: [#51354](https://github.com/openclaw/openclaw/issues/51354)
|
||||
|
||||
## ที่เกี่ยวข้อง
|
||||
|
||||
@ -1063,16 +1082,16 @@ Slack สามารถแนบสื่อที่ดาวน์โหล
|
||||
จับคู่ผู้ใช้ Slack กับ Gateway
|
||||
</Card>
|
||||
<Card title="Groups" icon="users" href="/th/channels/groups">
|
||||
พฤติกรรมช่องและ DM กลุ่ม
|
||||
พฤติกรรมของช่องและ DM กลุ่ม
|
||||
</Card>
|
||||
<Card title="Channel routing" icon="route" href="/th/channels/channel-routing">
|
||||
กำหนดเส้นทางข้อความขาเข้าไปยังเอเจนต์
|
||||
</Card>
|
||||
<Card title="Security" icon="shield" href="/th/gateway/security">
|
||||
โมเดลภัยคุกคามและการเสริมความปลอดภัย
|
||||
โมเดลภัยคุกคามและการเสริมความแข็งแกร่ง
|
||||
</Card>
|
||||
<Card title="Configuration" icon="sliders" href="/th/gateway/configuration">
|
||||
เค้าโครงการกำหนดค่าและลำดับความสำคัญ
|
||||
โครงร่างการกำหนดค่าและลำดับความสำคัญ
|
||||
</Card>
|
||||
<Card title="Slash commands" icon="terminal" href="/th/tools/slash-commands">
|
||||
แคตตาล็อกคำสั่งและพฤติกรรม
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
503
docs/th/ci.md
503
docs/th/ci.md
File diff suppressed because one or more lines are too long
@ -3,13 +3,13 @@ read_when:
|
||||
- คุณต้องการติดตั้งหรือจัดการ Plugin ของ Gateway หรือบันเดิลที่เข้ากันได้
|
||||
- คุณต้องการดีบักความล้มเหลวในการโหลด Plugin
|
||||
sidebarTitle: Plugins
|
||||
summary: ข้อมูลอ้างอิง CLI สำหรับ `openclaw plugins` (list, install, marketplace, uninstall, enable/disable, doctor)
|
||||
summary: คู่มืออ้างอิง CLI สำหรับ `openclaw plugins` (list, install, marketplace, uninstall, enable/disable, doctor)
|
||||
title: Plugin
|
||||
x-i18n:
|
||||
generated_at: "2026-05-03T21:28:41Z"
|
||||
generated_at: "2026-05-04T07:03:04Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: d854d052b0a012a86f9c775775676a9a8fe8ae86b2c38a18118f1abf0732174c
|
||||
source_hash: 36ae7edb12986ead7e126f25e0761bf312b2644b35017181b674082105886776
|
||||
source_path: cli/plugins.md
|
||||
workflow: 16
|
||||
---
|
||||
@ -18,19 +18,19 @@ x-i18n:
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="ระบบ Plugin" href="/th/tools/plugin">
|
||||
คู่มือสำหรับผู้ใช้ปลายทางในการติดตั้ง เปิดใช้งาน และแก้ปัญหา plugins
|
||||
คู่มือสำหรับผู้ใช้ปลายทางในการติดตั้ง เปิดใช้งาน และแก้ไขปัญหา plugins
|
||||
</Card>
|
||||
<Card title="จัดการ plugins" href="/th/plugins/manage-plugins">
|
||||
ตัวอย่างสั้น ๆ สำหรับติดตั้ง แสดงรายการ อัปเดต ถอนการติดตั้ง และเผยแพร่
|
||||
ตัวอย่างรวดเร็วสำหรับการติดตั้ง แสดงรายการ อัปเดต ถอนการติดตั้ง และเผยแพร่
|
||||
</Card>
|
||||
<Card title="Plugin bundles" href="/th/plugins/bundles">
|
||||
โมเดลความเข้ากันได้ของ bundle
|
||||
โมเดลความเข้ากันได้ของ Bundle
|
||||
</Card>
|
||||
<Card title="Plugin manifest" href="/th/plugins/manifest">
|
||||
ฟิลด์ manifest และสคีมา config
|
||||
ฟิลด์ Manifest และสคีมา config
|
||||
</Card>
|
||||
<Card title="ความปลอดภัย" href="/th/gateway/security">
|
||||
การเสริมความปลอดภัยสำหรับการติดตั้ง plugin
|
||||
การเพิ่มความแข็งแกร่งด้านความปลอดภัยสำหรับการติดตั้ง plugin
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@ -62,14 +62,16 @@ openclaw plugins marketplace list <marketplace>
|
||||
openclaw plugins marketplace list <marketplace> --json
|
||||
```
|
||||
|
||||
สำหรับการตรวจสอบการติดตั้ง การ inspect การถอนการติดตั้ง หรือการ refresh registry ที่ช้า ให้รันคำสั่งพร้อม `OPENCLAW_PLUGIN_LIFECYCLE_TRACE=1` trace จะเขียนเวลาของแต่ละเฟสไปยัง stderr และยังทำให้เอาต์พุต JSON parse ได้ ดู [การดีบัก](/th/help/debugging#plugin-lifecycle-trace)
|
||||
สำหรับการตรวจสอบการติดตั้ง การตรวจสอบ การถอนการติดตั้ง หรือการรีเฟรช registry ที่ช้า ให้รัน
|
||||
คำสั่งพร้อม `OPENCLAW_PLUGIN_LIFECYCLE_TRACE=1` trace จะเขียนเวลาของแต่ละเฟส
|
||||
ไปยัง stderr และยังคงทำให้เอาต์พุต JSON แยกวิเคราะห์ได้ ดู [การดีบัก](/th/help/debugging#plugin-lifecycle-trace)
|
||||
|
||||
<Note>
|
||||
plugins ที่ bundled มาพร้อมกับ OpenClaw บางรายการเปิดใช้งานตามค่าเริ่มต้น (เช่น bundled model providers, bundled speech providers และ bundled browser plugin); รายการอื่นต้องใช้ `plugins enable`
|
||||
plugins ที่รวมมาด้วยจะจัดส่งพร้อม OpenClaw บางตัวเปิดใช้งานตามค่าเริ่มต้น (เช่น provider โมเดลที่รวมมาด้วย, provider คำพูดที่รวมมาด้วย และ browser plugin ที่รวมมาด้วย); ตัวอื่นต้องใช้ `plugins enable`
|
||||
|
||||
plugins แบบเนทีฟของ OpenClaw ต้องมาพร้อม `openclaw.plugin.json` ที่มี JSON Schema แบบ inline (`configSchema` แม้จะว่างก็ตาม) bundles ที่เข้ากันได้จะใช้ bundle manifests ของตนเองแทน
|
||||
plugins แบบเนทีฟของ OpenClaw ต้องจัดส่ง `openclaw.plugin.json` พร้อม JSON Schema แบบอินไลน์ (`configSchema` แม้จะว่างก็ตาม) bundles ที่เข้ากันได้ใช้ manifest ของ bundle ของตัวเองแทน
|
||||
|
||||
`plugins list` แสดง `Format: openclaw` หรือ `Format: bundle` เอาต์พุต list/info แบบ verbose ยังแสดง subtype ของ bundle (`codex`, `claude` หรือ `cursor`) พร้อม capabilities ของ bundle ที่ตรวจพบ
|
||||
`plugins list` แสดง `Format: openclaw` หรือ `Format: bundle` เอาต์พุต list/info แบบละเอียดจะแสดง subtype ของ bundle ด้วย (`codex`, `claude` หรือ `cursor`) พร้อมความสามารถของ bundle ที่ตรวจพบ
|
||||
</Note>
|
||||
|
||||
### ติดตั้ง
|
||||
@ -91,100 +93,108 @@ openclaw plugins install <plugin> --marketplace https://github.com/<owner>/<repo
|
||||
```
|
||||
|
||||
<Warning>
|
||||
ชื่อแพ็กเกจแบบ bare จะติดตั้งจาก npm ตามค่าเริ่มต้นระหว่างช่วง launch cutover ใช้ `clawhub:<package>` สำหรับ ClawHub ปฏิบัติกับการติดตั้ง plugin เหมือนการรันโค้ด ควรใช้เวอร์ชันที่ pin ไว้
|
||||
ชื่อ package แบบเปล่าจะติดตั้งจาก npm ตามค่าเริ่มต้นระหว่างช่วงเปลี่ยนผ่านการเปิดตัว ใช้ `clawhub:<package>` สำหรับ ClawHub ให้ปฏิบัติกับการติดตั้ง plugin เหมือนการรันโค้ด ควรใช้เวอร์ชันที่ pin ไว้
|
||||
</Warning>
|
||||
|
||||
`plugins search` query ClawHub เพื่อค้นหาแพ็กเกจ plugin ที่ติดตั้งได้ และพิมพ์ชื่อแพ็กเกจที่พร้อมติดตั้ง โดยค้นหาแพ็กเกจ code-plugin และ bundle-plugin ไม่ใช่ skills ใช้ `openclaw skills search` สำหรับ ClawHub skills
|
||||
`plugins search` ค้นหา ClawHub สำหรับ package plugin ที่ติดตั้งได้ และพิมพ์
|
||||
ชื่อ package ที่พร้อมติดตั้ง โดยค้นหา package แบบ code-plugin และ bundle-plugin
|
||||
ไม่ใช่ skills ใช้ `openclaw skills search` สำหรับ ClawHub skills
|
||||
|
||||
<Note>
|
||||
ClawHub เป็นช่องทางหลักสำหรับการแจกจ่ายและค้นพบ plugins ส่วนใหญ่ Npm ยังคงเป็น fallback ที่รองรับและเป็นเส้นทาง direct-install แพ็กเกจ plugin `@openclaw/*` ที่ OpenClaw เป็นเจ้าของกลับมาเผยแพร่บน npm อีกครั้งแล้ว ดูรายการปัจจุบันได้ที่ [npmjs.com/org/openclaw](https://www.npmjs.com/org/openclaw) หรือ [plugin inventory](/th/plugins/plugin-inventory) การติดตั้ง stable ใช้ `latest` การติดตั้งและอัปเดตใน beta-channel จะใช้ npm `beta` dist-tag ก่อนเมื่อ tag นั้นมีอยู่ จากนั้นจึง fallback เป็น `latest`
|
||||
ClawHub เป็นพื้นผิวหลักสำหรับการจัดจำหน่ายและการค้นพบของ plugins ส่วนใหญ่ Npm
|
||||
ยังคงเป็น fallback ที่รองรับและเป็นเส้นทางการติดตั้งโดยตรง package plugin ที่ OpenClaw เป็นเจ้าของ
|
||||
`@openclaw/*` ถูกเผยแพร่บน npm อีกครั้ง ดูรายการปัจจุบัน
|
||||
ที่ [npmjs.com/org/openclaw](https://www.npmjs.com/org/openclaw) หรือ
|
||||
[คลัง plugin](/th/plugins/plugin-inventory) การติดตั้งแบบเสถียรใช้ `latest`
|
||||
การติดตั้งและอัปเดตในช่อง beta จะเลือกใช้ npm `beta` dist-tag เมื่อ tag นั้น
|
||||
พร้อมใช้งาน แล้วจึง fallback ไปที่ `latest`
|
||||
</Note>
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Config includes และการซ่อมแซม invalid-config">
|
||||
หากส่วน `plugins` ของคุณอิงกับ `$include` แบบไฟล์เดียว `plugins install/update/enable/disable/uninstall` จะเขียนผ่านไปยังไฟล์ included นั้นและปล่อย `openclaw.json` ไว้ไม่แตะต้อง Root includes, include arrays และ includes ที่มี sibling overrides จะ fail closed แทนที่จะ flatten ดู [Config includes](/th/gateway/configuration) สำหรับรูปแบบที่รองรับ
|
||||
<Accordion title="Config includes และการซ่อมแซม config ที่ไม่ถูกต้อง">
|
||||
หากส่วน `plugins` ของคุณรองรับด้วย `$include` แบบไฟล์เดียว `plugins install/update/enable/disable/uninstall` จะเขียนผ่านไปยังไฟล์ที่ include นั้น และปล่อย `openclaw.json` ไว้ไม่เปลี่ยนแปลง Root includes, include arrays และ includes ที่มี sibling overrides จะ fail closed แทนการ flatten ดู [Config includes](/th/gateway/configuration) สำหรับรูปแบบที่รองรับ
|
||||
|
||||
หาก config ไม่ถูกต้องระหว่างติดตั้ง โดยปกติ `plugins install` จะ fail closed และบอกให้คุณรัน `openclaw doctor --fix` ก่อน ระหว่าง Gateway startup และ hot reload config ของ plugin ที่ไม่ถูกต้องจะ fail closed เหมือน config ที่ไม่ถูกต้องอื่น ๆ; `openclaw doctor --fix` สามารถ quarantine entry ของ plugin ที่ไม่ถูกต้องได้ ข้อยกเว้น install-time ที่มีเอกสารกำกับไว้เพียงอย่างเดียวคือเส้นทาง recovery แบบแคบสำหรับ bundled-plugin สำหรับ plugins ที่ opt in เข้า `openclaw.install.allowInvalidConfigRecovery` อย่างชัดเจน
|
||||
หาก config ไม่ถูกต้องระหว่างการติดตั้ง โดยปกติ `plugins install` จะ fail closed และบอกให้คุณรัน `openclaw doctor --fix` ก่อน ระหว่างการเริ่มต้น Gateway และ hot reload config plugin ที่ไม่ถูกต้องจะ fail closed เหมือน config ที่ไม่ถูกต้องอื่น ๆ; `openclaw doctor --fix` สามารถ quarantine รายการ plugin ที่ไม่ถูกต้องได้ ข้อยกเว้นที่มีเอกสารระบุไว้สำหรับ install-time มีเพียงเส้นทางกู้คืน bundled-plugin แบบแคบสำหรับ plugins ที่ opt in อย่างชัดเจนไปยัง `openclaw.install.allowInvalidConfigRecovery`
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="--force และ reinstall เทียบกับ update">
|
||||
`--force` ใช้ target การติดตั้งเดิมซ้ำและเขียนทับ plugin หรือ hook pack ที่ติดตั้งไว้แล้วในที่เดิม ใช้เมื่อตั้งใจ reinstall id เดิมจาก local path, archive, แพ็กเกจ ClawHub หรือ artifact ของ npm ใหม่ สำหรับการอัปเกรด plugin npm ที่ติดตามอยู่แล้วตามปกติ ควรใช้ `openclaw plugins update <id-or-npm-spec>`
|
||||
<Accordion title="--force และการติดตั้งใหม่เทียบกับ update">
|
||||
`--force` ใช้เป้าหมายการติดตั้งเดิมซ้ำและเขียนทับ plugin หรือ hook pack ที่ติดตั้งแล้วในตำแหน่งเดิม ใช้เมื่อตั้งใจติดตั้ง id เดิมใหม่จาก path ในเครื่อง, archive, package ClawHub หรือ artifact npm ใหม่ สำหรับการอัปเกรดตามปกติของ npm plugin ที่ติดตามอยู่แล้ว ควรใช้ `openclaw plugins update <id-or-npm-spec>`
|
||||
|
||||
หากคุณรัน `plugins install` สำหรับ plugin id ที่ติดตั้งไว้แล้ว OpenClaw จะหยุดและชี้คุณไปที่ `plugins update <id-or-npm-spec>` สำหรับการอัปเกรดตามปกติ หรือไปที่ `plugins install <package> --force` เมื่อคุณต้องการเขียนทับการติดตั้งปัจจุบันจากแหล่งอื่นจริง ๆ
|
||||
หากคุณรัน `plugins install` สำหรับ id ของ plugin ที่ติดตั้งอยู่แล้ว OpenClaw จะหยุดและชี้ให้คุณใช้ `plugins update <id-or-npm-spec>` สำหรับการอัปเกรดปกติ หรือใช้ `plugins install <package> --force` เมื่อคุณต้องการเขียนทับการติดตั้งปัจจุบันจากแหล่งอื่นจริง ๆ
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="ขอบเขตของ --pin">
|
||||
`--pin` ใช้ได้กับการติดตั้ง npm เท่านั้น ไม่รองรับกับการติดตั้ง `git:`; ใช้ git ref แบบชัดเจน เช่น `git:github.com/acme/plugin@v1.2.3` เมื่อคุณต้องการแหล่งที่ pin ไว้ ไม่รองรับกับ `--marketplace` เพราะการติดตั้งจาก marketplace จะ persist metadata แหล่งที่มาของ marketplace แทน npm spec
|
||||
`--pin` ใช้กับการติดตั้ง npm เท่านั้น ไม่รองรับกับการติดตั้ง `git:`; ใช้ git ref ที่ชัดเจน เช่น `git:github.com/acme/plugin@v1.2.3` เมื่อคุณต้องการแหล่งที่ pin ไว้ ไม่รองรับกับ `--marketplace` เพราะการติดตั้ง marketplace จะเก็บ metadata แหล่งที่มาของ marketplace แทน npm spec
|
||||
</Accordion>
|
||||
<Accordion title="--dangerously-force-unsafe-install">
|
||||
`--dangerously-force-unsafe-install` เป็นตัวเลือก break-glass สำหรับ false positives ใน dangerous-code scanner ในตัว อนุญาตให้การติดตั้งดำเนินต่อได้แม้ scanner ในตัวจะรายงาน findings ระดับ `critical` แต่จะ **ไม่** bypass บล็อกจาก policy ของ hook `before_install` ของ plugin และจะ **ไม่** bypass scan failures
|
||||
`--dangerously-force-unsafe-install` เป็นตัวเลือก break-glass สำหรับ false positives ในตัวสแกนโค้ดอันตรายที่มีมาให้ ช่วยให้การติดตั้งดำเนินต่อได้แม้ตัวสแกนที่มีมาให้รายงาน findings ระดับ `critical` แต่จะ **ไม่** ข้าม policy blocks ของ hook `before_install` ของ plugin และ **ไม่** ข้าม scan failures
|
||||
|
||||
CLI flag นี้ใช้กับ flow การ install/update plugin การติดตั้ง skill dependencies ที่ Gateway รองรับใช้ request override ที่ตรงกันคือ `dangerouslyForceUnsafeInstall` ส่วน `openclaw skills install` ยังคงเป็น flow download/install skill ของ ClawHub ที่แยกต่างหาก
|
||||
flag CLI นี้ใช้กับ flow การติดตั้ง/อัปเดต plugin การติดตั้ง dependency ของ skill ที่รองรับโดย Gateway ใช้ request override ที่ตรงกันคือ `dangerouslyForceUnsafeInstall` ขณะที่ `openclaw skills install` ยังคงเป็น flow ดาวน์โหลด/ติดตั้ง ClawHub skill แยกต่างหาก
|
||||
|
||||
หาก plugin ที่คุณเผยแพร่บน ClawHub ถูกบล็อกโดย registry scan ให้ใช้ขั้นตอนสำหรับผู้เผยแพร่ใน [ClawHub](/th/tools/clawhub)
|
||||
หาก plugin ที่คุณเผยแพร่บน ClawHub ถูกบล็อกโดยการสแกน registry ให้ใช้ขั้นตอนของผู้เผยแพร่ใน [ClawHub](/th/tools/clawhub)
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Hook packs และ npm specs">
|
||||
`plugins install` ยังเป็นพื้นผิวการติดตั้งสำหรับ hook packs ที่ expose `openclaw.hooks` ใน `package.json` ใช้ `openclaw hooks` สำหรับการมองเห็น hook แบบ filtered และการเปิดใช้งานราย hook ไม่ใช่การติดตั้งแพ็กเกจ
|
||||
`plugins install` ยังเป็นพื้นผิวการติดตั้งสำหรับ hook packs ที่เปิดเผย `openclaw.hooks` ใน `package.json` ด้วย ใช้ `openclaw hooks` สำหรับการมองเห็น hook แบบกรองและการเปิดใช้งานราย hook ไม่ใช่การติดตั้ง package
|
||||
|
||||
Npm specs เป็น **registry-only** (ชื่อแพ็กเกจ + **exact version** หรือ **dist-tag** ที่เป็นตัวเลือก) Git/URL/file specs และ semver ranges จะถูกปฏิเสธ การติดตั้ง dependencies จะรันแบบ project-local พร้อม `--ignore-scripts` เพื่อความปลอดภัย แม้ shell ของคุณจะมี global npm install settings ก็ตาม
|
||||
Npm specs เป็นแบบ **registry-only** (ชื่อ package + **เวอร์ชันแบบ exact** หรือ **dist-tag** ที่เป็นทางเลือก) Git/URL/file specs และช่วง semver จะถูกปฏิเสธ การติดตั้ง dependency รันแบบ project-local พร้อม `--ignore-scripts` เพื่อความปลอดภัย แม้ shell ของคุณจะมีการตั้งค่า global npm install ก็ตาม
|
||||
|
||||
ใช้ `npm:<package>` เมื่อคุณต้องการระบุ npm resolution ให้ชัดเจน Bare package specs จะติดตั้งโดยตรงจาก npm ระหว่าง launch cutover เช่นกัน
|
||||
ใช้ `npm:<package>` เมื่อคุณต้องการทำให้การ resolve ของ npm ชัดเจน Bare package specs จะติดตั้งโดยตรงจาก npm เช่นกันระหว่างช่วงเปลี่ยนผ่านการเปิดตัว
|
||||
|
||||
Bare specs และ `@latest` จะอยู่บน stable track หาก npm resolve สิ่งใดสิ่งหนึ่งเป็น prerelease OpenClaw จะหยุดและขอให้คุณ opt in อย่างชัดเจนด้วย prerelease tag เช่น `@beta`/`@rc` หรือ exact prerelease version เช่น `@1.2.3-beta.4`
|
||||
Bare specs และ `@latest` จะอยู่บน track เสถียร เวอร์ชัน correction แบบประทับวันที่ของ OpenClaw เช่น `2026.5.3-1` เป็น stable releases สำหรับการตรวจสอบนี้ หาก npm resolve สิ่งใดสิ่งหนึ่งไปเป็น prerelease OpenClaw จะหยุดและขอให้คุณ opt in อย่างชัดเจนด้วย tag prerelease เช่น `@beta`/`@rc` หรือเวอร์ชัน prerelease แบบ exact เช่น `@1.2.3-beta.4`
|
||||
|
||||
หาก bare install spec ตรงกับ official plugin id (เช่น `diffs`) OpenClaw จะติดตั้ง catalog entry โดยตรง หากต้องการติดตั้งแพ็กเกจ npm ที่มีชื่อเดียวกัน ให้ใช้ explicit scoped spec (เช่น `@scope/diffs`)
|
||||
หาก bare install spec ตรงกับ id ของ plugin อย่างเป็นทางการ (เช่น `diffs`) OpenClaw จะติดตั้งรายการ catalog โดยตรง หากต้องการติดตั้ง npm package ที่มีชื่อเดียวกัน ให้ใช้ scoped spec ที่ชัดเจน (เช่น `@scope/diffs`)
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Git repositories">
|
||||
ใช้ `git:<repo>` เพื่อติดตั้งโดยตรงจาก git repository รูปแบบที่รองรับได้แก่ `git:github.com/owner/repo`, `git:owner/repo`, clone URLs แบบ full `https://`, `ssh://`, `git://`, `file://` และ `git@host:owner/repo.git` เพิ่ม `@<ref>` หรือ `#<ref>` เพื่อ check out branch, tag หรือ commit ก่อนติดตั้ง
|
||||
ใช้ `git:<repo>` เพื่อติดตั้งโดยตรงจาก git repository รูปแบบที่รองรับได้แก่ `git:github.com/owner/repo`, `git:owner/repo`, clone URLs แบบเต็ม `https://`, `ssh://`, `git://`, `file://` และ `git@host:owner/repo.git` เพิ่ม `@<ref>` หรือ `#<ref>` เพื่อ checkout branch, tag หรือ commit ก่อนติดตั้ง
|
||||
|
||||
การติดตั้งผ่าน Git จะ clone ไปยังไดเรกทอรีชั่วคราว check out ref ที่ร้องขอเมื่อมีอยู่ จากนั้นใช้ตัวติดตั้งไดเรกทอรี plugin ตามปกติ นั่นหมายความว่า manifest validation, dangerous-code scanning, งานติดตั้งของ package-manager และ install records จะทำงานเหมือนการติดตั้ง npm การติดตั้ง git ที่บันทึกไว้จะรวม source URL/ref พร้อม resolved commit เพื่อให้ `openclaw plugins update` สามารถ re-resolve แหล่งที่มาภายหลังได้
|
||||
การติดตั้ง Git จะ clone ไปยัง directory ชั่วคราว checkout ref ที่ร้องขอเมื่อมี จากนั้นใช้ตัวติดตั้ง directory plugin ปกติ ซึ่งหมายความว่า manifest validation, การสแกนโค้ดอันตราย, งานติดตั้ง package-manager และบันทึกการติดตั้งจะทำงานเหมือนการติดตั้ง npm การติดตั้ง git ที่บันทึกไว้จะรวม URL/ref แหล่งที่มาและ commit ที่ resolve แล้ว เพื่อให้ `openclaw plugins update` สามารถ re-resolve แหล่งที่มาในภายหลังได้
|
||||
|
||||
หลังจากติดตั้งจาก git ให้ใช้ `openclaw plugins inspect <id> --runtime --json` เพื่อตรวจสอบ runtime registrations เช่น gateway methods และ CLI commands หาก plugin ลงทะเบียน CLI root ด้วย `api.registerCli` ให้รันคำสั่งนั้นโดยตรงผ่าน root CLI ของ OpenClaw เช่น `openclaw demo-plugin ping`
|
||||
หลังติดตั้งจาก git ให้ใช้ `openclaw plugins inspect <id> --runtime --json` เพื่อตรวจสอบ runtime registrations เช่น gateway methods และ CLI commands หาก plugin ลงทะเบียน CLI root ด้วย `api.registerCli` ให้ execute คำสั่งนั้นโดยตรงผ่าน root CLI ของ OpenClaw เช่น `openclaw demo-plugin ping`
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Archives">
|
||||
Archives ที่รองรับ: `.zip`, `.tgz`, `.tar.gz`, `.tar` Archives ของ plugin แบบเนทีฟของ OpenClaw ต้องมี `openclaw.plugin.json` ที่ถูกต้องที่ root ของ plugin ที่ extract แล้ว; archives ที่มีเพียง `package.json` จะถูกปฏิเสธก่อน OpenClaw เขียน install records
|
||||
archives ที่รองรับ: `.zip`, `.tgz`, `.tar.gz`, `.tar` archives ของ OpenClaw plugin แบบเนทีฟต้องมี `openclaw.plugin.json` ที่ถูกต้องที่ root ของ plugin หลังแตกไฟล์; archives ที่มีเฉพาะ `package.json` จะถูกปฏิเสธก่อนที่ OpenClaw จะเขียนบันทึกการติดตั้ง
|
||||
|
||||
รองรับการติดตั้งจาก Claude marketplace ด้วย
|
||||
รองรับการติดตั้ง Claude marketplace ด้วย
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
การติดตั้ง ClawHub ใช้ locator แบบชัดเจน `clawhub:<package>`:
|
||||
การติดตั้ง ClawHub ใช้ locator `clawhub:<package>` ที่ชัดเจน:
|
||||
|
||||
```bash
|
||||
openclaw plugins install clawhub:openclaw-codex-app-server
|
||||
openclaw plugins install clawhub:openclaw-codex-app-server@1.2.3
|
||||
```
|
||||
|
||||
Bare npm-safe plugin specs จะติดตั้งจาก npm ตามค่าเริ่มต้นระหว่าง launch cutover:
|
||||
Bare npm-safe plugin specs จะติดตั้งจาก npm ตามค่าเริ่มต้นระหว่างช่วงเปลี่ยนผ่านการเปิดตัว:
|
||||
|
||||
```bash
|
||||
openclaw plugins install openclaw-codex-app-server
|
||||
```
|
||||
|
||||
ใช้ `npm:` เพื่อระบุ npm-only resolution ให้ชัดเจน:
|
||||
ใช้ `npm:` เพื่อทำให้การ resolve แบบ npm-only ชัดเจน:
|
||||
|
||||
```bash
|
||||
openclaw plugins install npm:openclaw-codex-app-server
|
||||
openclaw plugins install npm:@scope/plugin-name@1.0.1
|
||||
```
|
||||
|
||||
OpenClaw ตรวจสอบ plugin API ที่ประกาศไว้ / ความเข้ากันได้ขั้นต่ำของ gateway ก่อนติดตั้ง เมื่อเวอร์ชัน ClawHub ที่เลือกเผยแพร่ ClawPack artifact, OpenClaw จะดาวน์โหลด `.tgz` แบบ npm-pack ที่มีเวอร์ชัน ตรวจสอบ ClawHub digest header และ artifact digest จากนั้นติดตั้งผ่านเส้นทาง archive ปกติ เวอร์ชัน ClawHub ที่เก่ากว่าและไม่มี ClawPack metadata ยังคงติดตั้งผ่านเส้นทาง legacy package archive verification การติดตั้งที่บันทึกไว้จะเก็บ ClawHub source metadata, artifact kind, npm integrity, npm shasum, tarball name และข้อเท็จจริง ClawPack digest สำหรับการอัปเดตภายหลัง
|
||||
การติดตั้ง ClawHub แบบไม่ระบุเวอร์ชันจะเก็บ recorded spec แบบไม่ระบุเวอร์ชันไว้ เพื่อให้ `openclaw plugins update` สามารถตามรุ่นใหม่ของ ClawHub ได้; selectors แบบระบุเวอร์ชันหรือ tag ชัดเจน เช่น `clawhub:pkg@1.2.3` และ `clawhub:pkg@beta` จะยังคง pin ไว้กับ selector นั้น
|
||||
OpenClaw ตรวจสอบ plugin API ที่ประกาศไว้ / ความเข้ากันได้ขั้นต่ำของ gateway ก่อนติดตั้ง เมื่อเวอร์ชัน ClawHub ที่เลือกเผยแพร่ ClawPack artifact OpenClaw จะดาวน์โหลด `.tgz` แบบ npm-pack ที่มีเวอร์ชัน ตรวจสอบ ClawHub digest header และ artifact digest จากนั้นติดตั้งผ่าน path archive ปกติ เวอร์ชัน ClawHub เก่าที่ไม่มี metadata ของ ClawPack ยังคงติดตั้งผ่าน path การตรวจสอบ package archive แบบ legacy การติดตั้งที่บันทึกไว้จะเก็บ metadata แหล่งที่มา ClawHub, ชนิด artifact, npm integrity, npm shasum, ชื่อ tarball และข้อเท็จจริง digest ของ ClawPack ไว้สำหรับการอัปเดตในภายหลัง
|
||||
การติดตั้ง ClawHub แบบไม่มีเวอร์ชันจะเก็บ recorded spec แบบไม่มีเวอร์ชัน เพื่อให้ `openclaw plugins update` สามารถติดตาม releases ใหม่กว่าของ ClawHub ได้; selectors แบบระบุเวอร์ชันหรือ tag อย่างชัดเจน เช่น `clawhub:pkg@1.2.3` และ `clawhub:pkg@beta` จะยังคง pin อยู่กับ selector นั้น
|
||||
|
||||
#### ชวเลข Marketplace
|
||||
#### รูปย่อของ Marketplace
|
||||
|
||||
ใช้ชวเลข `plugin@marketplace` เมื่อชื่อ marketplace มีอยู่ใน local registry cache ของ Claude ที่ `~/.claude/plugins/known_marketplaces.json`:
|
||||
ใช้รูปย่อ `plugin@marketplace` เมื่อชื่อ marketplace มีอยู่ใน local registry cache ของ Claude ที่ `~/.claude/plugins/known_marketplaces.json`:
|
||||
|
||||
```bash
|
||||
openclaw plugins marketplace list <marketplace-name>
|
||||
openclaw plugins install <plugin-name>@<marketplace-name>
|
||||
```
|
||||
|
||||
ใช้ `--marketplace` เมื่อคุณต้องการส่งแหล่งที่มาของ marketplace อย่างชัดเจน:
|
||||
ใช้ `--marketplace` เมื่อคุณต้องการส่ง marketplace source อย่างชัดเจน:
|
||||
|
||||
```bash
|
||||
openclaw plugins install <plugin-name> --marketplace <marketplace-name>
|
||||
@ -195,30 +205,30 @@ openclaw plugins install <plugin-name> --marketplace ./my-marketplace
|
||||
|
||||
<Tabs>
|
||||
<Tab title="แหล่งที่มาของ Marketplace">
|
||||
- ชื่อ Marketplace ที่ Claude รู้จักจาก `~/.claude/plugins/known_marketplaces.json`
|
||||
- รูท Marketplace ในเครื่องหรือพาธ `marketplace.json`
|
||||
- ชื่อย่อ repo GitHub เช่น `owner/repo`
|
||||
- URL repo GitHub เช่น `https://github.com/owner/repo`
|
||||
- ชื่อ marketplace ที่ Claude รู้จักจาก `~/.claude/plugins/known_marketplaces.json`
|
||||
- ราก marketplace ในเครื่องหรือพาธ `marketplace.json`
|
||||
- ชวเลข repo ของ GitHub เช่น `owner/repo`
|
||||
- URL repo ของ GitHub เช่น `https://github.com/owner/repo`
|
||||
- URL git
|
||||
|
||||
</Tab>
|
||||
<Tab title="กฎของ Marketplace ระยะไกล">
|
||||
สำหรับ Marketplace ระยะไกลที่โหลดจาก GitHub หรือ git รายการ Plugin ต้องอยู่ภายใน repo Marketplace ที่โคลนมา OpenClaw ยอมรับแหล่งที่มาแบบพาธสัมพัทธ์จาก repo นั้น และปฏิเสธแหล่งที่มา Plugin แบบ HTTP(S), พาธสัมบูรณ์, git, GitHub และแหล่งที่มาอื่นที่ไม่ใช่พาธจาก manifest ระยะไกล
|
||||
<Tab title="กฎของ marketplace ระยะไกล">
|
||||
สำหรับ marketplace ระยะไกลที่โหลดจาก GitHub หรือ git รายการ Plugin ต้องอยู่ภายใน repo marketplace ที่โคลนมา OpenClaw ยอมรับแหล่งที่มาแบบพาธสัมพัทธ์จาก repo นั้น และปฏิเสธแหล่งที่มา Plugin แบบ HTTP(S), พาธสัมบูรณ์, git, GitHub และแหล่งที่มา Plugin อื่นที่ไม่ใช่พาธจาก manifest ระยะไกล
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
สำหรับพาธและไฟล์เก็บถาวรในเครื่อง OpenClaw จะตรวจจับโดยอัตโนมัติ:
|
||||
สำหรับพาธในเครื่องและไฟล์ archive OpenClaw ตรวจจับอัตโนมัติ:
|
||||
|
||||
- Plugin ดั้งเดิมของ OpenClaw (`openclaw.plugin.json`)
|
||||
- Plugin แบบเนทีฟของ OpenClaw (`openclaw.plugin.json`)
|
||||
- บันเดิลที่เข้ากันได้กับ Codex (`.codex-plugin/plugin.json`)
|
||||
- บันเดิลที่เข้ากันได้กับ Claude (`.claude-plugin/plugin.json` หรือเลย์เอาต์คอมโพเนนต์ Claude เริ่มต้น)
|
||||
- บันเดิลที่เข้ากันได้กับ Cursor (`.cursor-plugin/plugin.json`)
|
||||
|
||||
<Note>
|
||||
บันเดิลที่เข้ากันได้จะติดตั้งลงในรูท Plugin ปกติ และเข้าร่วมในโฟลว์ list/info/enable/disable เดียวกัน ปัจจุบันรองรับ Skills ของบันเดิล, command-skills ของ Claude, ค่าเริ่มต้น `settings.json` ของ Claude, ค่าเริ่มต้น `.lsp.json` / `lspServers` ที่ประกาศใน manifest ของ Claude, command-skills ของ Cursor และไดเรกทอรี hook ของ Codex ที่เข้ากันได้ ส่วนความสามารถอื่นของบันเดิลที่ตรวจพบจะแสดงใน diagnostics/info แต่ยังไม่ได้เชื่อมต่อเข้ากับการทำงานของ runtime
|
||||
บันเดิลที่เข้ากันได้จะติดตั้งลงในราก Plugin ปกติ และเข้าร่วมในโฟลว์ list/info/enable/disable เดียวกัน ปัจจุบันรองรับ Skills ของบันเดิล, command-skills ของ Claude, ค่าเริ่มต้น `settings.json` ของ Claude, ค่าเริ่มต้น `.lsp.json` ของ Claude / `lspServers` ที่ประกาศใน manifest, command-skills ของ Cursor และไดเรกทอรี hook ของ Codex ที่เข้ากันได้ ส่วนความสามารถอื่นของบันเดิลที่ตรวจพบจะแสดงใน diagnostics/info แต่ยังไม่ได้เชื่อมเข้ากับการทำงานขณะรันไทม์
|
||||
</Note>
|
||||
|
||||
### รายการ
|
||||
### แสดงรายการ
|
||||
|
||||
```bash
|
||||
openclaw plugins list
|
||||
@ -231,31 +241,31 @@ openclaw plugins search <query> --json
|
||||
```
|
||||
|
||||
<ParamField path="--enabled" type="boolean">
|
||||
แสดงเฉพาะ Plugin ที่เปิดใช้งานแล้ว
|
||||
แสดงเฉพาะ Plugin ที่เปิดใช้งานอยู่
|
||||
</ParamField>
|
||||
<ParamField path="--verbose" type="boolean">
|
||||
เปลี่ยนจากมุมมองตารางเป็นบรรทัดรายละเอียดต่อ Plugin พร้อมเมทาดาทา source/origin/version/activation
|
||||
เปลี่ยนจากมุมมองตารางเป็นบรรทัดรายละเอียดต่อ Plugin พร้อม metadata ของ source/origin/version/activation
|
||||
</ParamField>
|
||||
<ParamField path="--json" type="boolean">
|
||||
รายการ inventory ที่เครื่องอ่านได้ พร้อม diagnostics ของ registry และสถานะการติดตั้ง dependency ของแพ็กเกจ
|
||||
inventory ที่เครื่องอ่านได้ พร้อม diagnostics ของ registry และสถานะการติดตั้ง dependency ของ package
|
||||
</ParamField>
|
||||
|
||||
<Note>
|
||||
`plugins list` อ่าน registry Plugin ในเครื่องที่คงอยู่ไว้ก่อน โดยมี fallback ที่สร้างจาก manifest เท่านั้นเมื่อ registry ขาดหายหรือไม่ถูกต้อง คำสั่งนี้มีประโยชน์สำหรับตรวจสอบว่า Plugin ติดตั้งแล้ว เปิดใช้งานแล้ว และมองเห็นได้ในการวางแผนเริ่มต้นแบบเย็นหรือไม่ แต่ไม่ใช่การ probe runtime แบบสดของกระบวนการ Gateway ที่กำลังทำงานอยู่ หลังจากเปลี่ยนโค้ด Plugin, enablement, hook policy หรือ `plugins.load.paths` ให้รีสตาร์ท Gateway ที่ให้บริการ channel ก่อนคาดหวังให้โค้ด `register(api)` หรือ hook ใหม่ทำงาน สำหรับการปรับใช้แบบระยะไกล/คอนเทนเนอร์ ให้ตรวจสอบว่าคุณกำลังรีสตาร์ท child `openclaw gateway run` ตัวจริง ไม่ใช่แค่กระบวนการ wrapper
|
||||
`plugins list` อ่าน registry ของ Plugin ในเครื่องที่ persisted ไว้ก่อน โดยมี fallback ที่ derive จาก manifest เท่านั้นเมื่อ registry หายไปหรือไม่ถูกต้อง คำสั่งนี้มีประโยชน์สำหรับตรวจว่า Plugin ติดตั้งแล้ว เปิดใช้งานอยู่ และมองเห็นได้ในการวางแผน startup แบบ cold หรือไม่ แต่ไม่ใช่ probe รันไทม์สดของโปรเซส Gateway ที่กำลังรันอยู่ หลังเปลี่ยนโค้ด Plugin, enablement, นโยบาย hook หรือ `plugins.load.paths` ให้รีสตาร์ท Gateway ที่ให้บริการ channel ก่อนคาดหวังให้โค้ด `register(api)` หรือ hook ใหม่ทำงาน สำหรับ deployment ระยะไกล/คอนเทนเนอร์ ให้ตรวจสอบว่าคุณกำลังรีสตาร์ท child ของ `openclaw gateway run` ตัวจริง ไม่ใช่แค่โปรเซส wrapper
|
||||
|
||||
`plugins list --json` รวม `dependencyStatus` ของแต่ละ Plugin จาก `package.json`
|
||||
`dependencies` และ `optionalDependencies` OpenClaw ตรวจสอบว่าชื่อแพ็กเกจเหล่านั้นมีอยู่ตามพาธ lookup `node_modules` ปกติของ Node สำหรับ Plugin หรือไม่ โดยจะไม่นำเข้าโค้ด runtime ของ Plugin, ไม่เรียกตัวจัดการแพ็กเกจ และไม่ซ่อม dependency ที่ขาดหาย
|
||||
`dependencies` และ `optionalDependencies` OpenClaw ตรวจสอบว่าชื่อ package เหล่านั้นอยู่ตามพาธค้นหา `node_modules` ปกติของ Node สำหรับ Plugin นั้นหรือไม่ โดยไม่ import โค้ดรันไทม์ของ Plugin, ไม่รัน package manager และไม่ซ่อม dependency ที่หายไป
|
||||
</Note>
|
||||
|
||||
`plugins search` เป็นการค้นหาแค็ตตาล็อก ClawHub ระยะไกล คำสั่งนี้ไม่ตรวจสอบสถานะในเครื่อง, ไม่แก้ config, ไม่ติดตั้งแพ็กเกจ และไม่โหลดโค้ด runtime ของ Plugin ผลลัพธ์การค้นหาประกอบด้วยชื่อแพ็กเกจ ClawHub, family, channel, version, summary และคำแนะนำการติดตั้ง เช่น `openclaw plugins install clawhub:<package>`
|
||||
`plugins search` คือการค้นหาแค็ตตาล็อก ClawHub ระยะไกล คำสั่งนี้ไม่ตรวจสอบสถานะในเครื่อง ไม่แก้ config ไม่ติดตั้ง package และไม่โหลดโค้ดรันไทม์ของ Plugin ผลการค้นหารวมชื่อ package ของ ClawHub, family, channel, version, summary และคำใบ้การติดตั้ง เช่น `openclaw plugins install clawhub:<package>`
|
||||
|
||||
สำหรับงาน Plugin ที่บันเดิลไว้ภายในอิมเมจ Docker ที่แพ็กเกจแล้ว ให้ bind-mount ไดเรกทอรีซอร์สของ Plugin ทับพาธซอร์สที่แพ็กเกจไว้ให้ตรงกัน เช่น `/app/extensions/synology-chat` OpenClaw จะค้นพบ source overlay ที่ mount นั้นก่อน `/app/dist/extensions/synology-chat`; ไดเรกทอรีซอร์สที่คัดลอกธรรมดาจะยังไม่ทำงาน เพื่อให้การติดตั้งแบบแพ็กเกจปกติยังใช้ dist ที่คอมไพล์แล้ว
|
||||
สำหรับงาน Plugin ที่บันเดิลอยู่ภายในอิมเมจ Docker แบบแพ็กเกจ ให้ bind-mount ไดเรกทอรีต้นทางของ Plugin ทับพาธต้นทางแบบแพ็กเกจที่ตรงกัน เช่น `/app/extensions/synology-chat` OpenClaw จะค้นพบ overlay ต้นทางที่ mount นั้นก่อน `/app/dist/extensions/synology-chat`; ไดเรกทอรีต้นทางที่คัดลอกธรรมดาจะไม่ทำงาน ดังนั้นการติดตั้งแบบแพ็กเกจปกติยังคงใช้ dist ที่คอมไพล์แล้ว
|
||||
|
||||
สำหรับการดีบัก runtime hook:
|
||||
สำหรับการ debug hook ขณะรันไทม์:
|
||||
|
||||
- `openclaw plugins inspect <id> --runtime --json` แสดง hook ที่ลงทะเบียนและ diagnostics จากรอบการตรวจสอบที่โหลดโมดูล การตรวจสอบ runtime จะไม่ติดตั้ง dependency; ใช้ `openclaw doctor --fix` เพื่อล้างสถานะ dependency เก่าหรือติดตั้ง Plugin ที่ดาวน์โหลดได้ซึ่งกำหนดค่าไว้แต่ขาดหาย
|
||||
- `openclaw plugins inspect <id> --runtime --json` แสดง hook ที่ลงทะเบียนแล้วและ diagnostics จากรอบ inspection ที่โหลด module แล้ว Runtime inspection ไม่เคยติดตั้ง dependency; ใช้ `openclaw doctor --fix` เพื่อล้างสถานะ dependency แบบ legacy หรือติดตั้ง Plugin ที่ดาวน์โหลดได้ซึ่งกำหนดค่าไว้แต่หายไป
|
||||
- `openclaw gateway status --deep --require-rpc` ยืนยัน Gateway ที่เข้าถึงได้, คำใบ้ service/process, พาธ config และสุขภาพ RPC
|
||||
- hook การสนทนาที่ไม่ได้บันเดิล (`llm_input`, `llm_output`, `before_agent_finalize`, `agent_end`) ต้องใช้ `plugins.entries.<id>.hooks.allowConversationAccess=true`
|
||||
- hook การสนทนาที่ไม่ใช่แบบบันเดิล (`llm_input`, `llm_output`, `before_agent_finalize`, `agent_end`) ต้องใช้ `plugins.entries.<id>.hooks.allowConversationAccess=true`
|
||||
|
||||
ใช้ `--link` เพื่อหลีกเลี่ยงการคัดลอกไดเรกทอรีในเครื่อง (เพิ่มเข้า `plugins.load.paths`):
|
||||
|
||||
@ -264,16 +274,16 @@ openclaw plugins install -l ./my-plugin
|
||||
```
|
||||
|
||||
<Note>
|
||||
`--force` ไม่รองรับร่วมกับ `--link` เพราะการติดตั้งแบบลิงก์จะใช้พาธซอร์สซ้ำแทนการคัดลอกทับเป้าหมายการติดตั้งที่จัดการอยู่
|
||||
ไม่รองรับ `--force` ร่วมกับ `--link` เพราะการติดตั้งแบบ linked ใช้พาธต้นทางซ้ำแทนการคัดลอกทับเป้าหมายการติดตั้งที่จัดการโดยระบบ
|
||||
|
||||
ใช้ `--pin` กับการติดตั้ง npm เพื่อบันทึก spec ที่ resolve แล้วแบบแน่นอน (`name@version`) ในดัชนี Plugin ที่จัดการอยู่ ขณะที่ยังคงพฤติกรรมเริ่มต้นแบบไม่ pin
|
||||
ใช้ `--pin` กับการติดตั้ง npm เพื่อบันทึก spec แบบ exact ที่ resolve แล้ว (`name@version`) ในดัชนี Plugin ที่จัดการโดยระบบ ขณะที่พฤติกรรมเริ่มต้นยังคงไม่ pin
|
||||
</Note>
|
||||
|
||||
### ดัชนี Plugin
|
||||
|
||||
เมทาดาทาการติดตั้ง Plugin เป็นสถานะที่เครื่องจัดการ ไม่ใช่ config ของผู้ใช้ การติดตั้งและอัปเดตจะเขียนข้อมูลนี้ไปยัง `plugins/installs.json` ใต้ไดเรกทอรีสถานะ OpenClaw ที่ใช้งานอยู่ map ระดับบนสุด `installRecords` เป็นแหล่งข้อมูลถาวรของเมทาดาทาการติดตั้ง รวมถึงระเบียนสำหรับ manifest ของ Plugin ที่เสียหรือขาดหาย อาร์เรย์ `plugins` เป็นแคช cold registry ที่สร้างจาก manifest ไฟล์นี้มีคำเตือนห้ามแก้ไข และถูกใช้โดย `openclaw plugins update`, uninstall, diagnostics และ cold plugin registry
|
||||
metadata การติดตั้ง Plugin เป็นสถานะที่เครื่องจัดการ ไม่ใช่ config ของผู้ใช้ การติดตั้งและอัปเดตจะเขียนไปยัง `plugins/installs.json` ภายใต้ไดเรกทอรีสถานะ OpenClaw ที่ใช้งานอยู่ map ระดับบนสุด `installRecords` คือแหล่งข้อมูลถาวรของ metadata การติดตั้ง รวมถึง record สำหรับ manifest ของ Plugin ที่เสียหรือหายไป array `plugins` คือแคช registry แบบ cold ที่ derive จาก manifest ไฟล์นี้มีคำเตือนห้ามแก้ไข และถูกใช้โดย `openclaw plugins update`, uninstall, diagnostics และ registry ของ Plugin แบบ cold
|
||||
|
||||
เมื่อ OpenClaw พบระเบียน `plugins.installs` แบบ legacy ที่มากับระบบใน config จะย้ายระเบียนเหล่านั้นไปยังดัชนี Plugin และลบคีย์ config ออก หากการเขียนอย่างใดอย่างหนึ่งล้มเหลว ระเบียน config จะถูกเก็บไว้เพื่อไม่ให้เมทาดาทาการติดตั้งสูญหาย
|
||||
เมื่อ OpenClaw พบ record `plugins.installs` แบบ legacy ที่เคยจัดส่งใน config จะย้าย record เหล่านั้นเข้าไปในดัชนี Plugin และลบ config key ออก หากการเขียนครั้งใดครั้งหนึ่งล้มเหลว record ใน config จะถูกเก็บไว้เพื่อไม่ให้ metadata การติดตั้งสูญหาย
|
||||
|
||||
### ถอนการติดตั้ง
|
||||
|
||||
@ -283,7 +293,7 @@ openclaw plugins uninstall <id> --dry-run
|
||||
openclaw plugins uninstall <id> --keep-files
|
||||
```
|
||||
|
||||
`uninstall` ลบระเบียน Plugin ออกจาก `plugins.entries`, ดัชนี Plugin ที่คงอยู่, รายการ allow/deny ของ Plugin และรายการ `plugins.load.paths` ที่ลิงก์ไว้เมื่อเกี่ยวข้อง เว้นแต่ตั้งค่า `--keep-files` การถอนการติดตั้งจะลบไดเรกทอรีการติดตั้งที่จัดการและติดตามไว้ด้วยเมื่อไดเรกทอรีนั้นอยู่ภายในรูท extensions ของ Plugin ของ OpenClaw สำหรับ Plugin หน่วยความจำที่ใช้งานอยู่ slot หน่วยความจำจะรีเซ็ตเป็น `memory-core`
|
||||
`uninstall` ลบ record ของ Plugin ออกจาก `plugins.entries`, ดัชนี Plugin ที่ persisted ไว้, รายการ allow/deny ของ Plugin และรายการ linked `plugins.load.paths` เมื่อเกี่ยวข้อง เว้นแต่ตั้งค่า `--keep-files` ไว้ uninstall ยังลบไดเรกทอรีการติดตั้งที่จัดการโดยระบบซึ่งติดตามไว้ เมื่อไดเรกทอรีนั้นอยู่ภายในราก extensions ของ Plugin ของ OpenClaw สำหรับ Plugin หน่วยความจำ active memory slot จะรีเซ็ตเป็น `memory-core`
|
||||
|
||||
<Note>
|
||||
รองรับ `--keep-config` เป็น alias ที่เลิกใช้แล้วของ `--keep-files`
|
||||
@ -299,33 +309,33 @@ openclaw plugins update @openclaw/voice-call
|
||||
openclaw plugins update openclaw-codex-app-server --dangerously-force-unsafe-install
|
||||
```
|
||||
|
||||
การอัปเดตใช้กับการติดตั้ง Plugin ที่ติดตามไว้ในดัชนี Plugin ที่จัดการอยู่ และการติดตั้ง hook-pack ที่ติดตามไว้ใน `hooks.internal.installs`
|
||||
การอัปเดตมีผลกับการติดตั้ง Plugin ที่ติดตามไว้ในดัชนี Plugin ที่จัดการโดยระบบ และการติดตั้ง hook-pack ที่ติดตามไว้ใน `hooks.internal.installs`
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="การ resolve id ของ Plugin เทียบกับ npm spec">
|
||||
เมื่อคุณส่ง id ของ Plugin OpenClaw จะใช้ spec การติดตั้งที่บันทึกไว้สำหรับ Plugin นั้นซ้ำ ซึ่งหมายความว่า dist-tag ที่เคยจัดเก็บไว้ เช่น `@beta` และเวอร์ชันที่ pin แบบแน่นอน จะยังถูกใช้ต่อในการรัน `update <id>` ภายหลัง
|
||||
<Accordion title="การ resolve id ของ Plugin เทียบกับ spec ของ npm">
|
||||
เมื่อคุณส่ง id ของ Plugin OpenClaw จะใช้ spec การติดตั้งที่บันทึกไว้สำหรับ Plugin นั้นซ้ำ นั่นหมายความว่า dist-tag ที่เคยจัดเก็บไว้ เช่น `@beta` และเวอร์ชัน exact ที่ pin ไว้จะยังคงถูกใช้ในการรัน `update <id>` ภายหลัง
|
||||
|
||||
สำหรับการติดตั้ง npm คุณยังสามารถส่ง npm package spec แบบชัดเจนพร้อม dist-tag หรือเวอร์ชันแน่นอนได้ด้วย OpenClaw จะ resolve ชื่อแพ็กเกจนั้นกลับไปยังระเบียน Plugin ที่ติดตามไว้ อัปเดต Plugin ที่ติดตั้งนั้น และบันทึก npm spec ใหม่สำหรับการอัปเดตตาม id ในอนาคต
|
||||
สำหรับการติดตั้ง npm คุณยังสามารถส่ง spec ของ package npm แบบ explicit พร้อม dist-tag หรือเวอร์ชัน exact ได้ OpenClaw จะ resolve ชื่อ package นั้นกลับไปยัง record ของ Plugin ที่ติดตามไว้ อัปเดต Plugin ที่ติดตั้งนั้น และบันทึก spec npm ใหม่สำหรับการอัปเดตตาม id ในอนาคต
|
||||
|
||||
การส่งชื่อแพ็กเกจ npm โดยไม่มีเวอร์ชันหรือแท็กก็จะ resolve กลับไปยังระเบียน Plugin ที่ติดตามไว้เช่นกัน ใช้วิธีนี้เมื่อ Plugin ถูก pin ไว้ที่เวอร์ชันแน่นอน และคุณต้องการย้ายกลับไปยังสาย release เริ่มต้นของ registry
|
||||
การส่งชื่อ package npm โดยไม่มีเวอร์ชันหรือ tag ก็ resolve กลับไปยัง record ของ Plugin ที่ติดตามไว้เช่นกัน ใช้วิธีนี้เมื่อ Plugin ถูก pin ไว้กับเวอร์ชัน exact และคุณต้องการย้ายกลับไปยัง release line เริ่มต้นของ registry
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="การอัปเดต channel beta">
|
||||
`openclaw plugins update` ใช้ spec ของ Plugin ที่ติดตามไว้ซ้ำ เว้นแต่คุณจะส่ง spec ใหม่ `openclaw update` ยังรู้จัก channel อัปเดต OpenClaw ที่ใช้งานอยู่เพิ่มเติม: บน channel beta ระเบียน Plugin จาก npm และ ClawHub ในสายเริ่มต้นจะลอง `@beta` ก่อน แล้วจึง fallback ไปยัง spec default/latest ที่บันทึกไว้หากไม่มี release beta ของ Plugin เวอร์ชันแน่นอนและแท็กที่ระบุชัดเจนจะยังคง pin กับตัวเลือกนั้น
|
||||
`openclaw plugins update` ใช้ spec ของ Plugin ที่ติดตามไว้ซ้ำ เว้นแต่คุณจะส่ง spec ใหม่ `openclaw update` ยังรู้จัก channel การอัปเดต OpenClaw ที่ใช้งานอยู่เพิ่มเติม: บน channel beta, record ของ Plugin จาก npm และ ClawHub ใน default-line จะลอง `@beta` ก่อน แล้ว fallback ไปยัง spec default/latest ที่บันทึกไว้หากไม่มี release beta ของ Plugin เวอร์ชัน exact และ tag explicit จะยังคง pin อยู่กับ selector นั้น
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="การตรวจสอบเวอร์ชันและ integrity drift">
|
||||
ก่อนการอัปเดต npm แบบสด OpenClaw จะตรวจสอบเวอร์ชันแพ็กเกจที่ติดตั้งเทียบกับเมทาดาทา registry ของ npm หากเวอร์ชันที่ติดตั้งและอัตลักษณ์ artifact ที่บันทึกไว้ตรงกับเป้าหมายที่ resolve แล้วอยู่แล้ว การอัปเดตจะถูกข้ามโดยไม่ดาวน์โหลด, ติดตั้งใหม่ หรือเขียน `openclaw.json` ใหม่
|
||||
ก่อนการอัปเดต npm แบบสด OpenClaw ตรวจสอบเวอร์ชัน package ที่ติดตั้งกับ metadata ของ npm registry หากเวอร์ชันที่ติดตั้งและ identity ของ artifact ที่บันทึกไว้ตรงกับ target ที่ resolve แล้ว การอัปเดตจะถูกข้ามโดยไม่ดาวน์โหลด ติดตั้งซ้ำ หรือเขียน `openclaw.json` ใหม่
|
||||
|
||||
เมื่อมี hash integrity ที่จัดเก็บไว้และ hash ของ artifact ที่ดึงมาเปลี่ยนแปลง OpenClaw จะถือว่านั่นเป็น npm artifact drift คำสั่ง `openclaw plugins update` แบบโต้ตอบจะพิมพ์ hash ที่คาดหวังและ hash จริง แล้วขอการยืนยันก่อนดำเนินการต่อ ตัวช่วยอัปเดตแบบไม่โต้ตอบจะปิดแบบล้มเหลว เว้นแต่ caller จะระบุ policy การดำเนินการต่ออย่างชัดเจน
|
||||
เมื่อมี integrity hash ที่จัดเก็บไว้และ hash ของ artifact ที่ fetch มาเปลี่ยนไป OpenClaw จะถือว่านั่นคือ npm artifact drift คำสั่ง interactive `openclaw plugins update` จะพิมพ์ hash ที่คาดหวังและ hash จริง แล้วขอการยืนยันก่อนดำเนินการต่อ helper อัปเดตแบบ non-interactive จะ fail closed เว้นแต่ caller จะระบุนโยบาย continuation แบบ explicit
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="--dangerously-force-unsafe-install เมื่ออัปเดต">
|
||||
`--dangerously-force-unsafe-install` ยังใช้ได้กับ `plugins update` ในฐานะ override ฉุกเฉินสำหรับ false positive ของการสแกน dangerous-code ในตัวระหว่างการอัปเดต Plugin แต่ยังไม่ข้าม policy block `before_install` ของ Plugin หรือการบล็อกเมื่อการสแกนล้มเหลว และใช้กับการอัปเดต Plugin เท่านั้น ไม่ใช่การอัปเดต hook-pack
|
||||
<Accordion title="--dangerously-force-unsafe-install บน update">
|
||||
`--dangerously-force-unsafe-install` ยังใช้ได้บน `plugins update` เป็น override แบบ break-glass สำหรับ false positive จากการสแกน dangerous-code ในตัวระหว่างอัปเดต Plugin แต่ยังไม่ข้ามการบล็อกตามนโยบาย `before_install` ของ Plugin หรือการบล็อกเมื่อสแกนล้มเหลว และมีผลกับการอัปเดต Plugin เท่านั้น ไม่ใช่การอัปเดต hook-pack
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### ตรวจสอบ
|
||||
### ตรวจสอบรายละเอียด
|
||||
|
||||
```bash
|
||||
openclaw plugins inspect <id>
|
||||
@ -333,21 +343,21 @@ openclaw plugins inspect <id> --runtime
|
||||
openclaw plugins inspect <id> --json
|
||||
```
|
||||
|
||||
Inspect แสดง identity, สถานะการโหลด, source, ความสามารถของ manifest, policy flags, diagnostics, เมทาดาทาการติดตั้ง, ความสามารถของบันเดิล และการรองรับ MCP หรือ LSP server ที่ตรวจพบ โดยค่าเริ่มต้นจะไม่นำเข้า runtime ของ Plugin เพิ่ม `--runtime` เพื่อโหลดโมดูล Plugin และรวม hook, tools, commands, services, gateway methods และ HTTP routes ที่ลงทะเบียนไว้ การตรวจสอบ runtime จะรายงาน dependency ของ Plugin ที่ขาดหายโดยตรง; การติดตั้งและซ่อมแซมยังอยู่ใน `openclaw plugins install`, `openclaw plugins update` และ `openclaw doctor --fix`
|
||||
Inspect แสดง identity, สถานะการโหลด, source, ความสามารถจาก manifest, policy flags, diagnostics, metadata การติดตั้ง, ความสามารถของบันเดิล และการรองรับ server MCP หรือ LSP ใด ๆ ที่ตรวจพบ โดยค่าเริ่มต้นจะไม่ import รันไทม์ของ Plugin เพิ่ม `--runtime` เพื่อโหลด module ของ Plugin และรวม hook, tools, commands, services, gateway methods และ HTTP routes ที่ลงทะเบียนไว้ Runtime inspection รายงาน dependency ของ Plugin ที่หายไปโดยตรง; การติดตั้งและการซ่อมยังคงอยู่ใน `openclaw plugins install`, `openclaw plugins update` และ `openclaw doctor --fix`
|
||||
|
||||
คำสั่ง CLI ที่ Plugin เป็นเจ้าของจะติดตั้งเป็นกลุ่มคำสั่งราก `openclaw` หลังจาก `inspect --runtime` แสดงคำสั่งใต้ `cliCommands` แล้ว ให้รันเป็น `openclaw <command> ...`; เช่น Plugin ที่ลงทะเบียน `demo-git` สามารถตรวจสอบได้ด้วย `openclaw demo-git ping`
|
||||
คำสั่ง CLI ที่ Plugin เป็นเจ้าของจะติดตั้งเป็นกลุ่มคำสั่ง root `openclaw` หลังจาก `inspect --runtime` แสดงคำสั่งใต้ `cliCommands` ให้รันเป็น `openclaw <command> ...`; ตัวอย่างเช่น Plugin ที่ลงทะเบียน `demo-git` สามารถตรวจสอบได้ด้วย `openclaw demo-git ping`
|
||||
|
||||
Plugin แต่ละตัวจะถูกจัดประเภทตามสิ่งที่ลงทะเบียนจริงใน runtime:
|
||||
แต่ละ Plugin ถูกจัดประเภทตามสิ่งที่ลงทะเบียนจริงขณะรันไทม์:
|
||||
|
||||
- **plain-capability** — ความสามารถหนึ่งประเภท (เช่น Plugin ที่เป็น provider อย่างเดียว)
|
||||
- **hybrid-capability** — ความสามารถหลายประเภท (เช่น ข้อความ + เสียงพูด + รูปภาพ)
|
||||
- **plain-capability** — ความสามารถหนึ่งประเภท (เช่น Plugin เฉพาะ provider)
|
||||
- **hybrid-capability** — ความสามารถหลายประเภท (เช่น text + speech + images)
|
||||
- **hook-only** — เฉพาะ hook ไม่มีความสามารถหรือ surface
|
||||
- **non-capability** — tools/commands/services แต่ไม่มีความสามารถ
|
||||
|
||||
ดู [รูปทรง Plugin](/th/plugins/architecture#plugin-shapes) สำหรับข้อมูลเพิ่มเติมเกี่ยวกับโมเดลความสามารถ
|
||||
ดู [รูปแบบ Plugin](/th/plugins/architecture#plugin-shapes) สำหรับข้อมูลเพิ่มเติมเกี่ยวกับโมเดลความสามารถ
|
||||
|
||||
<Note>
|
||||
แฟล็ก `--json` ส่งออกรายงานที่เครื่องอ่านได้ เหมาะสำหรับสคริปต์และการ audit `inspect --all` จะแสดงตารางทั้ง fleet พร้อมคอลัมน์ shape, capability kinds, compatibility notices, bundle capabilities และ hook summary `info` เป็น alias ของ `inspect`
|
||||
flag `--json` ส่งออกรายงานที่เครื่องอ่านได้ เหมาะสำหรับ scripting และ auditing `inspect --all` แสดงตารางครอบคลุมทั้ง fleet พร้อมคอลัมน์ shape, capability kinds, compatibility notices, bundle capabilities และ hook summary `info` เป็น alias ของ `inspect`
|
||||
</Note>
|
||||
|
||||
### Doctor
|
||||
@ -356,11 +366,11 @@ Plugin แต่ละตัวจะถูกจัดประเภทตา
|
||||
openclaw plugins doctor
|
||||
```
|
||||
|
||||
`doctor` รายงานข้อผิดพลาดในการโหลด Plugin, diagnostics ของ manifest/discovery และ compatibility notices เมื่อทุกอย่างสะอาด จะพิมพ์ `No plugin issues detected.`
|
||||
`doctor` รายงานข้อผิดพลาดการโหลด Plugin, diagnostics ของ manifest/discovery และ compatibility notices เมื่อทุกอย่างสะอาดจะแสดง `No plugin issues detected.`
|
||||
|
||||
หาก Plugin ที่กำหนดค่าไว้มีอยู่บนดิสก์แต่ถูกบล็อกโดยการตรวจ path-safety ของ loader การตรวจสอบ config จะเก็บรายการ Plugin ไว้และรายงานเป็น `present but blocked` ให้แก้ diagnostic ของ Plugin ที่ถูกบล็อกก่อนหน้า เช่น ownership ของพาธหรือ permission แบบ world-writable แทนการลบ config `plugins.entries.<id>` หรือ `plugins.allow`
|
||||
หาก Plugin ที่กำหนดค่าไว้มีอยู่บนดิสก์แต่ถูกบล็อกโดยการตรวจสอบ path-safety ของ loader การ validate config จะเก็บรายการ Plugin ไว้และรายงานเป็น `present but blocked` ให้แก้ diagnostic ของ Plugin ที่ถูกบล็อกก่อนหน้า เช่น ownership ของพาธหรือ permission แบบ world-writable แทนที่จะลบ config `plugins.entries.<id>` หรือ `plugins.allow`
|
||||
|
||||
สำหรับความล้มเหลวของรูปทรงโมดูล เช่น export `register`/`activate` ที่ขาดหาย ให้รันซ้ำด้วย `OPENCLAW_PLUGIN_LOAD_DEBUG=1` เพื่อรวมสรุปรูปทรง export แบบกระชับไว้ในเอาต์พุต diagnostic
|
||||
สำหรับความล้มเหลวของ module-shape เช่น export `register`/`activate` หายไป ให้รันซ้ำด้วย `OPENCLAW_PLUGIN_LOAD_DEBUG=1` เพื่อรวมสรุป export-shape แบบกระชับใน output diagnostics
|
||||
|
||||
### Registry
|
||||
|
||||
@ -370,25 +380,25 @@ openclaw plugins registry --refresh
|
||||
openclaw plugins registry --json
|
||||
```
|
||||
|
||||
registry Plugin ในเครื่องคือโมเดลอ่านแบบเย็นที่คงอยู่ของ OpenClaw สำหรับ identity ของ Plugin ที่ติดตั้ง, enablement, เมทาดาทา source และ ownership ของ contribution การเริ่มต้นปกติ, การค้นหาเจ้าของ provider, การจำแนก channel setup และ inventory ของ Plugin สามารถอ่านข้อมูลนี้ได้โดยไม่ต้องนำเข้าโมดูล runtime ของ Plugin
|
||||
registry ของ Plugin ในเครื่องคือโมเดลอ่านแบบ cold ที่ persisted ไว้ของ OpenClaw สำหรับ identity ของ Plugin ที่ติดตั้ง, enablement, metadata ของ source และ ownership ของ contribution การ startup ปกติ, การ lookup เจ้าของ provider, การจัดประเภท setup ของ channel และ inventory ของ Plugin สามารถอ่านได้โดยไม่ต้อง import module รันไทม์ของ Plugin
|
||||
|
||||
ใช้ `plugins registry` เพื่อตรวจสอบว่ารีจิสทรีที่จัดเก็บไว้มีอยู่ เป็นปัจจุบัน หรือล้าสมัย ใช้ `--refresh` เพื่อสร้างใหม่จากดัชนี Plugin ที่จัดเก็บไว้ นโยบายการกำหนดค่า และเมทาดาทา manifest/package นี่คือเส้นทางการซ่อมแซม ไม่ใช่เส้นทางการเปิดใช้งานขณะรันไทม์
|
||||
ใช้ `plugins registry` เพื่อตรวจสอบว่า registry ที่บันทึกไว้มีอยู่ เป็นปัจจุบัน หรือล้าสมัย ใช้ `--refresh` เพื่อสร้างใหม่จากดัชนี Plugin ที่บันทึกไว้ นโยบาย config และเมทาดาทา manifest/package นี่เป็นเส้นทางสำหรับการซ่อมแซม ไม่ใช่เส้นทางสำหรับการเปิดใช้งานขณะรันไทม์
|
||||
|
||||
<Warning>
|
||||
`OPENCLAW_DISABLE_PERSISTED_PLUGIN_REGISTRY=1` เป็นสวิตช์ความเข้ากันได้แบบฉุกเฉินที่เลิกใช้แล้วสำหรับความล้มเหลวในการอ่านรีจิสทรี ควรใช้ `plugins registry --refresh` หรือ `openclaw doctor --fix`; กลไกสำรองผ่าน env มีไว้สำหรับการกู้คืนการเริ่มต้นระบบฉุกเฉินเท่านั้นระหว่างที่การย้ายระบบกำลังทยอยใช้งาน
|
||||
`OPENCLAW_DISABLE_PERSISTED_PLUGIN_REGISTRY=1` เป็นสวิตช์ความเข้ากันได้แบบ break-glass ที่เลิกใช้แล้วสำหรับความล้มเหลวในการอ่าน registry ควรใช้ `plugins registry --refresh` หรือ `openclaw doctor --fix`; fallback ผ่าน env มีไว้สำหรับการกู้คืนการเริ่มต้นในกรณีฉุกเฉินเท่านั้นระหว่างที่การย้ายระบบกำลังทยอยใช้งาน
|
||||
</Warning>
|
||||
|
||||
### มาร์เก็ตเพลส
|
||||
### Marketplace
|
||||
|
||||
```bash
|
||||
openclaw plugins marketplace list <source>
|
||||
openclaw plugins marketplace list <source> --json
|
||||
```
|
||||
|
||||
รายการมาร์เก็ตเพลสรับพาธมาร์เก็ตเพลสภายในเครื่อง, พาธ `marketplace.json`, รูปย่อ GitHub เช่น `owner/repo`, URL ของ repo GitHub หรือ URL git `--json` จะพิมพ์ป้ายกำกับแหล่งที่มาที่แก้ไขแล้ว พร้อมกับ manifest ของมาร์เก็ตเพลสที่แยกวิเคราะห์แล้วและรายการ Plugin
|
||||
รายการ Marketplace รองรับพาธ Marketplace ในเครื่อง, พาธ `marketplace.json`, รูปย่อ GitHub เช่น `owner/repo`, URL repo ของ GitHub หรือ URL git `--json` จะแสดงป้ายกำกับแหล่งที่มาที่ resolve แล้ว พร้อม manifest ของ Marketplace ที่แยกวิเคราะห์แล้วและรายการ Plugin
|
||||
|
||||
## ที่เกี่ยวข้อง
|
||||
|
||||
- [การสร้าง Plugin](/th/plugins/building-plugins)
|
||||
- [ข้อมูลอ้างอิง CLI](/th/cli)
|
||||
- [Plugin ชุมชน](/th/plugins/community)
|
||||
- [Plugin จากชุมชน](/th/plugins/community)
|
||||
|
||||
@ -1,29 +1,29 @@
|
||||
---
|
||||
read_when:
|
||||
- คุณต้องตรวจสอบความถูกต้องของการกำหนดเส้นทางพร็อกซีที่ผู้ปฏิบัติงานจัดการก่อนการปรับใช้
|
||||
- คุณต้องจับทราฟฟิกการรับส่งข้อมูลของ OpenClaw ในเครื่องเพื่อการดีบัก
|
||||
- คุณต้องการตรวจสอบเซสชันพร็อกซีดีบัก บล็อบ หรือค่าพรีเซ็ตการสืบค้นในตัว
|
||||
summary: ข้อมูลอ้างอิง CLI สำหรับ `openclaw proxy` รวมถึงการตรวจสอบความถูกต้องของพร็อกซีที่ผู้ปฏิบัติงานจัดการ และตัวตรวจสอบการจับข้อมูลพร็อกซีดีบักภายในเครื่อง
|
||||
- คุณต้องตรวจสอบยืนยันการกำหนดเส้นทางพร็อกซีที่ผู้ปฏิบัติการจัดการก่อนการปรับใช้
|
||||
- คุณต้องจับทราฟฟิกการรับส่งข้อมูลของ OpenClaw ภายในเครื่องเพื่อการดีบัก
|
||||
- คุณต้องการตรวจสอบเซสชันพร็อกซีดีบัก บล็อบ หรือพรีเซ็ตคิวรีในตัว
|
||||
summary: ข้อมูลอ้างอิง CLI สำหรับ `openclaw proxy` รวมถึงการตรวจสอบพร็อกซีที่จัดการโดยผู้ปฏิบัติการและตัวตรวจสอบการจับพร็อกซีดีบักภายในเครื่อง
|
||||
title: พร็อกซี
|
||||
x-i18n:
|
||||
generated_at: "2026-05-01T10:15:34Z"
|
||||
generated_at: "2026-05-04T07:03:12Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: e0820de861bfe1ec14e0c1624d636d6474b5fedd317e3ba1baaa61f6530e06e9
|
||||
source_hash: 9589bedafb97c31bcb6536a04307cd0c6550e1f307693bd4401785d79f34a1eb
|
||||
source_path: cli/proxy.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
# `openclaw proxy`
|
||||
|
||||
ตรวจสอบความถูกต้องของการกำหนดเส้นทางพร็อกซีที่จัดการโดยผู้ปฏิบัติการ หรือเรียกใช้พร็อกซีดีบักแบบชัดเจนในเครื่อง
|
||||
และตรวจดูทราฟฟิกที่จับบันทึกไว้
|
||||
ตรวจสอบความถูกต้องของการกำหนดเส้นทางพร็อกซีที่ผู้ปฏิบัติงานจัดการ หรือเรียกใช้พร็อกซีดีบักแบบระบุชัดภายในเครื่อง
|
||||
และตรวจสอบทราฟฟิกที่บันทึกไว้
|
||||
|
||||
ใช้ `validate` เพื่อ preflight พร็อกซีส่งต่อที่จัดการโดยผู้ปฏิบัติการก่อนเปิดใช้
|
||||
ใช้ `validate` เพื่อตรวจสอบล่วงหน้าพร็อกซีส่งต่อที่ผู้ปฏิบัติงานจัดการก่อนเปิดใช้
|
||||
การกำหนดเส้นทางพร็อกซีของ OpenClaw คำสั่งอื่นเป็นเครื่องมือดีบักสำหรับ
|
||||
การตรวจสอบระดับทรานสปอร์ต: สามารถเริ่มพร็อกซีในเครื่อง เรียกใช้คำสั่งลูก
|
||||
โดยเปิดการจับบันทึก แสดงรายการเซสชันการจับบันทึก คิวรีรูปแบบทราฟฟิกทั่วไป อ่าน
|
||||
บล็อบที่จับบันทึกไว้ และล้างข้อมูลการจับบันทึกในเครื่อง
|
||||
การตรวจสอบในระดับการขนส่ง: สามารถเริ่มพร็อกซีภายในเครื่อง เรียกใช้คำสั่งลูก
|
||||
พร้อมเปิดการบันทึก แสดงรายการเซสชันการบันทึก ค้นหารูปแบบทราฟฟิกทั่วไป อ่าน
|
||||
บล็อบที่บันทึกไว้ และล้างข้อมูลการบันทึกภายในเครื่อง
|
||||
|
||||
## คำสั่ง
|
||||
|
||||
@ -40,29 +40,29 @@ openclaw proxy purge
|
||||
|
||||
## ตรวจสอบความถูกต้อง
|
||||
|
||||
`openclaw proxy validate` ตรวจสอบ URL พร็อกซีที่จัดการโดยผู้ปฏิบัติการซึ่งมีผลใช้งานจริงจาก
|
||||
`--proxy-url`, คอนฟิก หรือ `OPENCLAW_PROXY_URL` โดยจะรายงานปัญหาคอนฟิกเมื่อ
|
||||
ไม่มีพร็อกซีที่เปิดใช้และกำหนดค่าไว้; ใช้ `--proxy-url` สำหรับการ preflight แบบครั้งเดียว
|
||||
ก่อนเปลี่ยนคอนฟิก ตามค่าเริ่มต้น คำสั่งนี้จะตรวจสอบว่าปลายทางสาธารณะสำเร็จ
|
||||
ผ่านพร็อกซี และพร็อกซีไม่สามารถเข้าถึง canary แบบลูปแบ็กชั่วคราวได้
|
||||
ปลายทางที่กำหนดเองว่าควรถูกปฏิเสธจะเป็นแบบ fail-closed: การตอบกลับ HTTP และความล้มเหลว
|
||||
ของทรานสปอร์ตที่กำกวมจะถือว่าล้มเหลวทั้งคู่ เว้นแต่คุณจะสามารถตรวจสอบสัญญาณการปฏิเสธ
|
||||
เฉพาะการติดตั้งใช้งานแยกต่างหากได้
|
||||
`openclaw proxy validate` ตรวจสอบ URL พร็อกซีที่ผู้ปฏิบัติงานจัดการซึ่งมีผลใช้งาน จาก
|
||||
`--proxy-url`, การกำหนดค่า หรือ `OPENCLAW_PROXY_URL` โดยรายงานปัญหาการกำหนดค่าเมื่อ
|
||||
ไม่มีพร็อกซีที่เปิดใช้งานและกำหนดค่าไว้ ใช้ `--proxy-url` สำหรับการตรวจสอบล่วงหน้าแบบครั้งเดียว
|
||||
ก่อนเปลี่ยนการกำหนดค่า โดยค่าเริ่มต้น ระบบจะตรวจสอบว่าปลายทางสาธารณะสำเร็จ
|
||||
ผ่านพร็อกซี และพร็อกซีไม่สามารถเข้าถึงคานารี loopback ชั่วคราวได้
|
||||
ปลายทางที่กำหนดเองซึ่งคาดว่าจะถูกปฏิเสธจะปิดเมื่อไม่ผ่าน: การตอบกลับ HTTP และความล้มเหลว
|
||||
ของการขนส่งที่กำกวมจะถือว่าไม่ผ่านทั้งคู่ เว้นแต่คุณจะสามารถตรวจสอบสัญญาณการปฏิเสธ
|
||||
เฉพาะการปรับใช้แยกต่างหากได้
|
||||
|
||||
ตัวเลือก:
|
||||
|
||||
- `--json`: พิมพ์ JSON ที่เครื่องอ่านได้
|
||||
- `--proxy-url <url>`: ตรวจสอบความถูกต้องของ URL พร็อกซีนี้แทนคอนฟิกหรือ env
|
||||
- `--allowed-url <url>`: เพิ่มปลายทางที่คาดว่าจะสำเร็จผ่านพร็อกซี ทำซ้ำเพื่อเช็กหลายปลายทาง
|
||||
- `--denied-url <url>`: เพิ่มปลายทางที่คาดว่าจะถูกพร็อกซีบล็อก ทำซ้ำเพื่อเช็กหลายปลายทาง
|
||||
- `--timeout-ms <ms>`: เวลาหมดเวลาต่อคำขอ หน่วยเป็นมิลลิวินาที
|
||||
- `--proxy-url <url>`: ตรวจสอบ URL พร็อกซีนี้แทนการกำหนดค่าหรือตัวแปรสภาพแวดล้อม
|
||||
- `--allowed-url <url>`: เพิ่มปลายทางที่คาดว่าจะสำเร็จผ่านพร็อกซี ทำซ้ำเพื่อตรวจสอบหลายปลายทาง
|
||||
- `--denied-url <url>`: เพิ่มปลายทางที่คาดว่าจะถูกพร็อกซีบล็อก ทำซ้ำเพื่อตรวจสอบหลายปลายทาง
|
||||
- `--timeout-ms <ms>`: ระยะหมดเวลาต่อคำขอ หน่วยเป็นมิลลิวินาที
|
||||
|
||||
ดู [พร็อกซีเครือข่าย](/th/security/network-proxy) สำหรับคำแนะนำการติดตั้งใช้งานและความหมาย
|
||||
ดู [พร็อกซีเครือข่าย](/th/security/network-proxy) สำหรับแนวทางการปรับใช้และความหมาย
|
||||
ของการปฏิเสธ
|
||||
|
||||
## พรีเซ็ตคิวรี
|
||||
## พรีเซ็ตการค้นหา
|
||||
|
||||
`openclaw proxy query --preset <name>` รับค่า:
|
||||
`openclaw proxy query --preset <name>` ยอมรับ:
|
||||
|
||||
- `double-sends`
|
||||
- `retry-storms`
|
||||
@ -73,13 +73,14 @@ openclaw proxy purge
|
||||
|
||||
## หมายเหตุ
|
||||
|
||||
- `start` มีค่าเริ่มต้นเป็น `127.0.0.1` เว้นแต่จะตั้งค่า `--host`
|
||||
- `run` เริ่มพร็อกซีดีบักในเครื่อง แล้วจึงเรียกใช้คำสั่งหลัง `--`
|
||||
- `validate` ออกด้วยรหัส 1 เมื่อคอนฟิกพร็อกซีหรือการตรวจสอบปลายทางล้มเหลว
|
||||
- การจับบันทึกเป็นข้อมูลดีบักในเครื่อง; ใช้ `openclaw proxy purge` เมื่อเสร็จสิ้น
|
||||
- `start` ใช้ค่าเริ่มต้นเป็น `127.0.0.1` เว้นแต่จะตั้งค่า `--host`
|
||||
- `run` เริ่มพร็อกซีดีบักภายในเครื่องแล้วจึงเรียกใช้คำสั่งหลัง `--`
|
||||
- การส่งต่อไปยังต้นทางโดยตรงของพร็อกซีดีบักจะเปิดซ็อกเก็ตต้นทางเพื่อการวินิจฉัย เมื่อโหมดพร็อกซีที่ OpenClaw จัดการเปิดใช้งานอยู่ การส่งต่อโดยตรงสำหรับคำขอพร็อกซีและอุโมงค์ CONNECT จะถูกปิดใช้งานตามค่าเริ่มต้น ตั้งค่า `OPENCLAW_DEBUG_PROXY_ALLOW_DIRECT_CONNECT_WITH_MANAGED_PROXY=1` เฉพาะสำหรับการวินิจฉัยภายในเครื่องที่ได้รับอนุมัติแล้วเท่านั้น
|
||||
- `validate` ออกด้วยรหัส 1 เมื่อการกำหนดค่าพร็อกซีหรือการตรวจสอบปลายทางล้มเหลว
|
||||
- การบันทึกเป็นข้อมูลดีบักภายในเครื่อง ใช้ `openclaw proxy purge` เมื่อดำเนินการเสร็จ
|
||||
|
||||
## ที่เกี่ยวข้อง
|
||||
|
||||
- [เอกสารอ้างอิง CLI](/th/cli)
|
||||
- [อ้างอิง CLI](/th/cli)
|
||||
- [พร็อกซีเครือข่าย](/th/security/network-proxy)
|
||||
- [การตรวจสอบสิทธิ์พร็อกซีที่เชื่อถือได้](/th/gateway/trusted-proxy-auth)
|
||||
- [การยืนยันตัวตนของพร็อกซีที่เชื่อถือได้](/th/gateway/trusted-proxy-auth)
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
---
|
||||
read_when:
|
||||
- คุณต้องการแสดงรายการเซสชันที่จัดเก็บไว้และดูกิจกรรมล่าสุด
|
||||
summary: ข้อมูลอ้างอิง CLI สำหรับ `openclaw sessions` (แสดงรายการเซสชันที่จัดเก็บไว้ + การใช้งาน)
|
||||
- คุณต้องการแสดงรายการเซสชันที่บันทึกไว้และดูกิจกรรมล่าสุด
|
||||
summary: เอกสารอ้างอิง CLI สำหรับ `openclaw sessions` (แสดงรายการเซสชันที่จัดเก็บไว้ + การใช้งาน)
|
||||
title: เซสชัน
|
||||
x-i18n:
|
||||
generated_at: "2026-05-02T20:42:28Z"
|
||||
generated_at: "2026-05-04T07:02:48Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 5c9ec3ca55f7c5b6217b481e9da62f5416df73e69405a0dc15e77d2afeac723f
|
||||
source_hash: 8dc90344f40c53513bd6db3696bc709279155f26e7c3b6ea27e81a07a2f9f15e
|
||||
source_path: cli/sessions.md
|
||||
workflow: 16
|
||||
---
|
||||
@ -16,7 +16,9 @@ x-i18n:
|
||||
|
||||
แสดงรายการเซสชันการสนทนาที่จัดเก็บไว้
|
||||
|
||||
รายการเซสชันไม่ใช่การตรวจสอบว่าช่องทาง/ผู้ให้บริการยังเชื่อมต่ออยู่หรือไม่ รายการเหล่านี้แสดงแถวการสนทนาที่บันทึกถาวรจากที่จัดเก็บเซสชัน ช่องทาง Discord, Slack, Telegram หรือช่องทางอื่นที่เงียบอยู่สามารถเชื่อมต่อใหม่ได้สำเร็จโดยไม่สร้างแถวเซสชันใหม่จนกว่าจะมีการประมวลผลข้อความ ใช้ `openclaw channels status --probe`, `openclaw status --deep` หรือ `openclaw health --verbose` เมื่อคุณต้องการตรวจสอบการเชื่อมต่อช่องทางแบบสด
|
||||
รายการเซสชันไม่ใช่การตรวจสอบความพร้อมใช้งานของช่องทาง/ผู้ให้บริการ รายการเหล่านี้แสดงแถวการสนทนาที่คงอยู่จาก session stores ช่องทาง Discord, Slack, Telegram หรือช่องทางอื่นที่เงียบอยู่สามารถเชื่อมต่อใหม่ได้สำเร็จโดยไม่สร้างแถวเซสชันใหม่จนกว่าจะมีการประมวลผลข้อความ ใช้ `openclaw channels status --probe`, `openclaw status --deep` หรือ `openclaw health --verbose` เมื่อต้องการการเชื่อมต่อช่องทางแบบสด
|
||||
|
||||
การตอบกลับ `sessions.list` ของ Gateway ถูกจำกัดขอบเขตโดยค่าเริ่มต้น เพื่อให้ store ขนาดใหญ่ที่ใช้งานยาวนานไม่ผูกขาด event loop ของ Gateway ส่ง `limit` ที่เป็นค่าบวกอย่างชัดเจนจาก RPC clients เมื่อต้องการกรอบผลลัพธ์ที่ต่างออกไป การตอบกลับจะมี `totalCount`, `limitApplied` และ `hasMore` เมื่อผู้เรียกต้องแสดงว่ายังมีแถวเพิ่มเติมอยู่
|
||||
|
||||
```bash
|
||||
openclaw sessions
|
||||
@ -29,22 +31,22 @@ openclaw sessions --json
|
||||
|
||||
การเลือกขอบเขต:
|
||||
|
||||
- ค่าเริ่มต้น: ที่จัดเก็บเอเจนต์ค่าเริ่มต้นที่กำหนดค่าไว้
|
||||
- `--verbose`: การบันทึกรายละเอียด
|
||||
- `--agent <id>`: ที่จัดเก็บเอเจนต์ที่กำหนดค่าไว้หนึ่งรายการ
|
||||
- `--all-agents`: รวมที่จัดเก็บเอเจนต์ที่กำหนดค่าไว้ทั้งหมด
|
||||
- `--store <path>`: เส้นทางที่จัดเก็บแบบระบุชัดเจน (ไม่สามารถใช้ร่วมกับ `--agent` หรือ `--all-agents` ได้)
|
||||
- ค่าเริ่มต้น: store ของ agent เริ่มต้นที่กำหนดค่าไว้
|
||||
- `--verbose`: การบันทึก log แบบละเอียด
|
||||
- `--agent <id>`: store ของ agent ที่กำหนดค่าไว้หนึ่งรายการ
|
||||
- `--all-agents`: รวม store ของ agent ที่กำหนดค่าไว้ทั้งหมด
|
||||
- `--store <path>`: เส้นทาง store ที่ระบุอย่างชัดเจน (ใช้ร่วมกับ `--agent` หรือ `--all-agents` ไม่ได้)
|
||||
|
||||
ส่งออกชุด trajectory สำหรับเซสชันที่จัดเก็บไว้:
|
||||
ส่งออก trajectory bundle สำหรับเซสชันที่จัดเก็บไว้:
|
||||
|
||||
```bash
|
||||
openclaw sessions export-trajectory --session-key "agent:main:telegram:direct:123" --workspace .
|
||||
openclaw sessions export-trajectory --session-key "agent:main:telegram:direct:123" --output bug-123 --json
|
||||
```
|
||||
|
||||
นี่คือเส้นทางคำสั่งที่คำสั่ง slash `/export-trajectory` ใช้หลังจากเจ้าของอนุมัติคำขอ exec แล้ว ไดเรกทอรีเอาต์พุตจะถูกแก้เส้นทางภายใน `.openclaw/trajectory-exports/` ภายใต้เวิร์กสเปซที่เลือกเสมอ
|
||||
นี่คือเส้นทางคำสั่งที่คำสั่ง slash `/export-trajectory` ใช้หลังจาก owner อนุมัติคำขอ exec แล้ว ไดเรกทอรีเอาต์พุตจะถูก resolve ภายใน `.openclaw/trajectory-exports/` ใต้ workspace ที่เลือกเสมอ
|
||||
|
||||
`openclaw sessions --all-agents` อ่านที่จัดเก็บเอเจนต์ที่กำหนดค่าไว้ การค้นหาเซสชันของ Gateway และ ACP มีขอบเขตกว้างกว่า: ยังรวมถึงที่จัดเก็บที่มีอยู่เฉพาะบนดิสก์ซึ่งพบภายใต้ราก `agents/` ค่าเริ่มต้น หรือราก `session.store` แบบเทมเพลต ที่จัดเก็บที่ค้นพบเหล่านั้นต้องแก้เส้นทางเป็นไฟล์ `sessions.json` ปกติภายในรากของเอเจนต์; symlink และเส้นทางที่อยู่นอกรากจะถูกข้าม
|
||||
`openclaw sessions --all-agents` อ่าน store ของ agent ที่กำหนดค่าไว้ การค้นหาเซสชันของ Gateway และ ACP กว้างกว่า: ยังรวม store ที่มีเฉพาะบนดิสก์ซึ่งพบใต้ root เริ่มต้น `agents/` หรือ root `session.store` ที่ใช้ template ได้ด้วย store ที่ค้นพบเหล่านั้นต้อง resolve เป็นไฟล์ `sessions.json` ปกติภายใน root ของ agent; symlink และเส้นทางนอก root จะถูกข้าม
|
||||
|
||||
ตัวอย่าง JSON:
|
||||
|
||||
@ -69,7 +71,7 @@ openclaw sessions export-trajectory --session-key "agent:main:telegram:direct:12
|
||||
|
||||
## การบำรุงรักษาเพื่อล้างข้อมูล
|
||||
|
||||
เรียกใช้การบำรุงรักษาตอนนี้ (แทนการรอรอบการเขียนถัดไป):
|
||||
เรียกใช้การบำรุงรักษาทันที (แทนที่จะรอรอบการเขียนถัดไป):
|
||||
|
||||
```bash
|
||||
openclaw sessions cleanup --dry-run
|
||||
@ -80,21 +82,21 @@ openclaw sessions cleanup --enforce --active-key "agent:main:telegram:direct:123
|
||||
openclaw sessions cleanup --json
|
||||
```
|
||||
|
||||
`openclaw sessions cleanup` ใช้การตั้งค่า `session.maintenance` จากการกำหนดค่า:
|
||||
`openclaw sessions cleanup` ใช้การตั้งค่า `session.maintenance` จาก config:
|
||||
|
||||
- หมายเหตุเรื่องขอบเขต: `openclaw sessions cleanup` ดูแลที่จัดเก็บเซสชัน transcript และ sidecar ของ trajectory โดยไม่ตัดทอนบันทึกการรัน Cron (`cron/runs/<jobId>.jsonl`) ซึ่งจัดการโดย `cron.runLog.maxBytes` และ `cron.runLog.keepLines` ใน [การกำหนดค่า Cron](/th/automation/cron-jobs#configuration) และอธิบายใน [การบำรุงรักษา Cron](/th/automation/cron-jobs#maintenance)
|
||||
- หมายเหตุเกี่ยวกับขอบเขต: `openclaw sessions cleanup` บำรุงรักษา session stores, transcripts และ trajectory sidecars คำสั่งนี้ไม่ตัดแต่ง cron run logs (`cron/runs/<jobId>.jsonl`) ซึ่งจัดการโดย `cron.runLog.maxBytes` และ `cron.runLog.keepLines` ใน [การกำหนดค่า Cron](/th/automation/cron-jobs#configuration) และอธิบายไว้ใน [การบำรุงรักษา Cron](/th/automation/cron-jobs#maintenance)
|
||||
|
||||
- `--dry-run`: ดูตัวอย่างจำนวนรายการที่จะถูกตัดทอน/จำกัดจำนวนโดยไม่เขียนข้อมูล
|
||||
- ในโหมดข้อความ dry-run จะพิมพ์ตารางการดำเนินการรายเซสชัน (`Action`, `Key`, `Age`, `Model`, `Flags`) เพื่อให้คุณเห็นว่าอะไรจะถูกเก็บไว้เทียบกับลบออก
|
||||
- `--enforce`: ใช้การบำรุงรักษาแม้เมื่อ `session.maintenance.mode` เป็น `warn`
|
||||
- `--fix-missing`: ลบรายการที่ไม่มีไฟล์ transcript แม้ว่าปกติรายการเหล่านั้นจะยังไม่ถูกคัดออกตามอายุ/จำนวนก็ตาม
|
||||
- `--active-key <key>`: ป้องกันคีย์ที่ใช้งานอยู่รายการใดรายการหนึ่งจากการถูกขับออกเพราะงบดิสก์ ตัวชี้การสนทนาภายนอกแบบคงทน เช่น เซสชันกลุ่มและเซสชันแชตที่ผูกกับเธรด จะถูกเก็บไว้โดยการบำรุงรักษาตามอายุ/จำนวน/งบดิสก์เช่นกัน
|
||||
- `--agent <id>`: เรียกใช้การล้างข้อมูลสำหรับที่จัดเก็บเอเจนต์ที่กำหนดค่าไว้หนึ่งรายการ
|
||||
- `--all-agents`: เรียกใช้การล้างข้อมูลสำหรับที่จัดเก็บเอเจนต์ที่กำหนดค่าไว้ทั้งหมด
|
||||
- `--dry-run`: แสดงตัวอย่างจำนวนรายการที่จะถูกตัดแต่ง/จำกัดโดยไม่เขียนข้อมูล
|
||||
- ในโหมดข้อความ dry-run จะพิมพ์ตารางการดำเนินการต่อเซสชัน (`Action`, `Key`, `Age`, `Model`, `Flags`) เพื่อให้คุณเห็นว่าสิ่งใดจะถูกเก็บไว้เทียบกับถูกลบออก
|
||||
- `--enforce`: ใช้การบำรุงรักษาแม้ว่า `session.maintenance.mode` จะเป็น `warn`
|
||||
- `--fix-missing`: ลบรายการที่ไม่มีไฟล์ transcript แม้ว่าปกติแล้วรายการเหล่านั้นจะยังไม่หมดอายุตามอายุ/จำนวนก็ตาม
|
||||
- `--active-key <key>`: ป้องกัน active key ที่ระบุจากการถูกขับออกเพราะงบดิสก์ ตัวชี้การสนทนาภายนอกแบบถาวร เช่น เซสชันกลุ่มและเซสชันแชทที่ผูกกับ thread จะถูกเก็บไว้โดยการบำรุงรักษาตามอายุ/จำนวน/งบดิสก์เช่นกัน
|
||||
- `--agent <id>`: เรียกใช้การล้างข้อมูลสำหรับ store ของ agent ที่กำหนดค่าไว้หนึ่งรายการ
|
||||
- `--all-agents`: เรียกใช้การล้างข้อมูลสำหรับ store ของ agent ที่กำหนดค่าไว้ทั้งหมด
|
||||
- `--store <path>`: เรียกใช้กับไฟล์ `sessions.json` ที่ระบุ
|
||||
- `--json`: พิมพ์สรุป JSON เมื่อใช้ร่วมกับ `--all-agents` เอาต์พุตจะรวมสรุปหนึ่งรายการต่อที่จัดเก็บ
|
||||
- `--json`: พิมพ์สรุป JSON เมื่อใช้ร่วมกับ `--all-agents` เอาต์พุตจะรวมสรุปหนึ่งรายการต่อ store
|
||||
|
||||
เมื่อ Gateway เข้าถึงได้ การล้างข้อมูลแบบไม่ใช่ dry-run สำหรับที่จัดเก็บเอเจนต์ที่กำหนดค่าไว้จะถูกส่งผ่าน Gateway เพื่อให้ใช้ตัวเขียนที่จัดเก็บเซสชันเดียวกับทราฟฟิกรันไทม์ ใช้ `--store <path>` สำหรับการซ่อมแซมไฟล์ที่จัดเก็บแบบออฟไลน์อย่างชัดเจน
|
||||
เมื่อ Gateway เข้าถึงได้ การล้างข้อมูลแบบไม่ใช่ dry-run สำหรับ store ของ agent ที่กำหนดค่าไว้จะถูกส่งผ่าน Gateway เพื่อให้ใช้ตัวเขียน session-store เดียวกับ traffic ขณะ runtime ใช้ `--store <path>` สำหรับการซ่อมแซมไฟล์ store แบบ offline ที่ระบุอย่างชัดเจน
|
||||
|
||||
`openclaw sessions cleanup --all-agents --dry-run --json`:
|
||||
|
||||
|
||||
@ -1,65 +1,65 @@
|
||||
---
|
||||
read_when:
|
||||
- การสร้างหรือเรียกใช้การตรวจสอบคุณภาพด้านภาพแบบสดสำหรับข้อบกพร่องของ OpenClaw
|
||||
- การสร้างหรือเรียกใช้การตรวจสอบคุณภาพเชิงภาพแบบสดสำหรับข้อบกพร่องของ OpenClaw
|
||||
- การเพิ่มการตรวจสอบก่อนและหลังสำหรับคำขอดึง
|
||||
- การเพิ่มสถานการณ์การรับส่งแบบสดสำหรับ Discord, Slack, WhatsApp หรืออื่นๆ
|
||||
- การดีบักการรัน QA ที่ต้องใช้ภาพหน้าจอ การทำงานอัตโนมัติของเบราว์เซอร์ หรือการเข้าถึง VNC
|
||||
summary: Mantis คือระบบตรวจสอบด้วยภาพแบบต้นทางถึงปลายทางสำหรับจำลองบั๊กของ OpenClaw ซ้ำบนทรานสปอร์ตที่ใช้งานจริง บันทึกหลักฐานก่อนและหลัง และแนบอาร์ติแฟกต์ไปยัง PR
|
||||
summary: Mantis คือระบบตรวจสอบแบบต้นทางถึงปลายทางเชิงภาพสำหรับจำลองบั๊กของ OpenClaw บนทรานสปอร์ตที่ใช้งานจริง เก็บหลักฐานก่อนและหลัง และแนบอาร์ติแฟกต์กับ PR
|
||||
title: ตั๊กแตนตำข้าว
|
||||
x-i18n:
|
||||
generated_at: "2026-05-04T02:23:26Z"
|
||||
generated_at: "2026-05-04T07:03:23Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 5a86ab4bc876d1c53ada1c30580034165f028194a072f559eb54a898a369211d
|
||||
source_hash: 9d3f3fa3db111b1b5c85f8efeccd749fbd5885cee6b7843ca4c8d049acfd9164
|
||||
source_path: concepts/mantis.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
Mantis คือระบบตรวจสอบแบบต้นทางถึงปลายทางของ OpenClaw สำหรับบั๊กที่ต้องใช้แรนไทม์จริง ทรานสปอร์ตจริง และหลักฐานที่มองเห็นได้ ระบบจะรันสถานการณ์กับ ref ที่ทราบว่ามีปัญหา เก็บหลักฐาน รันสถานการณ์เดียวกันกับ ref candidate แล้วเผยแพร่การเปรียบเทียบเป็นอาร์ติแฟกต์ที่ผู้ดูแลสามารถตรวจสอบได้จาก PR หรือจากคำสั่งภายในเครื่อง
|
||||
Mantis คือระบบตรวจสอบแบบ end-to-end ของ OpenClaw สำหรับบั๊กที่ต้องใช้ runtime จริง, transport จริง และหลักฐานที่มองเห็นได้ ระบบจะรัน scenario กับ ref ที่ทราบว่าเสีย, จับหลักฐาน, รัน scenario เดียวกันกับ ref ผู้สมัคร, แล้วเผยแพร่การเปรียบเทียบเป็นอาร์ติแฟกต์ที่ maintainer สามารถตรวจสอบได้จาก PR หรือจากคำสั่งภายในเครื่อง
|
||||
|
||||
Mantis เริ่มจาก Discord เพราะ Discord ให้เลนแรกที่มีคุณค่าสูงแก่เรา: การยืนยันตัวตนบอตจริง ช่องกิลด์จริง รีแอ็กชัน เธรด คำสั่งเนทีฟ และ UI บนเบราว์เซอร์ที่มนุษย์สามารถยืนยันด้วยสายตาได้ว่าทรานสปอร์ตแสดงอะไร
|
||||
Mantis เริ่มจาก Discord เพราะ Discord ให้ lane แรกที่มีคุณค่าสูงแก่เรา: การยืนยันตัวตนบอทจริง, ช่อง guild จริง, reaction, thread, คำสั่ง native และ UI บนเบราว์เซอร์ที่มนุษย์สามารถยืนยันด้วยสายตาได้ว่า transport แสดงอะไร
|
||||
|
||||
## เป้าหมาย
|
||||
|
||||
- ทำซ้ำบั๊กจาก issue หรือ PR บน GitHub ด้วยรูปแบบทรานสปอร์ตเดียวกับที่ผู้ใช้เห็น
|
||||
- เก็บอาร์ติแฟกต์ **ก่อน** บน ref พื้นฐานก่อนใช้การแก้ไข
|
||||
- เก็บอาร์ติแฟกต์ **หลัง** บน ref candidate หลังใช้การแก้ไข
|
||||
- ใช้ oracle แบบกำหนดแน่นอนเมื่อทำได้ เช่น การอ่านรีแอ็กชันผ่าน Discord REST หรือการตรวจทรานสคริปต์ของช่อง
|
||||
- เก็บภาพหน้าจอเมื่อบั๊กมีพื้นผิว UI ที่มองเห็นได้
|
||||
- จำลองบั๊กจาก GitHub issue หรือ PR ด้วยรูปแบบ transport เดียวกับที่ผู้ใช้เห็น
|
||||
- จับอาร์ติแฟกต์ **before** บน ref baseline ก่อนนำ fix มาใช้
|
||||
- จับอาร์ติแฟกต์ **after** บน ref ผู้สมัครหลังนำ fix มาใช้
|
||||
- ใช้ oracle แบบ deterministic เมื่อเป็นไปได้ เช่น การอ่าน reaction ผ่าน Discord REST หรือการตรวจสอบ transcript ของช่อง
|
||||
- จับภาพหน้าจอเมื่อบั๊กมีพื้นผิว UI ที่มองเห็นได้
|
||||
- รันภายในเครื่องจาก CLI ที่ agent ควบคุม และรันระยะไกลจาก GitHub
|
||||
- เก็บสถานะเครื่องให้เพียงพอสำหรับการกู้ผ่าน VNC เมื่อการเข้าสู่ระบบ ระบบอัตโนมัติของเบราว์เซอร์ หรือการยืนยันตัวตนของผู้ให้บริการติดขัด
|
||||
- โพสต์สถานะอย่างกระชับไปยังช่อง Discord ของโอเปอเรเตอร์เมื่อการรันถูกบล็อก ต้องการความช่วยเหลือผ่าน VNC แบบแมนนวล หรือเสร็จสิ้น
|
||||
- เก็บสถานะของเครื่องให้เพียงพอสำหรับการกู้ผ่าน VNC เมื่อการเข้าสู่ระบบ, การทำ browser automation หรือการยืนยันตัวตน provider ค้าง
|
||||
- โพสต์สถานะอย่างกระชับไปยังช่อง Discord สำหรับ operator เมื่อการรันถูกบล็อก, ต้องการความช่วยเหลือผ่าน VNC แบบแมนนวล หรือเสร็จสิ้น
|
||||
|
||||
## สิ่งที่ไม่ใช่เป้าหมาย
|
||||
|
||||
- Mantis ไม่ใช่สิ่งทดแทน unit test โดยปกติการรัน Mantis ควรถูกแปลงเป็น regression test ที่เล็กลงหลังจากเข้าใจการแก้ไขแล้ว
|
||||
- Mantis ไม่ใช่ gate CI ที่รวดเร็วตามปกติ ระบบนี้ช้ากว่า ใช้ข้อมูลประจำตัวจริง และสงวนไว้สำหรับบั๊กที่สภาพแวดล้อมจริงมีความสำคัญ
|
||||
- Mantis ไม่ควรต้องพึ่งมนุษย์ในการทำงานตามปกติ VNC แบบแมนนวลเป็นเส้นทางกู้คืน ไม่ใช่เส้นทางปกติ
|
||||
- Mantis ไม่เก็บความลับดิบไว้ในอาร์ติแฟกต์ ล็อก ภาพหน้าจอ รายงาน Markdown หรือคอมเมนต์ PR
|
||||
- Mantis ไม่ใช่สิ่งทดแทน unit tests โดยปกติการรัน Mantis ควรถูกเปลี่ยนเป็น regression test ที่เล็กลงหลังจากเข้าใจ fix แล้ว
|
||||
- Mantis ไม่ใช่ gate CI ที่เร็วตามปกติ มันช้ากว่า, ใช้ credentials จริง และสงวนไว้สำหรับบั๊กที่สภาพแวดล้อมจริงมีความสำคัญ
|
||||
- Mantis ไม่ควรต้องใช้มนุษย์สำหรับการทำงานปกติ VNC แบบแมนนวลเป็นเส้นทางกู้สถานการณ์ ไม่ใช่ happy path
|
||||
- Mantis ไม่เก็บ secrets ดิบในอาร์ติแฟกต์, logs, screenshots, รายงาน Markdown หรือความคิดเห็นใน PR
|
||||
|
||||
## ความเป็นเจ้าของ
|
||||
|
||||
Mantis อยู่ในสแต็ก QA ของ OpenClaw
|
||||
|
||||
- OpenClaw เป็นเจ้าของแรนไทม์สถานการณ์ อะแดปเตอร์ทรานสปอร์ต สคีมาหลักฐาน และ CLI ภายในเครื่องภายใต้ `pnpm openclaw qa mantis`
|
||||
- QA Lab เป็นเจ้าของชิ้นส่วนฮาร์เนสของทรานสปอร์ตจริง ตัวช่วยเก็บภาพเบราว์เซอร์ และตัวเขียนอาร์ติแฟกต์
|
||||
- Crabbox เป็นเจ้าของเครื่อง Linux ที่วอร์มไว้เมื่อจำเป็นต้องใช้ VM ระยะไกล
|
||||
- GitHub Actions เป็นเจ้าของจุดเข้าของเวิร์กโฟลว์ระยะไกลและการเก็บรักษาอาร์ติแฟกต์
|
||||
- ClawSweeper เป็นเจ้าของการกำหนดเส้นทางคอมเมนต์ GitHub: การแยกคำสั่งผู้ดูแล การ dispatch เวิร์กโฟลว์ และการโพสต์คอมเมนต์ PR สุดท้าย
|
||||
- agent ของ OpenClaw ขับเคลื่อน Mantis ผ่าน Codex เมื่อสถานการณ์ต้องการการตั้งค่าแบบ agentic การดีบัก หรือการรายงานสถานะค้าง
|
||||
- OpenClaw เป็นเจ้าของ scenario runtime, transport adapters, evidence schema และ CLI ภายในเครื่องภายใต้ `pnpm openclaw qa mantis`
|
||||
- QA Lab เป็นเจ้าของชิ้นส่วน live transport harness, ตัวช่วยจับภาพเบราว์เซอร์ และ artifact writers
|
||||
- Crabbox เป็นเจ้าของเครื่อง Linux ที่อุ่นไว้แล้วเมื่อจำเป็นต้องใช้ VM ระยะไกล
|
||||
- GitHub Actions เป็นเจ้าของ remote workflow entrypoint และการเก็บรักษาอาร์ติแฟกต์
|
||||
- ClawSweeper เป็นเจ้าของการ routing ความคิดเห็น GitHub: การ parse คำสั่ง maintainer, การ dispatch workflow และการโพสต์ความคิดเห็น PR สุดท้าย
|
||||
- OpenClaw agents ขับเคลื่อน Mantis ผ่าน Codex เมื่อ scenario ต้องมีการตั้งค่าแบบ agentic, การดีบัก หรือการรายงานสถานะค้าง
|
||||
|
||||
ขอบเขตนี้ทำให้ความรู้ด้านทรานสปอร์ตอยู่ใน OpenClaw การจัดกำหนดการเครื่องอยู่ใน Crabbox และกาวเชื่อมเวิร์กโฟลว์ผู้ดูแลอยู่ใน ClawSweeper
|
||||
ขอบเขตนี้ทำให้ความรู้เรื่อง transport อยู่ใน OpenClaw, การจัดตารางเครื่องอยู่ใน Crabbox และส่วนเชื่อม workflow ของ maintainer อยู่ใน ClawSweeper
|
||||
|
||||
## รูปแบบคำสั่ง
|
||||
|
||||
คำสั่งภายในเครื่องแรกตรวจสอบบอต Discord, กิลด์, ช่อง, การส่งข้อความ, การส่งรีแอ็กชัน และพาธอาร์ติแฟกต์:
|
||||
คำสั่งภายในเครื่องคำสั่งแรกตรวจสอบบอท Discord, guild, ช่อง, การส่งข้อความ, การส่ง reaction และ path ของอาร์ติแฟกต์:
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa mantis discord-smoke \
|
||||
--output-dir .artifacts/qa-e2e/mantis/discord-smoke
|
||||
```
|
||||
|
||||
ตัวรันก่อนและหลังภายในเครื่องรับรูปแบบนี้:
|
||||
runner before และ after ภายในเครื่องรับรูปแบบนี้:
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa mantis run \
|
||||
@ -70,7 +70,7 @@ pnpm openclaw qa mantis run \
|
||||
--output-dir .artifacts/qa-e2e/mantis/local-discord-status-reactions
|
||||
```
|
||||
|
||||
ตัวรันสร้าง worktree แบบ detached สำหรับ baseline และ candidate ภายใต้ไดเรกทอรีเอาต์พุต ติดตั้ง dependency บิลด์แต่ละ ref รันสถานการณ์ด้วย `--allow-failures` จากนั้นเขียน `baseline/`, `candidate/`, `comparison.json` และ `mantis-report.md` สำหรับสถานการณ์ Discord แรก การตรวจสอบที่สำเร็จหมายความว่าสถานะ baseline คือ `fail` และสถานะ candidate คือ `pass`
|
||||
runner สร้าง worktree ของ baseline และ candidate แบบ detached ภายใต้ไดเรกทอรี output, ติดตั้ง dependencies, build แต่ละ ref, รัน scenario ด้วย `--allow-failures` แล้วเขียน `baseline/`, `candidate/`, `comparison.json` และ `mantis-report.md` สำหรับ scenario Discord แรก การตรวจสอบที่สำเร็จหมายความว่าสถานะ baseline คือ `fail` และสถานะ candidate คือ `pass`
|
||||
|
||||
primitive แรกของ VM/เบราว์เซอร์คือ desktop smoke:
|
||||
|
||||
@ -79,30 +79,62 @@ pnpm openclaw qa mantis desktop-browser-smoke \
|
||||
--output-dir .artifacts/qa-e2e/mantis/desktop-browser
|
||||
```
|
||||
|
||||
คำสั่งนี้เช่าหรือนำเครื่องเดสก์ท็อป Crabbox มาใช้ซ้ำ เริ่มเบราว์เซอร์ที่มองเห็นได้ภายในเซสชัน VNC เก็บภาพเดสก์ท็อป ดึงอาร์ติแฟกต์กลับมายังไดเรกทอรีเอาต์พุตภายในเครื่อง และเขียนคำสั่งเชื่อมต่อใหม่ลงในรายงาน คำสั่งตั้งค่าเริ่มต้นเป็นผู้ให้บริการ Hetzner เพราะเป็นผู้ให้บริการรายแรกที่มี desktop/VNC coverage ที่ทำงานได้ในเลน Mantis แทนที่ได้ด้วย `--provider`, `--crabbox-bin` หรือ `OPENCLAW_MANTIS_CRABBOX_PROVIDER` เมื่อรันกับฟลีต Crabbox อื่น
|
||||
คำสั่งนี้เช่าหรือใช้เครื่องเดสก์ท็อป Crabbox ซ้ำ, เริ่มเบราว์เซอร์ที่มองเห็นได้ภายใน session VNC, จับภาพเดสก์ท็อป, ดึงอาร์ติแฟกต์กลับมายังไดเรกทอรี output ภายในเครื่อง และเขียนคำสั่ง reconnect ลงในรายงาน คำสั่งตั้งค่าเริ่มต้นเป็น provider Hetzner เพราะเป็น provider แรกที่มี coverage เดสก์ท็อป/VNC ใช้งานได้ใน lane ของ Mantis override ได้ด้วย `--provider`, `--crabbox-bin` หรือ `OPENCLAW_MANTIS_CRABBOX_PROVIDER` เมื่อรันกับ fleet Crabbox อื่น
|
||||
|
||||
แฟล็ก desktop smoke ที่มีประโยชน์:
|
||||
flags ที่มีประโยชน์สำหรับ desktop smoke:
|
||||
|
||||
- `--lease-id <cbx_...>` หรือ `OPENCLAW_MANTIS_CRABBOX_LEASE_ID` นำเดสก์ท็อปที่วอร์มไว้มาใช้ซ้ำ
|
||||
- `--lease-id <cbx_...>` หรือ `OPENCLAW_MANTIS_CRABBOX_LEASE_ID` ใช้เดสก์ท็อปที่อุ่นไว้แล้วซ้ำ
|
||||
- `--browser-url <url>` เปลี่ยนหน้าที่เปิดในเบราว์เซอร์ที่มองเห็นได้
|
||||
- `--html-file <path>` เรนเดอร์อาร์ติแฟกต์ HTML ภายใน repo ในเบราว์เซอร์ที่มองเห็นได้ Mantis ใช้สิ่งนี้เพื่อเก็บภาพไทม์ไลน์ Discord status-reaction ที่สร้างขึ้นผ่านเดสก์ท็อป Crabbox จริง
|
||||
- `--keep-lease` หรือ `OPENCLAW_MANTIS_KEEP_VM=1` คง lease ที่สร้างใหม่และผ่านไว้สำหรับการตรวจสอบผ่าน VNC การรันที่ล้มเหลวจะคง lease ไว้ตามค่าเริ่มต้นเมื่อมีการสร้าง lease เพื่อให้โอเปอเรเตอร์เชื่อมต่อใหม่ได้
|
||||
- `--html-file <path>` render อาร์ติแฟกต์ HTML ภายใน repo ในเบราว์เซอร์ที่มองเห็นได้ Mantis ใช้สิ่งนี้เพื่อจับ timeline reaction สถานะ Discord ที่สร้างขึ้นผ่านเดสก์ท็อป Crabbox จริง
|
||||
- `--keep-lease` หรือ `OPENCLAW_MANTIS_KEEP_VM=1` คง lease ที่สร้างใหม่และผ่านไว้เปิดอยู่สำหรับการตรวจสอบผ่าน VNC การรันที่ล้มเหลวจะคง lease ไว้โดยค่าเริ่มต้นเมื่อมีการสร้าง lease เพื่อให้ operator reconnect ได้
|
||||
- `--class`, `--idle-timeout` และ `--ttl` ปรับขนาดเครื่องและอายุของ lease
|
||||
|
||||
เวิร์กโฟลว์ smoke บน GitHub คือ `Mantis Discord Smoke` เวิร์กโฟลว์ก่อนและหลังบน GitHub สำหรับสถานการณ์จริงแรกคือ `Mantis Discord Status Reactions` โดยรับ:
|
||||
primitive transport เดสก์ท็อปแบบเต็มตัวแรกคือ Slack desktop smoke:
|
||||
|
||||
- `baseline_ref`: ref ที่คาดว่าจะทำซ้ำพฤติกรรม queued-only
|
||||
```bash
|
||||
pnpm openclaw qa mantis slack-desktop-smoke \
|
||||
--output-dir .artifacts/qa-e2e/mantis/slack-desktop \
|
||||
--gateway-setup \
|
||||
--scenario slack-canary \
|
||||
--keep-lease
|
||||
```
|
||||
|
||||
คำสั่งนี้เช่าหรือใช้เครื่องเดสก์ท็อป Crabbox ซ้ำ, sync checkout ปัจจุบันเข้าไปใน VM, รัน `pnpm openclaw qa slack` ภายใน VM นั้น, เปิด Slack Web ในเบราว์เซอร์ VNC, จับภาพเดสก์ท็อปที่มองเห็นได้ และคัดลอกทั้งอาร์ติแฟกต์ Slack QA และ screenshot VNC กลับมายังไดเรกทอรี output ภายในเครื่อง นี่เป็นรูปแบบ Mantis แรกที่ทั้ง SUT OpenClaw gateway และเบราว์เซอร์อยู่ภายใน Linux desktop VM เดียวกัน
|
||||
|
||||
เมื่อใช้ `--gateway-setup` คำสั่งจะเตรียม home ของ OpenClaw แบบ disposable ที่คงอยู่ที่ `$HOME/.openclaw-mantis/slack-openclaw`, patch การกำหนดค่า Slack Socket Mode สำหรับช่องที่เลือก, เริ่ม `openclaw gateway run` บน port `38973` และคง Chrome ให้รันอยู่ใน session VNC นี่คือโหมด "ปล่อยเดสก์ท็อป Linux ที่มี Slack และ claw กำลังรันไว้ให้ฉัน"; lane Slack QA แบบ bot-to-bot ยังคงเป็นค่าเริ่มต้นเมื่อไม่ได้ระบุ `--gateway-setup`
|
||||
|
||||
inputs ที่จำเป็นสำหรับ `--credential-source env`:
|
||||
|
||||
- `OPENCLAW_QA_SLACK_CHANNEL_ID`
|
||||
- `OPENCLAW_QA_SLACK_DRIVER_BOT_TOKEN`
|
||||
- `OPENCLAW_QA_SLACK_SUT_BOT_TOKEN`
|
||||
- `OPENCLAW_QA_SLACK_SUT_APP_TOKEN`
|
||||
- `OPENCLAW_LIVE_OPENAI_KEY` สำหรับ lane model ระยะไกล หากตั้งค่าเฉพาะ `OPENAI_API_KEY` ภายในเครื่อง Mantis จะ map ไปเป็น `OPENCLAW_LIVE_OPENAI_KEY` ก่อนเรียกใช้ Crabbox เพื่อให้การส่งต่อ env `OPENCLAW_*` ของ Crabbox พาเข้าไปใน VM ได้
|
||||
|
||||
flags Slack desktop ที่มีประโยชน์:
|
||||
|
||||
- `--lease-id <cbx_...>` รันซ้ำกับเครื่องที่ operator ได้เข้าสู่ระบบ Slack Web ผ่าน VNC ไว้แล้ว
|
||||
- `--gateway-setup` เริ่ม OpenClaw Slack gateway แบบ persistent ใน VM แทนที่จะรันเฉพาะ lane QA แบบ bot-to-bot
|
||||
- `--slack-url <url>` เปิด Slack Web URL เฉพาะ หากไม่มี Mantis จะ derive `https://app.slack.com/client/<team>/<channel>` จาก Slack `auth.test` เมื่อมี token บอท SUT
|
||||
- `--slack-channel-id <id>` ควบคุม allowlist ของช่อง Slack ที่ใช้โดย gateway setup
|
||||
- `OPENCLAW_MANTIS_SLACK_BROWSER_PROFILE_DIR` ควบคุมโปรไฟล์ Chrome แบบ persistent ภายใน VM ค่าเริ่มต้นคือ `$HOME/.config/openclaw-mantis/slack-chrome-profile` ดังนั้นการเข้าสู่ระบบ Slack Web แบบแมนนวลจะอยู่รอดในการรันซ้ำบน lease เดียวกัน
|
||||
- `--credential-source convex --credential-role ci` ใช้ shared credential pool แทน Slack env tokens โดยตรง
|
||||
- `--provider-mode`, `--model`, `--alt-model` และ `--fast` ส่งผ่านไปยัง Slack live lane
|
||||
|
||||
workflow smoke ของ GitHub คือ `Mantis Discord Smoke` workflow before และ after ของ GitHub สำหรับ scenario จริงแรกคือ `Mantis Discord Status Reactions` โดยรับ:
|
||||
|
||||
- `baseline_ref`: ref ที่คาดว่าจะจำลองพฤติกรรม queued-only ได้
|
||||
- `candidate_ref`: ref ที่คาดว่าจะแสดง `queued -> thinking -> done`
|
||||
|
||||
เวิร์กโฟลว์ checkout ref ของฮาร์เนสเวิร์กโฟลว์ บิลด์ worktree baseline และ candidate แยกกัน รัน `discord-status-reactions-tool-only` กับแต่ละ worktree และอัปโหลด `baseline/`, `candidate/`, `comparison.json` และ `mantis-report.md` เป็นอาร์ติแฟกต์ของ Actions นอกจากนี้ยังเรนเดอร์ HTML ไทม์ไลน์ของแต่ละเลนในเบราว์เซอร์เดสก์ท็อป Crabbox และเผยแพร่ภาพหน้าจอ VNC เหล่านั้นคู่กับ PNG ไทม์ไลน์แบบกำหนดแน่นอนในคอมเมนต์ PR เวิร์กโฟลว์บิลด์ Crabbox CLI จาก `openclaw/crabbox` main เพื่อให้ใช้แฟล็ก desktop/browser lease ปัจจุบันได้ก่อนที่จะตัด release ไบนารี Crabbox ถัดไป
|
||||
มัน checkout ref ของ workflow harness, build worktree baseline และ candidate แยกกัน, รัน `discord-status-reactions-tool-only` กับแต่ละ worktree และ upload `baseline/`, `candidate/`, `comparison.json` และ `mantis-report.md` เป็นอาร์ติแฟกต์ Actions นอกจากนี้ยัง render timeline HTML ของแต่ละ lane ในเบราว์เซอร์เดสก์ท็อป Crabbox และเผยแพร่ screenshot VNC เหล่านั้นไว้ข้าง PNG timeline แบบ deterministic ในความคิดเห็น PR workflow นี้ build Crabbox CLI จาก `openclaw/crabbox` main เพื่อให้สามารถใช้ flags lease เดสก์ท็อป/เบราว์เซอร์ปัจจุบันก่อนที่จะตัด release binary Crabbox ถัดไป
|
||||
|
||||
คุณยังสามารถทริกเกอร์การรัน status-reactions โดยตรงจากคอมเมนต์ PR:
|
||||
คุณยังสามารถ trigger การรัน status-reactions ได้โดยตรงจากความคิดเห็นใน PR:
|
||||
|
||||
```text
|
||||
@Mantis discord status reactions
|
||||
```
|
||||
|
||||
ทริกเกอร์คอมเมนต์นี้ตั้งใจให้แคบ โดยจะรันเฉพาะบนคอมเมนต์ pull request จากผู้ใช้ที่มีสิทธิ์ write, maintain หรือ admin และจะรู้จักเฉพาะคำขอ Discord status-reaction เท่านั้น ตามค่าเริ่มต้นจะใช้ ref พื้นฐานที่ทราบว่ามีปัญหาและ SHA ของหัว PR ปัจจุบันเป็น candidate ผู้ดูแลสามารถแทนที่ ref ใดก็ได้:
|
||||
comment trigger นี้จงใจจำกัดขอบเขต มันรันเฉพาะบนความคิดเห็น pull request จากผู้ใช้ที่มีสิทธิ์ write, maintain หรือ admin และรู้จักเฉพาะคำขอ status-reaction ของ Discord โดยค่าเริ่มต้นจะใช้ ref baseline ที่ทราบว่าเสีย และ SHA head ของ PR ปัจจุบันเป็น candidate Maintainers สามารถ override ref ใดก็ได้:
|
||||
|
||||
```text
|
||||
@Mantis discord status reactions baseline=origin/main candidate=HEAD
|
||||
@ -115,45 +147,45 @@ pnpm openclaw qa mantis desktop-browser-smoke \
|
||||
@clawsweeper verify e2e discord
|
||||
```
|
||||
|
||||
คำสั่งแรกระบุชัดเจนและมุ่งเน้นสถานการณ์ คำสั่งที่สองสามารถแมป PR หรือ issue ไปยังสถานการณ์ Mantis ที่แนะนำได้ในภายหลังจากป้ายกำกับ ไฟล์ที่เปลี่ยน และข้อค้นพบจากรีวิวของ ClawSweeper
|
||||
คำสั่งแรกเป็นคำสั่งแบบ explicit และเน้น scenario คำสั่งที่สองภายหลังสามารถ map PR หรือ issue ไปยัง scenario Mantis ที่แนะนำจาก labels, ไฟล์ที่เปลี่ยน และ findings จากการ review ของ ClawSweeper
|
||||
|
||||
## วงจรชีวิตการรัน
|
||||
## วงจรการรัน
|
||||
|
||||
1. รับข้อมูลประจำตัว
|
||||
2. จัดสรรหรือนำ VM มาใช้ซ้ำ
|
||||
3. เตรียมโปรไฟล์เดสก์ท็อป/เบราว์เซอร์เมื่อสถานการณ์ต้องการหลักฐาน UI
|
||||
4. เตรียม checkout ที่สะอาดสำหรับ ref พื้นฐาน
|
||||
5. ติดตั้ง dependency และบิลด์เฉพาะสิ่งที่สถานการณ์ต้องใช้
|
||||
6. เริ่ม OpenClaw Gateway ลูกด้วยไดเรกทอรีสถานะแบบแยก
|
||||
7. กำหนดค่าทรานสปอร์ตจริง ผู้ให้บริการ โมเดล และโปรไฟล์เบราว์เซอร์
|
||||
8. รันสถานการณ์และเก็บหลักฐาน baseline
|
||||
9. หยุด gateway และเก็บรักษาล็อก
|
||||
1. ดึง credentials
|
||||
2. จัดสรรหรือใช้ VM ซ้ำ
|
||||
3. เตรียมโปรไฟล์เดสก์ท็อป/เบราว์เซอร์เมื่อ scenario ต้องการหลักฐาน UI
|
||||
4. เตรียม checkout ที่สะอาดสำหรับ ref baseline
|
||||
5. ติดตั้ง dependencies และ build เฉพาะสิ่งที่ scenario ต้องใช้
|
||||
6. เริ่ม child OpenClaw Gateway ด้วยไดเรกทอรีสถานะแบบ isolated
|
||||
7. กำหนดค่า live transport, provider, model และโปรไฟล์เบราว์เซอร์
|
||||
8. รัน scenario และจับหลักฐาน baseline
|
||||
9. หยุด gateway และเก็บ logs ไว้
|
||||
10. เตรียม ref candidate ใน VM เดียวกัน
|
||||
11. รันสถานการณ์เดียวกันและเก็บหลักฐาน candidate
|
||||
12. เปรียบเทียบผลลัพธ์ oracle และหลักฐานภาพ
|
||||
13. เขียน Markdown, JSON, ล็อก, ภาพหน้าจอ และอาร์ติแฟกต์ trace ที่เป็นตัวเลือก
|
||||
14. อัปโหลดอาร์ติแฟกต์ GitHub Actions
|
||||
15. โพสต์ข้อความสถานะ PR หรือ Discord แบบกระชับ
|
||||
11. รัน scenario เดียวกันและจับหลักฐาน candidate
|
||||
12. เปรียบเทียบผล oracle และหลักฐานภาพ
|
||||
13. เขียน Markdown, JSON, logs, screenshots และอาร์ติแฟกต์ trace แบบ optional
|
||||
14. Upload อาร์ติแฟกต์ GitHub Actions
|
||||
15. โพสต์ข้อความสถานะ PR หรือ Discord อย่างกระชับ
|
||||
|
||||
สถานการณ์ควรล้มเหลวได้สองแบบที่แตกต่างกัน:
|
||||
scenario ควรสามารถล้มเหลวได้สองแบบที่ต่างกัน:
|
||||
|
||||
- **ทำซ้ำบั๊กได้**: baseline ล้มเหลวในแบบที่คาดไว้
|
||||
- **ฮาร์เนสล้มเหลว**: การตั้งค่าสภาพแวดล้อม ข้อมูลประจำตัว Discord API เบราว์เซอร์ หรือผู้ให้บริการล้มเหลวก่อนที่ bug oracle จะมีความหมาย
|
||||
- **จำลองบั๊กได้แล้ว**: baseline ล้มเหลวในลักษณะที่คาดไว้
|
||||
- **Harness failure**: การตั้งค่าสภาพแวดล้อม, credentials, Discord API, เบราว์เซอร์ หรือ provider ล้มเหลวก่อนที่ bug oracle จะมีความหมาย
|
||||
|
||||
รายงานสุดท้ายต้องแยกกรณีเหล่านี้เพื่อให้ผู้ดูแลไม่สับสนระหว่างสภาพแวดล้อมที่ไม่นิ่งกับพฤติกรรมของผลิตภัณฑ์
|
||||
รายงานสุดท้ายต้องแยกกรณีเหล่านี้ออกจากกัน เพื่อให้ maintainers ไม่สับสนระหว่างสภาพแวดล้อมที่ flaky กับพฤติกรรมของผลิตภัณฑ์
|
||||
|
||||
## MVP ของ Discord
|
||||
## Discord MVP
|
||||
|
||||
สถานการณ์แรกควรมุ่งเป้าไปที่ Discord status reactions ในช่องกิลด์ที่โหมดส่ง reply ต้นทางคือ `message_tool_only`
|
||||
scenario แรกควร target status reactions ของ Discord ในช่อง guild ที่ source reply delivery mode เป็น `message_tool_only`
|
||||
|
||||
เหตุผลที่เป็น seed ที่ดีสำหรับ Mantis:
|
||||
เหตุผลที่เป็น seed ของ Mantis ที่ดี:
|
||||
|
||||
- มองเห็นได้ใน Discord เป็นรีแอ็กชันบนข้อความที่ทริกเกอร์
|
||||
- มี REST oracle ที่แข็งแรงผ่านสถานะรีแอ็กชันของข้อความ Discord
|
||||
- ครอบคลุม OpenClaw Gateway จริง การยืนยันตัวตนบอต Discord การ dispatch ข้อความ โหมดส่ง reply ต้นทาง สถานะรีแอ็กชัน และวงจรชีวิต turn ของโมเดล
|
||||
- แคบพอที่จะทำให้การติดตั้งใช้งานครั้งแรกตรงไปตรงมา
|
||||
- มองเห็นได้ใน Discord เป็น reactions บนข้อความที่ trigger
|
||||
- มี REST oracle ที่แข็งแรงผ่านสถานะ reaction ของข้อความ Discord
|
||||
- ทดสอบ OpenClaw Gateway จริง, การยืนยันตัวตนบอท Discord, การ dispatch ข้อความ, source reply delivery mode, สถานะ status reaction และวงจรชีวิต model turn
|
||||
- แคบพอที่จะทำให้การ implement แรกซื่อตรงต่อเป้าหมาย
|
||||
|
||||
รูปแบบสถานการณ์ที่คาดไว้:
|
||||
รูปแบบ scenario ที่คาดไว้:
|
||||
|
||||
```yaml
|
||||
id: discord-status-reactions-tool-only
|
||||
@ -184,9 +216,9 @@ evidence:
|
||||
screenshotMessageRow: true
|
||||
```
|
||||
|
||||
หลักฐาน baseline ควรแสดงรีแอ็กชัน acknowledgement แบบ queued แต่ไม่มี lifecycle transition ในโหมด tool-only หลักฐาน candidate ควรแสดง lifecycle status reactions ที่ทำงานเมื่อ `messages.statusReactions.enabled` เป็น true อย่างชัดเจน
|
||||
หลักฐาน baseline ควรแสดง acknowledgement reaction แบบ queued แต่ไม่มี lifecycle transition ในโหมด tool-only หลักฐาน candidate ควรแสดง lifecycle status reactions ที่ทำงานเมื่อ `messages.statusReactions.enabled` เป็น true อย่าง explicit
|
||||
|
||||
slice แรกที่รันได้คือสถานการณ์ QA จริงของ Discord แบบ opt-in:
|
||||
slice แรกที่ executable คือ scenario Discord live QA แบบ opt-in:
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa discord \
|
||||
@ -198,24 +230,34 @@ pnpm openclaw qa discord \
|
||||
--output-dir .artifacts/qa-e2e/mantis/discord-status-reactions-candidate
|
||||
```
|
||||
|
||||
คำสั่งนี้กำหนดค่า SUT ให้จัดการกิลด์แบบเปิดตลอด, `visibleReplies:
|
||||
"message_tool"`, `ackReaction: "👀"` และ status reactions ที่ระบุชัดเจน oracle จะ poll ข้อความ Discord ที่ทริกเกอร์จริงและคาดหวังลำดับที่สังเกตได้คือ `👀 -> 🤔 -> 👍` อาร์ติแฟกต์ประกอบด้วย `discord-qa-reaction-timelines.json`, `discord-status-reactions-tool-only-timeline.html` และ `discord-status-reactions-tool-only-timeline.png`
|
||||
กำหนดค่า SUT ให้เปิดการจัดการกิลด์ตลอดเวลา, `visibleReplies:
|
||||
"message_tool"`, `ackReaction: "👀"` และรีแอ็กชันสถานะแบบชัดเจน oracle
|
||||
จะโพลข้อความกระตุ้นจริงใน Discord และคาดหวังลำดับที่สังเกตได้
|
||||
`👀 -> 🤔 -> 👍` artifact ประกอบด้วย `discord-qa-reaction-timelines.json`,
|
||||
`discord-status-reactions-tool-only-timeline.html` และ
|
||||
`discord-status-reactions-tool-only-timeline.png`
|
||||
|
||||
## ส่วนประกอบ QA ที่มีอยู่
|
||||
## ชิ้นส่วน QA ที่มีอยู่
|
||||
|
||||
Mantis ควรต่อยอดจากสแต็ก QA ส่วนตัวที่มีอยู่แทนที่จะเริ่มจากศูนย์:
|
||||
Mantis ควรต่อยอดจาก private QA stack ที่มีอยู่ แทนที่จะเริ่มจาก
|
||||
ศูนย์:
|
||||
|
||||
- `pnpm openclaw qa discord` รันเลน Discord จริงพร้อมบอต driver และ SUT อยู่แล้ว
|
||||
- ตัวรันทรานสปอร์ตจริงเขียนรายงานและอาร์ติแฟกต์ observed-message ภายใต้ `.artifacts/qa-e2e/` อยู่แล้ว
|
||||
- lease ข้อมูลประจำตัว Convex ให้สิทธิ์เข้าถึงข้อมูลประจำตัวทรานสปอร์ตจริงที่ใช้ร่วมกันแบบเอกสิทธิ์อยู่แล้ว
|
||||
- บริการควบคุมเบราว์เซอร์รองรับภาพหน้าจอ สแนปช็อต โปรไฟล์ managed แบบ headless และโปรไฟล์ CDP ระยะไกลอยู่แล้ว
|
||||
- QA Lab มี UI ดีบักเกอร์และ bus สำหรับการทดสอบที่มีรูปแบบเหมือนทรานสปอร์ตอยู่แล้ว
|
||||
- `pnpm openclaw qa discord` รันเลน Discord แบบ live พร้อมบอต driver และ
|
||||
SUT อยู่แล้ว
|
||||
- live transport runner เขียนรายงานและ artifact ของข้อความที่สังเกตได้
|
||||
ไว้ใต้ `.artifacts/qa-e2e/` อยู่แล้ว
|
||||
- lease ของข้อมูลรับรอง Convex ให้สิทธิ์เข้าถึงแบบเอกสิทธิ์แก่ข้อมูลรับรอง live
|
||||
transport ที่ใช้ร่วมกันอยู่แล้ว
|
||||
- browser control service รองรับ screenshot, snapshot,
|
||||
โปรไฟล์ managed แบบ headless และโปรไฟล์ CDP ระยะไกลอยู่แล้ว
|
||||
- QA Lab มี debugger UI และ bus สำหรับการทดสอบรูปทรง transport อยู่แล้ว
|
||||
|
||||
การติดตั้ง Mantis ครั้งแรกสามารถเป็นตัวรันก่อน/หลังแบบบางบนชิ้นส่วนเหล่านี้ พร้อมชั้นหลักฐานภาพหนึ่งชั้น
|
||||
การใช้งาน Mantis ระยะแรกสามารถเป็น runner แบบ thin ก่อน/หลังครอบชิ้นส่วนเหล่านี้
|
||||
พร้อมชั้นหลักฐานภาพหนึ่งชั้น
|
||||
|
||||
## โมเดลหลักฐาน
|
||||
|
||||
ทุกการรันเขียนไดเรกทอรีอาร์ติแฟกต์ที่เสถียร:
|
||||
ทุกการรันเขียนไดเรกทอรี artifact ที่เสถียร:
|
||||
|
||||
```text
|
||||
.artifacts/qa-e2e/mantis/<run-id>/
|
||||
@ -235,73 +277,79 @@ Mantis ควรต่อยอดจากสแต็ก QA ส่วนตั
|
||||
run.log
|
||||
```
|
||||
|
||||
`mantis-summary.json` ควรเป็นแหล่งความจริงที่เครื่องอ่านได้ รายงาน Markdown ใช้สำหรับคอมเมนต์ PR และการรีวิวโดยมนุษย์
|
||||
`mantis-summary.json` ควรเป็นแหล่งข้อมูลจริงที่เครื่องอ่านได้
|
||||
รายงาน Markdown มีไว้สำหรับคอมเมนต์ PR และการตรวจทานโดยมนุษย์
|
||||
|
||||
summary ต้องมี:
|
||||
สรุปต้องประกอบด้วย:
|
||||
|
||||
- ref และ SHA ที่ทดสอบ
|
||||
- ทรานสปอร์ตและรหัสสถานการณ์
|
||||
- ผู้ให้บริการเครื่องและรหัสเครื่องหรือรหัส lease
|
||||
- แหล่งข้อมูลประจำตัวโดยไม่มีค่าความลับ
|
||||
- transport และ scenario id
|
||||
- ผู้ให้บริการเครื่องและ machine id หรือ lease id
|
||||
- แหล่งข้อมูลรับรองโดยไม่มีค่าลับ
|
||||
- ผลลัพธ์ baseline
|
||||
- ผลลัพธ์ candidate
|
||||
- บั๊กถูกทำซ้ำบน baseline หรือไม่
|
||||
- บั๊กเกิดซ้ำบน baseline หรือไม่
|
||||
- candidate แก้ไขได้หรือไม่
|
||||
- พาธอาร์ติแฟกต์
|
||||
- path ของ artifact
|
||||
- ปัญหาการตั้งค่าหรือการล้างข้อมูลที่ผ่านการทำให้ปลอดภัยแล้ว
|
||||
|
||||
ภาพหน้าจอคือหลักฐาน ไม่ใช่ความลับ แต่ยังต้องมีวินัยด้านการ redact: ชื่อช่องส่วนตัว ชื่อผู้ใช้ หรือเนื้อหาข้อความอาจปรากฏ สำหรับ PR สาธารณะ ให้ใช้ลิงก์อาร์ติแฟกต์ GitHub Actions แทนภาพ inline จนกว่าเรื่องการ redact จะแข็งแรงขึ้น
|
||||
Screenshot เป็นหลักฐาน ไม่ใช่ secret แต่ยังต้องมีวินัยในการ redaction:
|
||||
ชื่อช่องส่วนตัว ชื่อผู้ใช้ หรือเนื้อหาข้อความอาจปรากฏได้ สำหรับ PR สาธารณะ
|
||||
ควรใช้ลิงก์ artifact ของ GitHub Actions แทนรูปภาพแบบ inline จนกว่าเรื่อง
|
||||
redaction จะแข็งแรงขึ้น
|
||||
|
||||
## เบราว์เซอร์และ VNC
|
||||
|
||||
เลนเบราว์เซอร์มีสองโหมด:
|
||||
|
||||
- **ระบบอัตโนมัติแบบ headless**: ค่าเริ่มต้นสำหรับ CI Chrome รันโดยเปิด CDP และ Playwright หรือการควบคุมเบราว์เซอร์ของ OpenClaw จะเก็บภาพหน้าจอ
|
||||
- **การกู้ผ่าน VNC**: เปิดใช้บน VM เดียวกันเมื่อการเข้าสู่ระบบ MFA ระบบป้องกันอัตโนมัติของ Discord หรือการดีบักภาพต้องใช้มนุษย์
|
||||
- **การทำงานอัตโนมัติแบบ headless**: ค่าเริ่มต้นสำหรับ CI Chrome รันโดยเปิดใช้ CDP
|
||||
และ Playwright หรือ browser control ของ OpenClaw จับภาพ screenshot
|
||||
- **การกู้สถานการณ์ด้วย VNC**: เปิดใช้บน VM เดียวกันเมื่อ login, MFA,
|
||||
การป้องกัน automation ของ Discord หรือการ debug ด้วยภาพต้องใช้มนุษย์
|
||||
|
||||
โปรไฟล์เบราว์เซอร์ผู้สังเกตการณ์ Discord ควรคงอยู่เพียงพอเพื่อหลีกเลี่ยง
|
||||
การเข้าสู่ระบบทุกครั้งที่รัน แต่ต้องแยกจากสถานะเบราว์เซอร์ส่วนตัว โปรไฟล์
|
||||
เป็นของพูลเครื่อง Mantis ไม่ใช่แล็ปท็อปของนักพัฒนา
|
||||
โปรไฟล์เบราว์เซอร์ผู้สังเกตการณ์ Discord ควรมี persistence พอที่จะหลีกเลี่ยง
|
||||
การ login ทุกการรัน แต่แยกจากสถานะเบราว์เซอร์ส่วนตัว โปรไฟล์เป็นของพูลเครื่อง
|
||||
Mantis ไม่ใช่ของแล็ปท็อปนักพัฒนา
|
||||
|
||||
เมื่อ Mantis ติดขัด ระบบจะโพสต์ข้อความสถานะ Discord พร้อมข้อมูลต่อไปนี้:
|
||||
เมื่อ Mantis ติดขัด จะโพสต์ข้อความสถานะ Discord พร้อม:
|
||||
|
||||
- id การรัน
|
||||
- id สถานการณ์
|
||||
- run id
|
||||
- scenario id
|
||||
- ผู้ให้บริการเครื่อง
|
||||
- ไดเรกทอรีอาร์ติแฟกต์
|
||||
- ไดเรกทอรี artifact
|
||||
- คำแนะนำการเชื่อมต่อ VNC หรือ noVNC หากมี
|
||||
- ข้อความตัวบล็อกสั้น ๆ
|
||||
- ข้อความ blocker แบบสั้น
|
||||
|
||||
การปรับใช้แบบส่วนตัวครั้งแรกสามารถโพสต์ข้อความเหล่านี้ไปยังช่องผู้ปฏิบัติงาน
|
||||
ที่มีอยู่ แล้วค่อยย้ายไปยังช่อง Mantis เฉพาะในภายหลัง
|
||||
การ deploy แบบ private ครั้งแรกสามารถโพสต์ข้อความเหล่านี้ไปยังช่อง operator
|
||||
ที่มีอยู่ แล้วค่อยย้ายไปช่อง Mantis เฉพาะในภายหลัง
|
||||
|
||||
## เครื่อง
|
||||
|
||||
Mantis ควรเลือกใช้ AWS ผ่าน Crabbox สำหรับการใช้งานระยะไกลครั้งแรก
|
||||
Crabbox ให้เครื่องที่อุ่นไว้แล้ว การติดตามสัญญาเช่า การเติมสภาพแวดล้อม ล็อก ผลลัพธ์ และ
|
||||
การทำความสะอาด หากความจุของ AWS ช้าเกินไปหรือไม่พร้อมใช้งาน ให้เพิ่มผู้ให้บริการ Hetzner
|
||||
ไว้หลังอินเทอร์เฟซเครื่องเดียวกัน
|
||||
Mantis ควรเลือกใช้ AWS ผ่าน Crabbox สำหรับ remote implementation ระยะแรก
|
||||
Crabbox ให้เครื่องที่อุ่นไว้แล้ว, การติดตาม lease, hydration, log, ผลลัพธ์ และ
|
||||
การล้างข้อมูล หาก capacity ของ AWS ช้าเกินไปหรือไม่พร้อมใช้งาน ให้เพิ่ม provider
|
||||
ของ Hetzner ไว้หลัง machine interface เดียวกัน
|
||||
|
||||
ข้อกำหนด VM ขั้นต่ำ:
|
||||
ข้อกำหนดขั้นต่ำของ VM:
|
||||
|
||||
- Linux ที่มี Chrome หรือ Chromium ซึ่งรองรับเดสก์ท็อปติดตั้งอยู่
|
||||
- การเข้าถึง CDP สำหรับการทำงานอัตโนมัติของเบราว์เซอร์
|
||||
- VNC หรือ noVNC สำหรับการกู้คืน
|
||||
- Linux ที่ติดตั้ง Chrome หรือ Chromium ซึ่งรองรับ desktop
|
||||
- การเข้าถึง CDP สำหรับ browser automation
|
||||
- VNC หรือ noVNC สำหรับการกู้สถานการณ์
|
||||
- Node 22 และ pnpm
|
||||
- การ checkout OpenClaw และแคช dependency
|
||||
- แคชเบราว์เซอร์ Playwright Chromium เมื่อใช้ Playwright
|
||||
- CPU และหน่วยความจำเพียงพอสำหรับ OpenClaw Gateway หนึ่งตัว เบราว์เซอร์หนึ่งตัว และการรันโมเดลหนึ่งครั้ง
|
||||
- การเข้าถึงขาออกไปยัง Discord, GitHub, ผู้ให้บริการโมเดล และโบรกเกอร์ข้อมูลรับรอง
|
||||
- checkout ของ OpenClaw และ dependency cache
|
||||
- cache ของเบราว์เซอร์ Playwright Chromium เมื่อใช้ Playwright
|
||||
- CPU และ memory เพียงพอสำหรับ OpenClaw Gateway หนึ่งตัว เบราว์เซอร์หนึ่งตัว และ model run หนึ่งครั้ง
|
||||
- การเข้าถึงขาออกไปยัง Discord, GitHub, model provider และ credential broker
|
||||
|
||||
VM ไม่ควรเก็บความลับดิบที่มีอายุยาวนอกเหนือจากที่เก็บข้อมูลรับรองหรือ
|
||||
ที่เก็บโปรไฟล์เบราว์เซอร์ที่คาดไว้
|
||||
VM ไม่ควรเก็บ raw secret ที่มีอายุยาวนอก credential store หรือ browser profile
|
||||
store ที่คาดไว้
|
||||
|
||||
## ความลับ
|
||||
## Secret
|
||||
|
||||
ความลับอยู่ใน GitHub organization หรือ repository secrets สำหรับการรันระยะไกล และอยู่ใน
|
||||
ไฟล์ความลับภายในเครื่องที่ควบคุมโดยผู้ปฏิบัติงานสำหรับการรันภายในเครื่อง
|
||||
Secret อยู่ใน GitHub organization หรือ repository secrets สำหรับ remote run
|
||||
และอยู่ในไฟล์ secret ที่ควบคุมโดย operator ในเครื่องสำหรับ local run
|
||||
|
||||
ชื่อความลับที่แนะนำ:
|
||||
ชื่อ secret ที่แนะนำ:
|
||||
|
||||
- `OPENCLAW_QA_DISCORD_MANTIS_BOT_TOKEN`
|
||||
- `OPENCLAW_QA_DISCORD_DRIVER_BOT_TOKEN`
|
||||
@ -309,52 +357,52 @@ VM ไม่ควรเก็บความลับดิบที่มี
|
||||
- `OPENCLAW_QA_DISCORD_GUILD_ID`
|
||||
- `OPENCLAW_QA_DISCORD_CHANNEL_ID`
|
||||
- `OPENCLAW_QA_DISCORD_NOTIFY_CHANNEL_ID`
|
||||
- `OPENCLAW_QA_REDACT_PUBLIC_METADATA=1` สำหรับการอัปโหลดอาร์ติแฟกต์ GitHub สาธารณะ
|
||||
- `OPENCLAW_QA_REDACT_PUBLIC_METADATA=1` สำหรับการอัปโหลด artifact สาธารณะของ GitHub
|
||||
- `OPENCLAW_QA_CONVEX_SITE_URL`
|
||||
- `OPENCLAW_QA_CONVEX_SECRET_CI`
|
||||
- `OPENCLAW_QA_MANTIS_CRABBOX_COORDINATOR`
|
||||
- `OPENCLAW_QA_MANTIS_CRABBOX_COORDINATOR_TOKEN`
|
||||
|
||||
ในระยะยาว พูลข้อมูลรับรอง Convex ควรยังคงเป็นแหล่งปกติสำหรับข้อมูลรับรอง
|
||||
การขนส่งแบบสด GitHub secrets ใช้บูตสแตรปโบรกเกอร์และเลนสำรอง
|
||||
เวิร์กโฟลว์สถานะ-รีแอ็กชันของ Discord จับคู่ความลับ Mantis Crabbox กลับไปยัง
|
||||
ตัวแปรสภาพแวดล้อม `CRABBOX_COORDINATOR` และ `CRABBOX_COORDINATOR_TOKEN`
|
||||
ที่ Crabbox CLI คาดหวัง ชื่อ GitHub secret แบบธรรมดา `CRABBOX_*` ยังคง
|
||||
ได้รับการยอมรับเป็น fallback เพื่อความเข้ากันได้
|
||||
ในระยะยาว credential pool ของ Convex ควรยังเป็นแหล่งปกติสำหรับข้อมูลรับรอง live
|
||||
transport GitHub secrets ใช้ bootstrap broker และ fallback lane
|
||||
workflow สำหรับ status reaction ของ Discord map secret ของ Mantis Crabbox กลับไปยัง
|
||||
environment variable `CRABBOX_COORDINATOR` และ `CRABBOX_COORDINATOR_TOKEN`
|
||||
ที่ Crabbox CLI คาดหวัง ชื่อ GitHub secret แบบ plain `CRABBOX_*` ยังรองรับเป็น
|
||||
fallback เพื่อความเข้ากันได้
|
||||
|
||||
ตัวรัน Mantis ต้องไม่พิมพ์สิ่งต่อไปนี้:
|
||||
Mantis runner ต้องไม่พิมพ์:
|
||||
|
||||
- โทเค็นบอต Discord
|
||||
- คีย์ API ของผู้ให้บริการ
|
||||
- คุกกี้เบราว์เซอร์
|
||||
- เนื้อหาโปรไฟล์การยืนยันตัวตน
|
||||
- token ของบอต Discord
|
||||
- API key ของ provider
|
||||
- cookie ของเบราว์เซอร์
|
||||
- เนื้อหา auth profile
|
||||
- รหัสผ่าน VNC
|
||||
- payload ข้อมูลรับรองดิบ
|
||||
- payload ข้อมูลรับรองแบบ raw
|
||||
|
||||
การอัปโหลดอาร์ติแฟกต์สาธารณะควรปกปิดเมทาดาทาเป้าหมาย Discord ด้วย เช่น id ของบอต,
|
||||
กิลด์, ช่อง และข้อความ เวิร์กโฟลว์ smoke ของ GitHub เปิดใช้
|
||||
การอัปโหลด artifact สาธารณะควร redact metadata เป้าหมายของ Discord เช่น bot,
|
||||
guild, channel และ message id ด้วย GitHub smoke workflow เปิดใช้
|
||||
`OPENCLAW_QA_REDACT_PUBLIC_METADATA=1` ด้วยเหตุผลนี้
|
||||
|
||||
หากโทเค็นถูกวางลงใน issue, PR, แชต หรือบันทึกโดยไม่ได้ตั้งใจ ให้หมุนเวียนโทเค็นนั้น
|
||||
หลังจากเก็บความลับใหม่แล้ว
|
||||
หาก token ถูกวางลงใน issue, PR, chat หรือ log โดยไม่ตั้งใจ ให้ rotate หลังจาก
|
||||
จัดเก็บ secret ใหม่แล้ว
|
||||
|
||||
## GitHub Artifacts และความคิดเห็น PR
|
||||
## GitHub Artifacts และคอมเมนต์ PR
|
||||
|
||||
เวิร์กโฟลว์ Mantis ควรอัปโหลดชุดหลักฐานเต็มเป็นอาร์ติแฟกต์ Actions
|
||||
ที่มีอายุสั้น เมื่อเวิร์กโฟลว์ถูกรันสำหรับรายงานบั๊กหรือ PR แก้ไข ควร
|
||||
เผยแพร่ภาพหน้าจอ PNG ที่ปกปิดแล้วไปยัง branch `qa-artifacts` และ upsert
|
||||
ความคิดเห็นบนบั๊กหรือ PR แก้ไขนั้นพร้อมภาพหน้าจอแบบ inline ก่อน/หลัง อย่าโพสต์
|
||||
หลักฐานหลักไว้เฉพาะบน PR ระบบอัตโนมัติ QA ทั่วไป ล็อกดิบ ข้อความที่สังเกตเห็น
|
||||
และหลักฐานขนาดใหญ่อื่น ๆ ให้อยู่ในอาร์ติแฟกต์ Actions
|
||||
workflow ของ Mantis ควรอัปโหลด evidence bundle ทั้งหมดเป็น artifact ของ Actions
|
||||
ที่มีอายุสั้น เมื่อ workflow ถูกรันสำหรับรายงานบั๊กหรือ PR แก้ไข ควร publish
|
||||
screenshot PNG ที่ผ่าน redaction แล้วไปยัง branch `qa-artifacts` และ upsert
|
||||
คอมเมนต์บนบั๊กหรือ PR แก้ไขนั้นพร้อม screenshot ก่อน/หลังแบบ inline อย่าโพสต์
|
||||
หลักฐานหลักไว้เฉพาะบน PR automation QA ทั่วไป raw log, ข้อความที่สังเกตได้ และ
|
||||
หลักฐานขนาดใหญ่อื่น ๆ ให้อยู่ใน artifact ของ Actions
|
||||
|
||||
เวิร์กโฟลว์โปรดักชันควรโพสต์ความคิดเห็นเหล่านั้นด้วย Mantis GitHub App ไม่ใช่
|
||||
ด้วย `github-actions[bot]` เก็บ app id และ private key เป็น GitHub Actions
|
||||
workflow production ควรโพสต์คอมเมนต์เหล่านั้นด้วย Mantis GitHub App ไม่ใช่ด้วย
|
||||
`github-actions[bot]` เก็บ app id และ private key เป็น GitHub Actions
|
||||
secrets ชื่อ `MANTIS_GITHUB_APP_ID` และ `MANTIS_GITHUB_APP_PRIVATE_KEY`
|
||||
เวิร์กโฟลว์ใช้ marker ที่ซ่อนอยู่เป็นคีย์ upsert อัปเดตความคิดเห็นนั้นเมื่อ
|
||||
โทเค็นสามารถแก้ไขได้ และสร้างความคิดเห็นใหม่ที่ Mantis เป็นเจ้าของเมื่อ
|
||||
marker เก่าที่บอตเป็นเจ้าของไม่สามารถแก้ไขได้
|
||||
workflow ใช้ marker ที่ซ่อนอยู่เป็น upsert key, อัปเดตคอมเมนต์นั้นเมื่อ token
|
||||
แก้ไขได้ และสร้างคอมเมนต์ใหม่ที่ Mantis เป็นเจ้าของเมื่อ marker เก่าที่บอตเป็นเจ้าของ
|
||||
แก้ไขไม่ได้
|
||||
|
||||
ความคิดเห็น PR ควรสั้นและเน้นภาพ:
|
||||
คอมเมนต์ PR ควรสั้นและมีภาพ:
|
||||
|
||||
```md
|
||||
Mantis Discord Status Reactions QA
|
||||
@ -374,73 +422,70 @@ candidate showed the expected queued -> thinking -> done sequence.
|
||||
| <inline screenshot> | <inline screenshot> |
|
||||
```
|
||||
|
||||
เมื่อการรันล้มเหลวเพราะ harness ล้มเหลว ความคิดเห็นต้องระบุเช่นนั้น
|
||||
แทนที่จะสื่อว่าตัวเลือก candidate ล้มเหลว
|
||||
เมื่อการรันล้มเหลวเพราะ harness ล้มเหลว คอมเมนต์ต้องบอกเช่นนั้นแทนที่จะสื่อว่า
|
||||
candidate ล้มเหลว
|
||||
|
||||
## หมายเหตุการปรับใช้แบบส่วนตัว
|
||||
## หมายเหตุการ deploy แบบ private
|
||||
|
||||
การปรับใช้แบบส่วนตัวอาจมีแอปพลิเคชัน Discord ของ Mantis อยู่แล้ว ให้นำ
|
||||
แอปพลิเคชันนั้นกลับมาใช้แทนการสร้างแอปใหม่ เมื่อแอปนั้นมีสิทธิ์บอตที่ถูกต้อง
|
||||
และสามารถหมุนเวียนได้อย่างปลอดภัย
|
||||
การ deploy แบบ private อาจมี application Discord ของ Mantis อยู่แล้ว ให้ใช้
|
||||
application นั้นซ้ำแทนการสร้าง app ใหม่เมื่อมี permission ของบอตที่ถูกต้องและสามารถ
|
||||
rotate ได้อย่างปลอดภัย
|
||||
|
||||
ตั้งค่าช่องแจ้งเตือนผู้ปฏิบัติงานเริ่มต้นผ่าน secrets หรือการกำหนดค่าการปรับใช้
|
||||
ช่องนี้สามารถชี้ไปยังช่องผู้ดูแลหรือปฏิบัติการที่มีอยู่ก่อน แล้วค่อยย้ายไปยัง
|
||||
ตั้งค่าช่องแจ้งเตือน operator เริ่มต้นผ่าน secret หรือ configuration ของ deployment
|
||||
ช่องนี้สามารถชี้ไปที่ช่อง maintainer หรือ operations ที่มีอยู่ก่อน แล้วค่อยย้ายไปยัง
|
||||
ช่อง Mantis เฉพาะเมื่อมีช่องนั้นแล้ว
|
||||
|
||||
อย่าใส่ guild ids, channel ids, bot tokens, browser cookies หรือ VNC passwords
|
||||
ในเอกสารนี้ ให้เก็บไว้ใน GitHub secrets, โบรกเกอร์ข้อมูลรับรอง หรือที่เก็บ
|
||||
ความลับภายในเครื่องของผู้ปฏิบัติงาน
|
||||
อย่าใส่ guild id, channel id, bot token, cookie ของเบราว์เซอร์ หรือรหัสผ่าน VNC
|
||||
ไว้ในเอกสารนี้ ให้เก็บไว้ใน GitHub secrets, credential broker หรือ local secret store
|
||||
ของ operator
|
||||
|
||||
## การเพิ่มสถานการณ์
|
||||
## การเพิ่ม scenario
|
||||
|
||||
สถานการณ์ Mantis ควรประกาศ:
|
||||
scenario ของ Mantis ควรประกาศ:
|
||||
|
||||
- id และชื่อเรื่อง
|
||||
- การขนส่ง
|
||||
- transport
|
||||
- ข้อมูลรับรองที่ต้องใช้
|
||||
- นโยบาย baseline ref
|
||||
- นโยบาย candidate ref
|
||||
- patch การกำหนดค่า OpenClaw
|
||||
- นโยบาย ref ของ baseline
|
||||
- นโยบาย ref ของ candidate
|
||||
- patch config ของ OpenClaw
|
||||
- ขั้นตอนการตั้งค่า
|
||||
- สิ่งกระตุ้น
|
||||
- oracle baseline ที่คาดหวัง
|
||||
- oracle candidate ที่คาดหวัง
|
||||
- stimulus
|
||||
- oracle ของ baseline ที่คาดหวัง
|
||||
- oracle ของ candidate ที่คาดหวัง
|
||||
- เป้าหมายการจับภาพ
|
||||
- งบประมาณเวลา timeout
|
||||
- ขั้นตอนการทำความสะอาด
|
||||
- budget timeout
|
||||
- ขั้นตอนการล้างข้อมูล
|
||||
|
||||
สถานการณ์ควรเลือกใช้ oracle ขนาดเล็กที่มี type:
|
||||
scenario ควรเลือกใช้ oracle ที่เล็กและมี type:
|
||||
|
||||
- สถานะรีแอ็กชัน Discord สำหรับบั๊กรีแอ็กชัน
|
||||
- สถานะ reaction ของ Discord สำหรับบั๊ก reaction
|
||||
- การอ้างอิงข้อความ Discord สำหรับบั๊ก threading
|
||||
- thread ts ของ Slack และสถานะ API รีแอ็กชันสำหรับบั๊ก Slack
|
||||
- id ข้อความอีเมลและส่วนหัวสำหรับบั๊กอีเมล
|
||||
- ภาพหน้าจอเบราว์เซอร์เมื่อ UI เป็นสิ่งที่สังเกตได้อย่างน่าเชื่อถือเพียงอย่างเดียว
|
||||
- thread ts ของ Slack และสถานะ reaction API สำหรับบั๊ก Slack
|
||||
- message id และ header ของอีเมลสำหรับบั๊กอีเมล
|
||||
- screenshot ของเบราว์เซอร์เมื่อ UI เป็น observable เดียวที่เชื่อถือได้
|
||||
|
||||
การตรวจด้วย vision ควรเป็นแบบเพิ่มเติม หาก API ของแพลตฟอร์มสามารถพิสูจน์บั๊กได้ ให้ใช้
|
||||
API เป็น oracle ผ่าน/ไม่ผ่าน และเก็บภาพหน้าจอไว้เพื่อเพิ่มความมั่นใจของมนุษย์
|
||||
การตรวจด้วย vision ควรเป็นแบบ additive หาก API ของแพลตฟอร์มสามารถพิสูจน์บั๊กได้
|
||||
ให้ใช้ API เป็น oracle pass/fail และเก็บ screenshot ไว้เพื่อเพิ่มความมั่นใจให้มนุษย์
|
||||
|
||||
## การขยายผู้ให้บริการ
|
||||
## การขยาย Provider
|
||||
|
||||
หลังจาก Discord ตัวรันเดียวกันสามารถเพิ่ม:
|
||||
หลังจาก Discord แล้ว runner เดียวกันสามารถเพิ่ม:
|
||||
|
||||
- Slack: รีแอ็กชัน, thread, app mentions, modals, การอัปโหลดไฟล์
|
||||
- อีเมล: การยืนยันตัวตน Gmail และ message threading โดยใช้ `gog` เมื่อ connector
|
||||
ไม่เพียงพอ
|
||||
- WhatsApp: การเข้าสู่ระบบ QR, การระบุตัวตนใหม่, การส่งข้อความ, สื่อ, รีแอ็กชัน
|
||||
- Telegram: group mention gating, คำสั่ง, รีแอ็กชันเมื่อพร้อมใช้งาน
|
||||
- Matrix: ห้องที่เข้ารหัส, ความสัมพันธ์ของ thread หรือ reply, การ resume หลัง restart
|
||||
- Slack: reaction, thread, app mention, modal, การอัปโหลดไฟล์
|
||||
- อีเมล: auth ของ Gmail และ message threading โดยใช้ `gog` เมื่อ connector ไม่เพียงพอ
|
||||
- WhatsApp: การ login ด้วย QR, การระบุตัวตนซ้ำ, การส่งข้อความ, สื่อ, reaction
|
||||
- Telegram: gating การ mention ในกลุ่ม, command, reaction เมื่อพร้อมใช้งาน
|
||||
- Matrix: ห้องที่เข้ารหัส, ความสัมพันธ์แบบ thread หรือ reply, การ resume หลัง restart
|
||||
|
||||
แต่ละการขนส่งควรมีสถานการณ์ smoke ราคาถูกหนึ่งรายการ และสถานการณ์ตามกลุ่มบั๊กหนึ่งรายการขึ้นไป
|
||||
สถานการณ์ภาพที่มีค่าใช้จ่ายสูงควรเป็นแบบ opt-in
|
||||
แต่ละ transport ควรมี smoke scenario ราคาถูกหนึ่งรายการ และ scenario ตามชนิดบั๊ก
|
||||
หนึ่งรายการขึ้นไป scenario แบบ visual ที่มีค่าใช้จ่ายสูงควรเป็น opt-in
|
||||
|
||||
## คำถามที่ยังเปิดอยู่
|
||||
## คำถามเปิด
|
||||
|
||||
- บอต Discord ใดควรเป็น driver และบอตใดควรเป็น SUT เมื่อมีการนำ
|
||||
บอต Mantis ที่มีอยู่กลับมาใช้
|
||||
- การเข้าสู่ระบบเบราว์เซอร์ผู้สังเกตการณ์ควรใช้บัญชี Discord ของมนุษย์ บัญชีทดสอบ
|
||||
หรือใช้เฉพาะหลักฐาน REST ที่บอตอ่านได้สำหรับเฟสแรก
|
||||
- GitHub ควรเก็บอาร์ติแฟกต์ Mantis สำหรับ PR ไว้นานเท่าใด
|
||||
- เมื่อใด ClawSweeper ควรแนะนำ Mantis โดยอัตโนมัติแทนการรอคำสั่ง
|
||||
จากผู้ดูแล
|
||||
- ภาพหน้าจอควรถูกปกปิดหรือตัดก่อนอัปโหลดสำหรับ PR สาธารณะหรือไม่
|
||||
- บอต Discord ตัวใดควรเป็น driver และตัวใดควรเป็น SUT เมื่อใช้บอต Mantis ที่มีอยู่ซ้ำ?
|
||||
- การ login เบราว์เซอร์ของ observer ควรใช้บัญชี Discord ของมนุษย์, บัญชีทดสอบ
|
||||
หรือใช้เฉพาะหลักฐาน REST ที่บอตอ่านได้สำหรับ phase แรก?
|
||||
- GitHub ควรเก็บ artifact ของ Mantis สำหรับ PR ไว้นานเท่าใด?
|
||||
- ClawSweeper ควรแนะนำ Mantis โดยอัตโนมัติเมื่อใด แทนที่จะรอ command จาก maintainer?
|
||||
- ควร redact หรือ crop screenshot ก่อนอัปโหลดสำหรับ PR สาธารณะหรือไม่?
|
||||
|
||||
@ -1,22 +1,22 @@
|
||||
---
|
||||
read_when:
|
||||
- อธิบายวิธีที่ข้อความขาเข้ากลายเป็นการตอบกลับ
|
||||
- อธิบายว่าข้อความขาเข้ากลายเป็นการตอบกลับอย่างไร
|
||||
- การทำให้เซสชัน โหมดการจัดคิว หรือพฤติกรรมการสตรีมชัดเจนขึ้น
|
||||
- การจัดทำเอกสารเรื่องการมองเห็นการให้เหตุผลและผลกระทบต่อการใช้งาน
|
||||
summary: การไหลของข้อความ เซสชัน การจัดคิว และการมองเห็นการให้เหตุผล
|
||||
- การจัดทำเอกสารเกี่ยวกับการมองเห็นการให้เหตุผลและผลกระทบต่อการใช้งาน
|
||||
summary: โฟลว์ข้อความ เซสชัน การจัดคิว และการมองเห็นการให้เหตุผล
|
||||
title: ข้อความ
|
||||
x-i18n:
|
||||
generated_at: "2026-04-30T16:27:51Z"
|
||||
generated_at: "2026-05-04T07:03:43Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: fdeee014d92767a725501691fbe0c4ee6b631acc9a2ab5cbbcf321bfee9679b9
|
||||
source_hash: 15242e21fd17a9f2013561003e108d197204d834caf51bbcdc53ffb3f118b14f
|
||||
source_path: concepts/messages.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
OpenClaw จัดการข้อความขาเข้าผ่านไปป์ไลน์ของการระบุเซสชัน การจัดคิว การสตรีม การเรียกใช้เครื่องมือ และการมองเห็นการให้เหตุผล หน้านี้แสดงเส้นทางตั้งแต่ข้อความขาเข้าจนถึงข้อความตอบกลับ
|
||||
OpenClaw จัดการข้อความขาเข้าผ่านไปป์ไลน์ของการระบุเซสชัน การเข้าคิว การสตรีม การเรียกใช้เครื่องมือ และการแสดงเหตุผล หน้านี้แสดงเส้นทางตั้งแต่ข้อความขาเข้าจนถึงการตอบกลับ
|
||||
|
||||
## ลำดับการไหลของข้อความ (ภาพรวม)
|
||||
## โฟลว์ข้อความ (ระดับสูง)
|
||||
|
||||
```
|
||||
Inbound message
|
||||
@ -26,23 +26,23 @@ Inbound message
|
||||
-> outbound replies (channel limits + chunking)
|
||||
```
|
||||
|
||||
ค่าควบคุมหลักอยู่ในการกำหนดค่า:
|
||||
ปุ่มปรับหลักอยู่ในการกำหนดค่า:
|
||||
|
||||
- `messages.*` สำหรับคำนำหน้า การจัดคิว และพฤติกรรมของกลุ่ม
|
||||
- `messages.*` สำหรับคำนำหน้า การเข้าคิว และพฤติกรรมของกลุ่ม
|
||||
- `agents.defaults.*` สำหรับค่าเริ่มต้นของการสตรีมแบบบล็อกและการแบ่งชิ้นข้อความ
|
||||
- การ override ตามช่องทาง (`channels.whatsapp.*`, `channels.telegram.*` และอื่นๆ) สำหรับขีดจำกัดและตัวเปิดปิดการสตรีม
|
||||
- การแทนที่ระดับช่องทาง (`channels.whatsapp.*`, `channels.telegram.*` ฯลฯ) สำหรับเพดานจำกัดและตัวเปิดปิดการสตรีม
|
||||
|
||||
ดูสคีมาเต็มได้ที่ [การกำหนดค่า](/th/gateway/configuration)
|
||||
|
||||
## การตัดข้อความขาเข้าซ้ำ
|
||||
## การกรองข้อความขาเข้าซ้ำ
|
||||
|
||||
ช่องทางอาจส่งข้อความเดิมซ้ำหลังจากเชื่อมต่อใหม่ OpenClaw เก็บแคชอายุสั้นที่อิงตาม channel/account/peer/session/message id เพื่อให้การส่งซ้ำไม่ทริกเกอร์ agent run อีกครั้ง
|
||||
ช่องทางอาจส่งข้อความเดิมซ้ำหลังจากเชื่อมต่อใหม่ OpenClaw เก็บแคชอายุสั้นที่ใช้คีย์ตามช่องทาง/บัญชี/เพียร์/เซสชัน/รหัสข้อความ เพื่อให้การส่งซ้ำไม่เรียกการรันเอเจนต์อีกครั้ง
|
||||
|
||||
## การหน่วงรวมข้อความขาเข้า
|
||||
|
||||
ข้อความที่ส่งต่อเนื่องอย่างรวดเร็วจาก **ผู้ส่งคนเดียวกัน** สามารถรวมเป็น agent turn เดียวได้ผ่าน `messages.inbound` การหน่วงรวมมีขอบเขตต่อช่องทาง + การสนทนา และใช้ข้อความล่าสุดสำหรับเธรด/ID ของการตอบกลับ
|
||||
ข้อความที่ส่งติดกันอย่างรวดเร็วจาก **ผู้ส่งคนเดียวกัน** สามารถถูกรวมเป็นเทิร์นเดียวของเอเจนต์ผ่าน `messages.inbound` การหน่วงรวมมีขอบเขตต่อช่องทาง + บทสนทนา และใช้ข้อความล่าสุดสำหรับการผูกเธรด/รหัสของการตอบกลับ
|
||||
|
||||
การกำหนดค่า (ค่าเริ่มต้นส่วนกลาง + การ override ต่อช่องทาง):
|
||||
การกำหนดค่า (ค่าเริ่มต้นระดับสากล + การแทนที่รายช่องทาง):
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -61,120 +61,119 @@ Inbound message
|
||||
|
||||
หมายเหตุ:
|
||||
|
||||
- การหน่วงรวมใช้กับข้อความ **แบบข้อความล้วน** เท่านั้น สื่อ/ไฟล์แนบจะถูกส่งออกทันที
|
||||
- คำสั่งควบคุมจะข้ามการหน่วงรวมเพื่อให้ยังคงเป็นรายการเดี่ยว — **ยกเว้น** เมื่อช่องทางเลือกเข้าร่วมการรวม DM จากผู้ส่งคนเดียวกันอย่างชัดเจน (เช่น [BlueBubbles `coalesceSameSenderDms`](/th/channels/bluebubbles#coalescing-split-send-dms-command--url-in-one-composition)) ซึ่งคำสั่ง DM จะรออยู่ในช่วงหน่วงรวมเพื่อให้ payload แบบส่งแยกสามารถเข้าร่วม agent turn เดียวกันได้
|
||||
- การหน่วงรวมใช้กับข้อความ **ที่เป็นข้อความล้วน** เท่านั้น สื่อ/ไฟล์แนบจะถูกส่งต่อทันที
|
||||
- คำสั่งควบคุมจะข้ามการหน่วงรวมเพื่อให้ยังคงเป็นข้อความเดี่ยว ยกเว้นเมื่อช่องทางเลือกใช้การรวม DM จากผู้ส่งคนเดียวกันอย่างชัดเจน (เช่น [BlueBubbles `coalesceSameSenderDms`](/th/channels/bluebubbles#coalescing-split-send-dms-command--url-in-one-composition)) ซึ่งคำสั่ง DM จะรออยู่ในหน้าต่างหน่วงรวม เพื่อให้เพย์โหลดที่ส่งแยกสามารถรวมเป็นเทิร์นเดียวกันของเอเจนต์ได้
|
||||
|
||||
## เซสชันและอุปกรณ์
|
||||
|
||||
เซสชันเป็นของ Gateway ไม่ใช่ของไคลเอนต์
|
||||
|
||||
- แชทโดยตรงจะถูกรวมเข้าเป็นคีย์เซสชันหลักของ agent
|
||||
- แชทโดยตรงจะถูกรวมเข้ากับคีย์เซสชันหลักของเอเจนต์
|
||||
- กลุ่ม/ช่องทางจะมีคีย์เซสชันของตัวเอง
|
||||
- ที่เก็บเซสชันและบันทึกบทสนทนาอยู่บนโฮสต์ Gateway
|
||||
- ที่เก็บเซสชันและทรานสคริปต์อยู่บนโฮสต์ Gateway
|
||||
|
||||
อุปกรณ์/ช่องทางหลายรายการสามารถแมปไปยังเซสชันเดียวกันได้ แต่ประวัติจะไม่ถูกซิงก์กลับไปยังไคลเอนต์ทุกตัวอย่างสมบูรณ์ คำแนะนำ: ใช้อุปกรณ์หลักหนึ่งเครื่องสำหรับการสนทนายาวเพื่อหลีกเลี่ยงบริบทที่แตกต่างกัน Control UI และ TUI จะแสดงบันทึกบทสนทนาของเซสชันที่อิงกับ Gateway เสมอ ดังนั้นจึงเป็นแหล่งข้อมูลจริง
|
||||
อุปกรณ์/ช่องทางหลายรายการสามารถแมปไปยังเซสชันเดียวกันได้ แต่ประวัติจะไม่ถูกซิงก์กลับไปยังไคลเอนต์ทุกตัวอย่างครบถ้วน คำแนะนำ: ใช้อุปกรณ์หลักเพียงหนึ่งตัวสำหรับบทสนทนายาวเพื่อหลีกเลี่ยงบริบทที่แยกทางกัน Control UI และ TUI จะแสดงทรานสคริปต์เซสชันที่อิงจาก Gateway เสมอ ดังนั้นจึงเป็นแหล่งข้อมูลจริง
|
||||
|
||||
รายละเอียด: [การจัดการเซสชัน](/th/concepts/session)
|
||||
|
||||
## เมทาดาทาของผลลัพธ์เครื่องมือ
|
||||
|
||||
`content` ของผลลัพธ์เครื่องมือคือผลลัพธ์ที่โมเดลมองเห็น ส่วน `details` ของผลลัพธ์เครื่องมือคือเมทาดาทารันไทม์สำหรับการเรนเดอร์ UI การวินิจฉัย การส่งสื่อ และ Plugin
|
||||
`content` ของผลลัพธ์เครื่องมือคือผลลัพธ์ที่โมเดลมองเห็น ส่วน `details` ของผลลัพธ์เครื่องมือคือเมทาดาทารันไทม์สำหรับการเรนเดอร์ UI การวินิจฉัย การส่งมอบสื่อ และ Plugin
|
||||
|
||||
OpenClaw ทำให้ขอบเขตนั้นชัดเจน:
|
||||
OpenClaw รักษาขอบเขตนั้นไว้อย่างชัดเจน:
|
||||
|
||||
- `toolResult.details` จะถูกตัดออกก่อน replay ของ provider และอินพุต Compaction
|
||||
- บันทึกบทสนทนาเซสชันที่บันทึกไว้จะเก็บเฉพาะ `details` ที่มีขอบเขต เมทาดาทาที่ใหญ่เกินไปจะถูกแทนที่ด้วยสรุปแบบกระชับที่ทำเครื่องหมาย `persistedDetailsTruncated: true`
|
||||
- `toolResult.details` จะถูกลบออกก่อนการเล่นซ้ำกับผู้ให้บริการและอินพุตของ Compaction
|
||||
- ทรานสคริปต์เซสชันที่บันทึกถาวรจะเก็บเฉพาะ `details` ที่มีขนาดจำกัด เมทาดาทาที่ใหญ่เกินไปจะถูกแทนที่ด้วยสรุปแบบกระชับที่ทำเครื่องหมาย `persistedDetailsTruncated: true`
|
||||
- Plugin และเครื่องมือควรใส่ข้อความที่โมเดลต้องอ่านไว้ใน `content` ไม่ใช่เฉพาะใน `details`
|
||||
|
||||
## เนื้อหาขาเข้าและบริบทประวัติ
|
||||
|
||||
OpenClaw แยก **เนื้อหา prompt** ออกจาก **เนื้อหาคำสั่ง**:
|
||||
OpenClaw แยก **เนื้อหาพรอมป์** ออกจาก **เนื้อหาคำสั่ง**:
|
||||
|
||||
- `BodyForAgent`: ข้อความหลักที่หันหน้าเข้าหาโมเดลสำหรับข้อความปัจจุบัน Plugin ของช่องทางควรทำให้ส่วนนี้โฟกัสที่ข้อความปัจจุบันของผู้ส่งซึ่งมี prompt
|
||||
- `Body`: fallback ของ prompt แบบเดิม ส่วนนี้อาจรวม envelope ของช่องทางและ wrapper ประวัติแบบเลือกได้ แต่ช่องทางปัจจุบันไม่ควรพึ่งพาส่วนนี้เป็นอินพุตหลักของโมเดลเมื่อมี `BodyForAgent`
|
||||
- `CommandBody`: ข้อความผู้ใช้ดิบสำหรับการแยกวิเคราะห์ directive/คำสั่ง
|
||||
- `RawBody`: alias เดิมของ `CommandBody` (เก็บไว้เพื่อความเข้ากันได้)
|
||||
- `BodyForAgent`: ข้อความหลักที่หันเข้าหาโมเดลสำหรับข้อความปัจจุบัน Plugin ของช่องทางควรรักษาให้ส่วนนี้เน้นเฉพาะข้อความปัจจุบันของผู้ส่งที่เป็นพรอมป์
|
||||
- `Body`: พรอมป์สำรองแบบเดิม อาจมีเอนเวโลปของช่องทางและตัวครอบประวัติเสริม แต่ช่องทางปัจจุบันไม่ควรพึ่งพาส่วนนี้เป็นอินพุตหลักของโมเดลเมื่อมี `BodyForAgent`
|
||||
- `CommandBody`: ข้อความผู้ใช้ดิบสำหรับการแยกวิเคราะห์ไดเรกทีฟ/คำสั่ง
|
||||
- `RawBody`: ชื่อแทนเดิมของ `CommandBody` (เก็บไว้เพื่อความเข้ากันได้)
|
||||
|
||||
เมื่อช่องทางส่งประวัติมา จะใช้ wrapper ร่วมกัน:
|
||||
เมื่อช่องทางส่งประวัติมา จะใช้ตัวครอบร่วม:
|
||||
|
||||
- `[Chat messages since your last reply - for context]`
|
||||
- `[Current message - respond to this]`
|
||||
|
||||
สำหรับ **แชทที่ไม่ใช่แชทโดยตรง** (กลุ่ม/ช่องทาง/ห้อง) **เนื้อหาข้อความปัจจุบัน** จะมีคำนำหน้าด้วยป้ายกำกับผู้ส่ง (สไตล์เดียวกับที่ใช้กับรายการประวัติ) สิ่งนี้ทำให้ข้อความแบบเรียลไทม์และข้อความที่อยู่ในคิว/ประวัติสอดคล้องกันใน prompt ของ agent
|
||||
สำหรับ **แชทที่ไม่ใช่แชทโดยตรง** (กลุ่ม/ช่องทาง/ห้อง) **เนื้อหาข้อความปัจจุบัน** จะนำหน้าด้วยป้ายชื่อผู้ส่ง (สไตล์เดียวกับที่ใช้กับรายการประวัติ) วิธีนี้ทำให้ข้อความแบบเรียลไทม์และข้อความในคิว/ประวัติสอดคล้องกันในพรอมป์ของเอเจนต์
|
||||
|
||||
บัฟเฟอร์ประวัติเป็นแบบ **รอดำเนินการเท่านั้น**: รวมข้อความกลุ่มที่ _ไม่ได้_ ทริกเกอร์ run (เช่น ข้อความที่ถูกกั้นด้วยการ mention) และ **ไม่รวม** ข้อความที่อยู่ในบันทึกบทสนทนาเซสชันแล้ว
|
||||
บัฟเฟอร์ประวัติเป็นแบบ **รอดำเนินการเท่านั้น**: รวมข้อความกลุ่มที่ _ไม่ได้_ เรียกการรัน (เช่น ข้อความที่ถูกกั้นด้วยการกล่าวถึง) และ **ไม่รวม** ข้อความที่มีอยู่แล้วในทรานสคริปต์เซสชัน
|
||||
|
||||
การตัด directive ใช้กับส่วน **ข้อความปัจจุบัน** เท่านั้นเพื่อให้ประวัติยังคงครบถ้วน ช่องทางที่ครอบประวัติควรตั้งค่า `CommandBody` (หรือ `RawBody`) เป็นข้อความเดิม และเก็บ `Body` เป็น prompt ที่รวมแล้ว ประวัติแบบมีโครงสร้าง การตอบกลับ ข้อความที่ส่งต่อ และเมทาดาทาช่องทางจะถูกเรนเดอร์เป็นบล็อกบริบทที่ไม่น่าเชื่อถือในบทบาทผู้ใช้ระหว่างการประกอบ prompt
|
||||
บัฟเฟอร์ประวัติกำหนดค่าได้ผ่าน `messages.groupChat.historyLimit` (ค่าเริ่มต้นส่วนกลาง) และการ override ต่อช่องทาง เช่น `channels.slack.historyLimit` หรือ `channels.telegram.accounts.<id>.historyLimit` (ตั้งเป็น `0` เพื่อปิดใช้)
|
||||
การตัดไดเรกทีฟออกจะใช้เฉพาะกับส่วน **ข้อความปัจจุบัน** เพื่อให้ประวัติยังคงครบถ้วน ช่องทางที่ครอบประวัติควรตั้ง `CommandBody` (หรือ `RawBody`) เป็นข้อความต้นฉบับ และเก็บ `Body` เป็นพรอมป์ที่รวมแล้ว ประวัติที่มีโครงสร้าง การตอบกลับ ข้อความที่ส่งต่อ และเมทาดาทาของช่องทางจะถูกเรนเดอร์เป็นบล็อกบริบทที่ไม่น่าเชื่อถือในบทบาทผู้ใช้ระหว่างการประกอบพรอมป์
|
||||
บัฟเฟอร์ประวัติสามารถกำหนดค่าได้ผ่าน `messages.groupChat.historyLimit` (ค่าเริ่มต้นระดับสากล) และการแทนที่รายช่องทาง เช่น `channels.slack.historyLimit` หรือ `channels.telegram.accounts.<id>.historyLimit` (ตั้ง `0` เพื่อปิดใช้งาน)
|
||||
|
||||
## การจัดคิวและ followup
|
||||
## การเข้าคิวและการติดตามผล
|
||||
|
||||
หากมี run ที่กำลังทำงานอยู่ ข้อความขาเข้าสามารถถูกจัดคิว นำไป steer เข้าสู่ run ปัจจุบัน หรือรวบรวมไว้สำหรับ turn followup ได้
|
||||
หากมีการรันทำงานอยู่แล้ว ข้อความขาเข้าสามารถถูกเข้าคิว ถูกนำทางเข้าไปในการรันปัจจุบัน หรือถูกรวบรวมไว้สำหรับเทิร์นติดตามผล
|
||||
|
||||
- กำหนดค่าผ่าน `messages.queue` (และ `messages.queue.byChannel`)
|
||||
- โหมดเริ่มต้นคือ `steer` พร้อมการหน่วงรวม followup 500ms เมื่อการ steer fallback ไปเป็นการส่ง followup ที่จัดคิวไว้
|
||||
- โหมด: `steer`, `followup`, `collect`, `steer-backlog`, `interrupt` และโหมดเดิมแบบทีละรายการ `queue`
|
||||
- โหมดเริ่มต้นคือ `steer` พร้อมการหน่วงรวมติดตามผล 500ms เมื่อการนำทางย้อนกลับไปใช้การส่งมอบติดตามผลแบบเข้าคิว
|
||||
- โหมด: `steer`, `followup`, `collect`, `steer-backlog`, `interrupt` และโหมด `queue` แบบเดิมที่ทำทีละรายการ
|
||||
|
||||
รายละเอียด: [คิวคำสั่ง](/th/concepts/queue) และ [คิวการ steer](/th/concepts/queue-steering)
|
||||
รายละเอียด: [คิวคำสั่ง](/th/concepts/queue) และ [คิวการนำทาง](/th/concepts/queue-steering)
|
||||
|
||||
## ความเป็นเจ้าของ run ของช่องทาง
|
||||
## ความเป็นเจ้าของการรันของช่องทาง
|
||||
|
||||
Plugin ของช่องทางอาจรักษาลำดับ หน่วงรวมอินพุต และใช้ backpressure ของทรานสปอร์ตก่อนที่ข้อความจะเข้าสู่คิวเซสชัน ไม่ควรกำหนด timeout แยกต่างหากรอบ agent turn เอง เมื่อข้อความถูก route ไปยังเซสชันแล้ว งานที่รันนานจะถูกควบคุมโดย lifecycle ของเซสชัน เครื่องมือ และรันไทม์ เพื่อให้ทุกช่องทางรายงานและกู้คืนจาก turn ที่ช้าได้อย่างสอดคล้องกัน
|
||||
Plugin ของช่องทางอาจรักษาลำดับ หน่วงรวมอินพุต และใช้แรงดันย้อนกลับของการขนส่งก่อนที่ข้อความจะเข้าสู่คิวเซสชัน แต่ไม่ควรกำหนดเวลาหมดอายุแยกต่างหากรอบเทิร์นของเอเจนต์เอง เมื่อข้อความถูกกำหนดเส้นทางไปยังเซสชันแล้ว งานที่ใช้เวลานานจะถูกควบคุมโดยวงจรชีวิตของเซสชัน เครื่องมือ และรันไทม์ เพื่อให้ทุกช่องทางรายงานและกู้คืนจากเทิร์นที่ช้าได้อย่างสอดคล้องกัน
|
||||
|
||||
## การสตรีม การแบ่งชิ้นข้อความ และการจัดชุด
|
||||
|
||||
การสตรีมแบบบล็อกส่งข้อความตอบกลับบางส่วนเมื่อโมเดลผลิตบล็อกข้อความ
|
||||
การแบ่งชิ้นข้อความเคารพขีดจำกัดข้อความของช่องทางและหลีกเลี่ยงการแยก fenced code
|
||||
การสตรีมแบบบล็อกส่งการตอบกลับบางส่วนเมื่อโมเดลสร้างบล็อกข้อความ การแบ่งชิ้นข้อความเคารพขีดจำกัดข้อความของช่องทางและหลีกเลี่ยงการตัดแบ่งโค้ดแบบมีรั้ว
|
||||
|
||||
การตั้งค่าหลัก:
|
||||
|
||||
- `agents.defaults.blockStreamingDefault` (`on|off`, ค่าเริ่มต้น off)
|
||||
- `agents.defaults.blockStreamingDefault` (`on|off`, ค่าเริ่มต้นปิด)
|
||||
- `agents.defaults.blockStreamingBreak` (`text_end|message_end`)
|
||||
- `agents.defaults.blockStreamingChunk` (`minChars|maxChars|breakPreference`)
|
||||
- `agents.defaults.blockStreamingCoalesce` (การจัดชุดตาม idle)
|
||||
- `agents.defaults.humanDelay` (การหยุดแบบคล้ายมนุษย์ระหว่างข้อความตอบกลับแบบบล็อก)
|
||||
- การ override ของช่องทาง: `*.blockStreaming` และ `*.blockStreamingCoalesce` (ช่องทางที่ไม่ใช่ Telegram ต้องมี `*.blockStreaming: true` อย่างชัดเจน)
|
||||
- `agents.defaults.blockStreamingCoalesce` (การจัดชุดตามเวลาว่าง)
|
||||
- `agents.defaults.humanDelay` (การหยุดพักคล้ายมนุษย์ระหว่างการตอบกลับแบบบล็อก)
|
||||
- การแทนที่ระดับช่องทาง: `*.blockStreaming` และ `*.blockStreamingCoalesce` (ช่องทางที่ไม่ใช่ Telegram ต้องมี `*.blockStreaming: true` อย่างชัดเจน)
|
||||
|
||||
รายละเอียด: [การสตรีม + การแบ่งชิ้นข้อความ](/th/concepts/streaming)
|
||||
|
||||
## การมองเห็นการให้เหตุผลและ token
|
||||
## การแสดงเหตุผลและโทเคน
|
||||
|
||||
OpenClaw สามารถเปิดเผยหรือซ่อนการให้เหตุผลของโมเดลได้:
|
||||
|
||||
- `/reasoning on|off|stream` ควบคุมการมองเห็น
|
||||
- เนื้อหาการให้เหตุผลยังคงนับรวมในปริมาณการใช้ token เมื่อโมเดลสร้างขึ้น
|
||||
- Telegram รองรับการสตรีมการให้เหตุผลเข้าไปใน bubble แบบร่าง
|
||||
- `/reasoning on|off|stream` ควบคุมการแสดงผล
|
||||
- เนื้อหาการให้เหตุผลยังคงนับรวมในการใช้โทเคนเมื่อโมเดลสร้างขึ้น
|
||||
- Telegram รองรับการสตรีมเหตุผลไปยังบับเบิลฉบับร่างชั่วคราวที่จะถูกลบหลังส่งมอบคำตอบสุดท้าย ใช้ `/reasoning on` สำหรับเอาต์พุตเหตุผลแบบคงอยู่
|
||||
|
||||
รายละเอียด: [directive สำหรับ Thinking + reasoning](/th/tools/thinking) และ [การใช้ token](/th/reference/token-use)
|
||||
รายละเอียด: [ไดเรกทีฟการคิด + การให้เหตุผล](/th/tools/thinking) และ [การใช้โทเคน](/th/reference/token-use)
|
||||
|
||||
## คำนำหน้า เธรด และการตอบกลับ
|
||||
|
||||
การจัดรูปแบบข้อความขาออกถูกรวมศูนย์ไว้ใน `messages`:
|
||||
|
||||
- `messages.responsePrefix`, `channels.<channel>.responsePrefix` และ `channels.<channel>.accounts.<id>.responsePrefix` (ลำดับคำนำหน้าขาออก) รวมถึง `channels.whatsapp.messagePrefix` (คำนำหน้าขาเข้าของ WhatsApp)
|
||||
- การทำเธรดคำตอบผ่าน `replyToMode` และค่าเริ่มต้นต่อช่องทาง
|
||||
- `messages.responsePrefix`, `channels.<channel>.responsePrefix` และ `channels.<channel>.accounts.<id>.responsePrefix` (ลำดับการใช้คำนำหน้าขาออก), รวมถึง `channels.whatsapp.messagePrefix` (คำนำหน้าขาเข้าของ WhatsApp)
|
||||
- การผูกเธรดการตอบกลับผ่าน `replyToMode` และค่าเริ่มต้นรายช่องทาง
|
||||
|
||||
รายละเอียด: [การกำหนดค่า](/th/gateway/config-agents#messages) และเอกสารช่องทาง
|
||||
รายละเอียด: [การกำหนดค่า](/th/gateway/config-agents#messages) และเอกสารของช่องทาง
|
||||
|
||||
## การตอบกลับแบบเงียบ
|
||||
|
||||
silent token ที่แน่นอน `NO_REPLY` / `no_reply` หมายถึง “อย่าส่งคำตอบที่ผู้ใช้มองเห็น”
|
||||
เมื่อ turn มีสื่อเครื่องมือที่รอดำเนินการด้วย เช่น เสียง TTS ที่สร้างขึ้น OpenClaw จะตัดข้อความแบบเงียบออกแต่ยังคงส่งไฟล์แนบสื่อ
|
||||
OpenClaw แก้พฤติกรรมนั้นตามประเภทการสนทนา:
|
||||
โทเคนเงียบที่ตรงตัว `NO_REPLY` / `no_reply` หมายถึง “อย่าส่งคำตอบที่ผู้ใช้มองเห็น”
|
||||
เมื่อเทิร์นหนึ่งยังมีสื่อเครื่องมือที่รอดำเนินการด้วย เช่น เสียง TTS ที่สร้างขึ้น OpenClaw จะตัดข้อความเงียบออก แต่ยังส่งมอบไฟล์แนบสื่อนั้น
|
||||
OpenClaw แก้พฤติกรรมนั้นตามประเภทบทสนทนา:
|
||||
|
||||
- การสนทนาโดยตรงไม่อนุญาตความเงียบตามค่าเริ่มต้น และเขียนคำตอบแบบเงียบล้วนใหม่เป็น fallback สั้นๆ ที่มองเห็นได้
|
||||
- บทสนทนาโดยตรงไม่อนุญาตความเงียบตามค่าเริ่มต้น และเขียนคำตอบเงียบล้วนใหม่เป็นข้อความสำรองสั้น ๆ ที่มองเห็นได้
|
||||
- กลุ่ม/ช่องทางอนุญาตความเงียบตามค่าเริ่มต้น
|
||||
- การประสานงานภายในอนุญาตความเงียบตามค่าเริ่มต้น
|
||||
|
||||
OpenClaw ยังใช้การตอบกลับแบบเงียบสำหรับความล้มเหลวของ runner ภายในที่เกิดขึ้นก่อนคำตอบของ assistant ใดๆ ในแชทที่ไม่ใช่แชทโดยตรง เพื่อให้กลุ่ม/ช่องทางไม่เห็นข้อความ error boilerplate ของ Gateway แชทโดยตรงจะแสดงข้อความความล้มเหลวแบบกระชับตามค่าเริ่มต้น รายละเอียด runner ดิบจะแสดงเฉพาะเมื่อ `/verbose` เป็น `on` หรือ `full`
|
||||
OpenClaw ยังใช้การตอบกลับแบบเงียบสำหรับความล้มเหลวของรันเนอร์ภายในที่เกิดขึ้นก่อนมีการตอบกลับจากผู้ช่วยในแชทที่ไม่ใช่แชทโดยตรง เพื่อให้กลุ่ม/ช่องทางไม่เห็นข้อความข้อผิดพลาดสำเร็จรูปของ Gateway แชทโดยตรงจะแสดงข้อความความล้มเหลวแบบกระชับตามค่าเริ่มต้น รายละเอียดรันเนอร์ดิบจะแสดงเฉพาะเมื่อ `/verbose` เป็น `on` หรือ `full`
|
||||
|
||||
ค่าเริ่มต้นอยู่ภายใต้ `agents.defaults.silentReply` และ `agents.defaults.silentReplyRewrite`; `surfaces.<id>.silentReply` และ `surfaces.<id>.silentReplyRewrite` สามารถ override ต่อ surface ได้
|
||||
ค่าเริ่มต้นอยู่ใต้ `agents.defaults.silentReply` และ `agents.defaults.silentReplyRewrite`; `surfaces.<id>.silentReply` และ `surfaces.<id>.silentReplyRewrite` สามารถแทนที่ต่อพื้นผิวได้
|
||||
|
||||
เมื่อเซสชันแม่มี spawned subagent run ที่รอดำเนินการอย่างน้อยหนึ่งรายการ การตอบกลับแบบเงียบล้วนจะถูกทิ้งในทุก surface แทนที่จะถูกเขียนใหม่ เพื่อให้เซสชันแม่ยังคงเงียบจนกว่าเหตุการณ์ child completion จะส่งคำตอบจริง
|
||||
เมื่อเซสชันแม่มีการรันซับเอเจนต์ที่สร้างไว้และรอดำเนินการหนึ่งรายการขึ้นไป การตอบกลับเงียบล้วนจะถูกทิ้งบนทุกพื้นผิวแทนการเขียนใหม่ เพื่อให้เซสชันแม่ยังเงียบอยู่จนกว่าอีเวนต์เสร็จสิ้นของลูกจะส่งมอบคำตอบจริง
|
||||
|
||||
## ที่เกี่ยวข้อง
|
||||
|
||||
- [การสตรีม](/th/concepts/streaming) — การส่งข้อความแบบเรียลไทม์
|
||||
- [ลองใหม่](/th/concepts/retry) — พฤติกรรมการลองส่งข้อความใหม่
|
||||
- [คิว](/th/concepts/queue) — คิวประมวลผลข้อความ
|
||||
- [ช่องทาง](/th/channels) — การเชื่อมต่อกับแพลตฟอร์มส่งข้อความ
|
||||
- [การสตรีม](/th/concepts/streaming) — การส่งมอบข้อความแบบเรียลไทม์
|
||||
- [การลองใหม่](/th/concepts/retry) — พฤติกรรมการลองส่งมอบข้อความใหม่
|
||||
- [คิว](/th/concepts/queue) — คิวการประมวลผลข้อความ
|
||||
- [ช่องทาง](/th/channels) — การผสานรวมแพลตฟอร์มรับส่งข้อความ
|
||||
|
||||
@ -1,26 +1,26 @@
|
||||
---
|
||||
read_when:
|
||||
- การกำหนดค่าการอัปเดตความคืบหน้าที่มองเห็นได้สำหรับรอบการสนทนาที่ใช้เวลานาน
|
||||
- การเลือกระหว่างโหมดสตรีมมิงแบบบางส่วน แบบบล็อก และแบบความคืบหน้า
|
||||
- อธิบายวิธีที่ OpenClaw อัปเดตข้อความเดียวในช่องระหว่างที่งานกำลังดำเนินอยู่
|
||||
- การแก้ไขปัญหาร่างความคืบหน้า ข้อความความคืบหน้าแบบแยกอิสระ หรือกลไกสำรองสำหรับการสรุปผล
|
||||
summary: 'ฉบับร่างความคืบหน้า: ข้อความงานที่กำลังดำเนินการที่มองเห็นได้หนึ่งรายการ ซึ่งอัปเดตระหว่างที่ agent ทำงาน'
|
||||
- การกำหนดค่าการอัปเดตความคืบหน้าที่มองเห็นได้สำหรับรอบแชตที่ใช้เวลานาน
|
||||
- การเลือกระหว่างโหมดการสตรีมแบบบางส่วน แบบบล็อก และแบบความคืบหน้า
|
||||
- อธิบายว่า OpenClaw อัปเดตข้อความหนึ่งรายการในช่องทางอย่างไรขณะที่งานกำลังดำเนินอยู่
|
||||
- การแก้ไขปัญหาร่างความคืบหน้า ข้อความความคืบหน้าแบบแยกอิสระ หรือกลไกสำรองในการสรุปผล
|
||||
summary: 'ร่างความคืบหน้า: ข้อความแสดงงานระหว่างดำเนินการที่มองเห็นได้หนึ่งข้อความ ซึ่งอัปเดตระหว่างที่เอเจนต์ทำงาน'
|
||||
title: ฉบับร่างความคืบหน้า
|
||||
x-i18n:
|
||||
generated_at: "2026-05-04T02:23:44Z"
|
||||
generated_at: "2026-05-04T07:04:15Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 8ce19262800f1c3c3e505a3cf1d41ed5c3dffcbca168ad7b7afabdce62eee8fe
|
||||
source_hash: f78c07866cd7f613012a80a40413e5866c1dd2edd477088f9fc141347f5f3788
|
||||
source_path: concepts/progress-drafts.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
ร่างความคืบหน้าช่วยให้เทิร์นของ agent ที่ใช้เวลานานดูมีการดำเนินการอยู่ในแชต โดยไม่ทำให้
|
||||
บทสนทนากลายเป็นกองข้อความตอบกลับสถานะชั่วคราว
|
||||
ร่างความคืบหน้าทำให้เทิร์นของเอเจนต์ที่ทำงานนานดูมีชีวิตในแชต โดยไม่ทำให้
|
||||
บทสนทนากลายเป็นกองข้อความสถานะชั่วคราว
|
||||
|
||||
เมื่อเปิดใช้ร่างความคืบหน้า OpenClaw จะสร้างข้อความงานระหว่างทำที่มองเห็นได้หนึ่งข้อความ
|
||||
เฉพาะหลังจากเทิร์นนั้นพิสูจน์แล้วว่ากำลังทำงานจริง อัปเดตข้อความนั้นขณะที่
|
||||
agent อ่าน วางแผน เรียกเครื่องมือ หรือรอการอนุมัติ จากนั้นเปลี่ยนร่างนั้น
|
||||
เมื่อเปิดใช้ร่างความคืบหน้า OpenClaw จะสร้างข้อความงานที่กำลังดำเนินการที่มองเห็นได้หนึ่งข้อความ
|
||||
เฉพาะหลังจากที่เทิร์นพิสูจน์แล้วว่ากำลังทำงานจริง อัปเดตข้อความนั้นขณะที่
|
||||
เอเจนต์อ่าน วางแผน เรียกใช้เครื่องมือ หรือรอการอนุมัติ แล้วเปลี่ยนร่างนั้น
|
||||
เป็นคำตอบสุดท้ายเมื่อช่องทางสามารถทำได้อย่างปลอดภัย
|
||||
|
||||
```text
|
||||
@ -49,58 +49,57 @@ Shelling...
|
||||
}
|
||||
```
|
||||
|
||||
โดยทั่วไปเท่านี้ก็เพียงพอแล้ว OpenClaw จะเลือกป้ายกำกับคำเดียวโดยอัตโนมัติ รอ
|
||||
จนกว่างานจะใช้เวลาอย่างน้อยห้าวินาทีหรือปล่อยเหตุการณ์งานครั้งที่สอง เพิ่มบรรทัด
|
||||
ความคืบหน้าแบบกระชับขณะที่มีงานที่เป็นประโยชน์เกิดขึ้น และระงับข้อความความคืบหน้า
|
||||
แยกซ้ำๆ สำหรับเทิร์นนั้น
|
||||
โดยปกติเพียงเท่านี้ก็พอ OpenClaw จะเลือกป้ายกำกับแบบคำเดียวโดยอัตโนมัติ รอ
|
||||
จนกว่างานจะใช้เวลาอย่างน้อยห้าวินาทีหรือปล่อยเหตุการณ์งานที่สอง เพิ่มบรรทัด
|
||||
ความคืบหน้าแบบกะทัดรัดขณะที่มีงานที่เป็นประโยชน์เกิดขึ้น และระงับข้อความคุย
|
||||
ความคืบหน้าแบบเดี่ยวที่ซ้ำกันสำหรับเทิร์นนั้น
|
||||
|
||||
## สิ่งที่ผู้ใช้เห็น
|
||||
|
||||
ร่างความคืบหน้ามีสองส่วน:
|
||||
|
||||
| ส่วน | วัตถุประสงค์ |
|
||||
| ส่วน | วัตถุประสงค์ |
|
||||
| -------------- | --------------------------------------------------------------------------- |
|
||||
| ป้ายกำกับ | ชื่อสั้นๆ เช่น `Thinking...` หรือ `Shelling...` |
|
||||
| บรรทัดความคืบหน้า | อัปเดตการทำงานแบบกระชับโดยใช้ป้ายกำกับเครื่องมือและไอคอนเดียวกับเอาต์พุตแบบละเอียด |
|
||||
| ป้ายกำกับ | ชื่อสั้นๆ เช่น `Thinking...` หรือ `Shelling...` |
|
||||
| บรรทัดความคืบหน้า | การอัปเดตการทำงานแบบกะทัดรัด โดยใช้ป้ายกำกับและไอคอนเครื่องมือเดียวกับเอาต์พุตแบบละเอียด |
|
||||
|
||||
ป้ายกำกับจะปรากฏหลังจาก agent เริ่มงานที่มีความหมาย และยังคงทำงานอยู่
|
||||
เป็นเวลาห้าวินาทีหรือปล่อยเหตุการณ์งานครั้งที่สอง การตอบกลับที่เป็นข้อความล้วนจะไม่
|
||||
แสดงร่างความคืบหน้า บรรทัดความคืบหน้าจะถูกเพิ่มเฉพาะเมื่อ agent ปล่อย
|
||||
อัปเดตงานที่เป็นประโยชน์ เช่น `🛠️ Exec`, `🔎 Web Search` หรือ `✍️ Write: to /tmp/file`
|
||||
โดยค่าเริ่มต้นจะใช้โหมดอธิบายแบบกระชับเดียวกับ `/verbose`; ตั้งค่า
|
||||
`agents.defaults.toolProgressDetail: "raw"` เมื่อดีบักและคุณต้องการให้ต่อท้าย
|
||||
คำสั่ง/รายละเอียดดิบด้วย
|
||||
คำตอบสุดท้ายจะแทนที่ร่างเมื่อทำได้ มิฉะนั้น
|
||||
OpenClaw จะส่งคำตอบสุดท้ายตามปกติ และล้างหรือตัดการอัปเดต
|
||||
ร่างตาม transport ของช่องทางนั้น
|
||||
ป้ายกำกับจะปรากฏหลังจากเอเจนต์เริ่มงานที่มีความหมาย และยังคงยุ่งอยู่
|
||||
เป็นเวลาห้าวินาทีหรือปล่อยเหตุการณ์งานที่สอง คำตอบแบบข้อความล้วนเท่านั้นจะไม่
|
||||
แสดงร่างความคืบหน้า บรรทัดความคืบหน้าจะถูกเพิ่มเฉพาะเมื่อเอเจนต์ปล่อยการอัปเดต
|
||||
งานที่เป็นประโยชน์ เช่น `🛠️ Exec`, `🔎 Web Search` หรือ `✍️ Write: to /tmp/file`
|
||||
โดยค่าเริ่มต้น บรรทัดเหล่านี้ใช้โหมดอธิบายแบบกะทัดรัดเดียวกับ `/verbose`; ตั้งค่า
|
||||
`agents.defaults.toolProgressDetail: "raw"` เมื่อดีบักและคุณต้องการให้ผนวกคำสั่ง/รายละเอียดดิบด้วย
|
||||
คำตอบสุดท้ายจะแทนที่ร่างเมื่อเป็นไปได้ มิฉะนั้น
|
||||
OpenClaw จะส่งคำตอบสุดท้ายตามปกติ และล้างหรือหยุดอัปเดตร่าง
|
||||
ตามการขนส่งของช่องทางนั้น
|
||||
|
||||
## เลือกโหมด
|
||||
|
||||
`channels.<channel>.streaming.mode` ควบคุมลักษณะงานระหว่างทำที่มองเห็นได้:
|
||||
`channels.<channel>.streaming.mode` ควบคุมพฤติกรรมงานที่กำลังดำเนินการที่มองเห็นได้:
|
||||
|
||||
| โหมด | เหมาะสำหรับ | สิ่งที่ปรากฏในแชต |
|
||||
| โหมด | เหมาะที่สุดสำหรับ | สิ่งที่ปรากฏในแชต |
|
||||
| ---------- | -------------------------------- | ------------------------------------------------- |
|
||||
| `off` | ช่องทางที่ต้องการความเงียบ | เฉพาะคำตอบสุดท้าย |
|
||||
| `partial` | การดูข้อความคำตอบปรากฏขึ้น | ร่างหนึ่งฉบับที่แก้ไขด้วยข้อความคำตอบล่าสุด |
|
||||
| `block` | ก้อนพรีวิวคำตอบที่ใหญ่ขึ้น | พรีวิวหนึ่งรายการที่อัปเดตหรือต่อท้ายเป็นก้อนใหญ่ขึ้น |
|
||||
| `progress` | เทิร์นที่ใช้เครื่องมือมากหรือทำงานนาน | ร่างสถานะหนึ่งฉบับ แล้วตามด้วยคำตอบสุดท้าย |
|
||||
| `off` | ช่องทางที่ต้องการความเงียบ | เฉพาะคำตอบสุดท้าย |
|
||||
| `partial` | การดูข้อความคำตอบค่อยๆ ปรากฏ | ร่างหนึ่งข้อความที่แก้ไขด้วยข้อความคำตอบล่าสุด |
|
||||
| `block` | ชิ้นส่วนตัวอย่างคำตอบที่ใหญ่ขึ้น | ตัวอย่างหนึ่งรายการที่อัปเดตหรือผนวกเป็นชิ้นใหญ่ขึ้น |
|
||||
| `progress` | เทิร์นที่ใช้เครื่องมือมากหรือทำงานนาน | ร่างสถานะหนึ่งข้อความ แล้วตามด้วยคำตอบสุดท้าย |
|
||||
|
||||
เลือก `progress` เมื่อผู้ใช้ให้ความสำคัญกับ "กำลังเกิดอะไรขึ้น" มากกว่าการดู
|
||||
ข้อความคำตอบสตรีมทีละ token
|
||||
เลือก `progress` เมื่อผู้ใช้สนใจว่า "กำลังเกิดอะไรขึ้น" มากกว่าการดู
|
||||
ข้อความคำตอบสตรีมทีละโทเคน
|
||||
|
||||
เลือก `partial` เมื่อคำตอบเองเป็นสัญญาณความคืบหน้า
|
||||
|
||||
เลือก `block` เมื่อคุณต้องการอัปเดตร่างพรีวิวเป็นก้อนข้อความที่ใหญ่ขึ้น บน
|
||||
Discord และ Telegram, `streaming.mode: "block"` ยังคงเป็นการสตรีมพรีวิว ไม่ใช่
|
||||
การส่งแบบบล็อกปกติ ใช้ `streaming.block.enabled` หรือ
|
||||
`blockStreaming` แบบเก่าเมื่อคุณต้องการการตอบกลับแบบบล็อกปกติ
|
||||
เลือก `block` เมื่อคุณต้องการการอัปเดตร่างตัวอย่างเป็นชิ้นข้อความที่ใหญ่ขึ้น บน
|
||||
Discord และ Telegram, `streaming.mode: "block"` ยังเป็นการสตรีมตัวอย่าง ไม่ใช่
|
||||
การส่งแบบบล็อกปกติ ใช้ `streaming.block.enabled` หรือแบบเดิม
|
||||
`blockStreaming` เมื่อคุณต้องการคำตอบแบบบล็อกปกติ
|
||||
|
||||
## กำหนดค่าป้ายกำกับ
|
||||
|
||||
ป้ายกำกับความคืบหน้าอยู่ภายใต้ `channels.<channel>.streaming.progress`
|
||||
|
||||
ป้ายกำกับเริ่มต้นคือ `auto` ซึ่งเลือกจากชุดป้ายกำกับในตัวของ OpenClaw
|
||||
แบบคำเดียวตามด้วยจุดไข่ปลา:
|
||||
ที่เป็นคำเดียวพร้อมจุดไข่ปลา:
|
||||
|
||||
```text
|
||||
Thinking...
|
||||
@ -180,8 +179,8 @@ Surfacing...
|
||||
## ควบคุมบรรทัดความคืบหน้า
|
||||
|
||||
บรรทัดความคืบหน้าเปิดใช้โดยค่าเริ่มต้นในโหมดความคืบหน้า บรรทัดเหล่านี้มาจากเหตุการณ์การทำงานจริง:
|
||||
การเริ่มใช้เครื่องมือ การอัปเดตรายการ แผนงาน การอนุมัติ เอาต์พุตคำสั่ง สรุป
|
||||
patch และกิจกรรม agent ที่คล้ายกัน
|
||||
การเริ่มเครื่องมือ การอัปเดตรายการ แผนงาน การอนุมัติ เอาต์พุตคำสั่ง สรุปแพตช์
|
||||
และกิจกรรมเอเจนต์ที่คล้ายกัน
|
||||
|
||||
OpenClaw ใช้ตัวจัดรูปแบบเดียวกันสำหรับร่างความคืบหน้าและ `/verbose`:
|
||||
|
||||
@ -195,17 +194,17 @@ OpenClaw ใช้ตัวจัดรูปแบบเดียวกัน
|
||||
}
|
||||
```
|
||||
|
||||
`"explain"` เป็นค่าเริ่มต้น และทำให้ร่างมีความคงที่ด้วยป้ายกำกับกระชับ เช่น
|
||||
`🛠️ Exec: check JS syntax for /tmp/app.js` `"raw"` จะต่อท้าย
|
||||
คำสั่ง/รายละเอียดพื้นฐานเมื่อมี ซึ่งมีประโยชน์ขณะดีบักแต่รบกวนมากกว่าใน
|
||||
`"explain"` เป็นค่าเริ่มต้นและทำให้ร่างนิ่งด้วยป้ายกำกับกระชับ เช่น
|
||||
`🛠️ Exec: check JS syntax for /tmp/app.js` ส่วน `"raw"` จะผนวก
|
||||
คำสั่ง/รายละเอียดเบื้องหลังเมื่อมี ซึ่งมีประโยชน์ขณะดีบักแต่มีเสียงรบกวนมากกว่าใน
|
||||
แชต
|
||||
|
||||
ตัวอย่างเช่น คำสั่งเดียวกันจะปรากฏต่างกันตามโหมดรายละเอียด:
|
||||
|
||||
| โหมด | บรรทัดความคืบหน้า |
|
||||
| โหมด | บรรทัดความคืบหน้า |
|
||||
| --------- | -------------------------------------------------------------------- |
|
||||
| `explain` | `🛠️ Exec: check JS syntax for /tmp/app.js` |
|
||||
| `raw` | `🛠️ Exec: check JS syntax for /tmp/app.js, node --check /tmp/app.js` |
|
||||
| `explain` | `🛠️ Exec: check JS syntax for /tmp/app.js` |
|
||||
| `raw` | `🛠️ Exec: check JS syntax for /tmp/app.js, node --check /tmp/app.js` |
|
||||
|
||||
จำกัดจำนวนบรรทัดที่ยังมองเห็นได้:
|
||||
|
||||
@ -224,7 +223,34 @@ OpenClaw ใช้ตัวจัดรูปแบบเดียวกัน
|
||||
}
|
||||
```
|
||||
|
||||
คงร่างความคืบหน้าเดี่ยวไว้ แต่ซ่อนบรรทัดเครื่องมือและงาน:
|
||||
บรรทัดความคืบหน้าจะถูกบีบอัดโดยอัตโนมัติเพื่อลดการจัดเรียงฟองแชตใหม่ขณะที่มีการแก้ไขร่าง
|
||||
|
||||
OpenClaw ตัดบรรทัดความคืบหน้าที่ยาวโดยค่าเริ่มต้น เพื่อไม่ให้การแก้ไขร่างซ้ำๆ
|
||||
ตัดบรรทัดต่างกันทุกครั้งที่อัปเดต คำนำหน้ายังคงอ่านได้ และรายละเอียดที่ยาว
|
||||
เช่น พาธหรือคำสั่งดิบจะถูกย่อด้วยจุดไข่ปลา
|
||||
|
||||
Slack สามารถแสดงบรรทัดความคืบหน้าเป็นฟิลด์ Block Kit แบบมีโครงสร้างแทน
|
||||
เนื้อความข้อความเดียว:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
slack: {
|
||||
streaming: {
|
||||
mode: "progress",
|
||||
progress: {
|
||||
render: "rich",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
การแสดงผลแบบ rich ยังคงมี fallback แบบข้อความล้วนเดียวกัน เพื่อให้ช่องทางและไคลเอนต์ที่
|
||||
ไม่รองรับรูปแบบที่สมบูรณ์กว่า ยังสามารถแสดงข้อความความคืบหน้าแบบกะทัดรัดได้
|
||||
|
||||
คงร่างความคืบหน้าเดียวไว้แต่ซ่อนบรรทัดเครื่องมือและงาน:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -241,77 +267,77 @@ OpenClaw ใช้ตัวจัดรูปแบบเดียวกัน
|
||||
}
|
||||
```
|
||||
|
||||
ด้วย `toolProgress: false` OpenClaw ยังคงระงับข้อความ
|
||||
ความคืบหน้าของเครื่องมือแบบแยกเดิมสำหรับเทิร์นนั้น ช่องทางจะยังดูเงียบ
|
||||
จนกว่าจะมีคำตอบสุดท้าย ยกเว้นป้ายกำกับหากมีการกำหนดค่าไว้
|
||||
เมื่อใช้ `toolProgress: false` OpenClaw ยังคงระงับข้อความ
|
||||
ความคืบหน้าของเครื่องมือแบบเดี่ยวรุ่นเก่าสำหรับเทิร์นนั้น ช่องทางจะยังคงเงียบในเชิงภาพจนกว่า
|
||||
คำตอบสุดท้าย ยกเว้นป้ายกำกับถ้ามีการกำหนดค่าไว้
|
||||
|
||||
## พฤติกรรมของช่องทาง
|
||||
|
||||
แต่ละช่องทางใช้ transport ที่สะอาดที่สุดที่รองรับ:
|
||||
แต่ละช่องทางใช้การขนส่งที่สะอาดที่สุดที่รองรับ:
|
||||
|
||||
| ช่องทาง | transport ความคืบหน้า | หมายเหตุ |
|
||||
| ช่องทาง | การขนส่งความคืบหน้า | หมายเหตุ |
|
||||
| --------------- | -------------------------------------- | --------------------------------------------------------------------- |
|
||||
| Discord | ส่งหนึ่งข้อความ แล้วแก้ไขข้อความนั้น | ข้อความสุดท้ายจะแก้ไขในตำแหน่งเดิมเมื่อพอดีกับข้อความพรีวิวที่ปลอดภัยหนึ่งข้อความ |
|
||||
| Matrix | ส่งหนึ่ง event แล้วแก้ไข event นั้น | การกำหนดค่าสตรีมระดับบัญชีควบคุมร่างระดับบัญชี |
|
||||
| Microsoft Teams | สตรีม Teams แบบ native ในแชตส่วนตัว | `streaming.mode: "block"` แมปไปยังการส่งแบบบล็อกของ Teams |
|
||||
| Slack | สตรีมแบบ native หรือโพสต์ร่างที่แก้ไขได้ | ความพร้อมของ thread ส่งผลต่อว่าสามารถใช้สตรีมแบบ native ได้หรือไม่ |
|
||||
| Telegram | ส่งหนึ่งข้อความ แล้วแก้ไขข้อความนั้น | ร่างเก่าที่มองเห็นได้อาจถูกแทนที่ เพื่อให้เวลาประทับสุดท้ายยังมีประโยชน์ |
|
||||
| Mattermost | โพสต์ร่างที่แก้ไขได้ | กิจกรรมเครื่องมือถูกรวมเข้าในโพสต์แบบร่างเดียวกัน |
|
||||
| Discord | ส่งข้อความหนึ่งข้อความ แล้วแก้ไขข้อความนั้น | ข้อความสุดท้ายแก้ไขแทนที่เดิมเมื่อพอดีกับข้อความตัวอย่างที่ปลอดภัยหนึ่งข้อความ |
|
||||
| Matrix | ส่งเหตุการณ์หนึ่งรายการ แล้วแก้ไขเหตุการณ์นั้น | การกำหนดค่าสตรีมระดับบัญชีควบคุมร่างระดับบัญชี |
|
||||
| Microsoft Teams | สตรีม Teams แบบเนทีฟในแชตส่วนตัว | `streaming.mode: "block"` แมปไปยังการส่งแบบบล็อกของ Teams |
|
||||
| Slack | สตรีมเนทีฟหรือโพสต์ร่างที่แก้ไขได้ | ความพร้อมใช้งานของเธรดมีผลต่อว่าจะใช้การสตรีมเนทีฟได้หรือไม่ |
|
||||
| Telegram | ส่งข้อความหนึ่งข้อความ แล้วแก้ไขข้อความนั้น | ร่างเก่าที่มองเห็นได้อาจถูกแทนที่เพื่อให้เวลาประทับสุดท้ายยังมีประโยชน์ |
|
||||
| Mattermost | โพสต์ร่างที่แก้ไขได้ | กิจกรรมเครื่องมือถูกรวมเข้าในโพสต์แบบร่างเดียวกัน |
|
||||
|
||||
ช่องทางที่ไม่มีการรองรับการแก้ไขอย่างปลอดภัยมักถอยกลับไปใช้ตัวบ่งชี้การพิมพ์หรือ
|
||||
ช่องทางที่ไม่รองรับการแก้ไขอย่างปลอดภัยมักจะ fallback ไปเป็นตัวบ่งชี้การพิมพ์หรือ
|
||||
การส่งเฉพาะคำตอบสุดท้าย
|
||||
|
||||
## การปิดท้าย
|
||||
## การสรุปผล
|
||||
|
||||
เมื่อคำตอบสุดท้ายพร้อม OpenClaw จะพยายามรักษาแชตให้สะอาด:
|
||||
เมื่อคำตอบสุดท้ายพร้อม OpenClaw จะพยายามทำให้แชตสะอาด:
|
||||
|
||||
- หากร่างสามารถกลายเป็นคำตอบสุดท้ายได้อย่างปลอดภัย OpenClaw จะแก้ไขร่างนั้นในตำแหน่งเดิม
|
||||
- หากช่องทางใช้การสตรีมความคืบหน้าแบบ native OpenClaw จะปิดท้ายสตรีมนั้น
|
||||
เมื่อ transport แบบ native รับข้อความสุดท้าย
|
||||
- หากคำตอบสุดท้ายมีสื่อ พรอมต์อนุมัติ เป้าหมายการตอบกลับที่ระบุชัด
|
||||
มีจำนวนก้อนมากเกินไป หรือการแก้ไข/ส่งล้มเหลว OpenClaw จะส่งคำตอบสุดท้ายผ่าน
|
||||
เส้นทางการส่งปกติของช่องทาง
|
||||
- หากร่างสามารถกลายเป็นคำตอบสุดท้ายได้อย่างปลอดภัย OpenClaw จะแก้ไขร่างนั้นแทนที่เดิม
|
||||
- หากช่องทางใช้การสตรีมความคืบหน้าแบบเนทีฟ OpenClaw จะสรุปสตรีมนั้น
|
||||
เมื่อการขนส่งเนทีฟยอมรับข้อความสุดท้าย
|
||||
- หากคำตอบสุดท้ายมีสื่อ พรอมป์ขออนุมัติ เป้าหมายการตอบกลับที่ระบุชัดเจน
|
||||
มีจำนวนชิ้นมากเกินไป หรือแก้ไข/ส่งไม่สำเร็จ OpenClaw จะส่งคำตอบสุดท้ายผ่าน
|
||||
เส้นทางการส่งของช่องทางปกติ
|
||||
|
||||
เส้นทาง fallback เป็นความตั้งใจ การส่งคำตอบสุดท้ายใหม่ดีกว่า
|
||||
การทำข้อความหาย ตอบผิด thread หรือเขียนทับร่างด้วย payload ที่ช่องทาง
|
||||
ไม่สามารถแสดงแทนได้อย่างปลอดภัย
|
||||
เส้นทาง fallback เป็นสิ่งที่ตั้งใจไว้ การส่งคำตอบสุดท้ายใหม่ดีกว่า
|
||||
การสูญเสียข้อความ การตอบผิดเธรด หรือการเขียนทับร่างด้วย payload ที่ช่องทาง
|
||||
ไม่สามารถแทนได้อย่างปลอดภัย
|
||||
|
||||
## การแก้ปัญหา
|
||||
## การแก้ไขปัญหา
|
||||
|
||||
**ฉันเห็นเฉพาะคำตอบสุดท้าย**
|
||||
|
||||
ตรวจสอบว่า `channels.<channel>.streaming.mode` ตั้งค่าเป็น `progress` สำหรับ
|
||||
บัญชีหรือช่องทางที่จัดการข้อความนั้น เส้นทางบางแบบของกลุ่มหรือการตอบกลับแบบอ้างอิงอาจ
|
||||
ปิดใช้พรีวิวร่างสำหรับเทิร์นหนึ่งเมื่อช่องทางไม่สามารถแก้ไขข้อความที่ถูกต้องได้อย่างปลอดภัย
|
||||
ตรวจสอบว่า `channels.<channel>.streaming.mode` ถูกตั้งค่าเป็น `progress` สำหรับ
|
||||
บัญชีหรือช่องทางที่จัดการข้อความนั้น เส้นทางกลุ่มหรือการตอบกลับแบบอ้างอิงบางอย่างอาจ
|
||||
ปิดใช้ตัวอย่างร่างสำหรับเทิร์นหนึ่งเมื่อช่องทางไม่สามารถแก้ไขข้อความที่ถูกต้องได้อย่างปลอดภัย
|
||||
|
||||
**ฉันเห็นป้ายกำกับแต่ไม่มีบรรทัดเครื่องมือ**
|
||||
|
||||
ตรวจสอบ `streaming.progress.toolProgress` หากเป็น `false` OpenClaw จะคง
|
||||
พฤติกรรมร่างเดี่ยวไว้ แต่ซ่อนบรรทัดความคืบหน้าของเครื่องมือและงาน
|
||||
พฤติกรรมร่างเดียวไว้แต่ซ่อนบรรทัดความคืบหน้าของเครื่องมือและงาน
|
||||
|
||||
**ฉันเห็นข้อความสุดท้ายใหม่แทนร่างที่ถูกแก้ไข**
|
||||
**ฉันเห็นข้อความสุดท้ายใหม่แทนที่จะเป็นร่างที่แก้ไขแล้ว**
|
||||
|
||||
นั่นคือ fallback เพื่อความปลอดภัย สิ่งนี้อาจเกิดขึ้นกับการตอบกลับที่มีสื่อ คำตอบยาว
|
||||
เป้าหมายการตอบกลับที่ระบุชัด ร่าง Telegram เก่า เป้าหมาย thread ของ Slack ที่ขาดหาย
|
||||
ข้อความพรีวิวที่ถูกลบ หรือการปิดท้ายสตรีมแบบ native ที่ล้มเหลว
|
||||
นั่นคือ fallback ด้านความปลอดภัย อาจเกิดขึ้นกับคำตอบที่มีสื่อ คำตอบยาว
|
||||
เป้าหมายการตอบกลับที่ระบุชัดเจน ร่าง Telegram เก่า เป้าหมายเธรด Slack ที่หายไป
|
||||
ข้อความตัวอย่างที่ถูกลบ หรือการสรุปสตรีมเนทีฟที่ล้มเหลว
|
||||
|
||||
**ฉันยังเห็นข้อความความคืบหน้าแบบแยกอยู่**
|
||||
**ฉันยังเห็นข้อความความคืบหน้าแบบเดี่ยว**
|
||||
|
||||
โหมดความคืบหน้าจะระงับข้อความความคืบหน้าของเครื่องมือแบบแยกตามค่าเริ่มต้นเมื่อร่าง
|
||||
กำลังทำงานอยู่ หากข้อความแยกยังปรากฏ ให้ตรวจสอบว่าเทิร์นนั้นกำลัง
|
||||
โหมดความคืบหน้าจะระงับข้อความความคืบหน้าของเครื่องมือแบบเดี่ยวเริ่มต้นเมื่อร่าง
|
||||
กำลังใช้งานอยู่ หากข้อความแบบเดี่ยวยังปรากฏ ให้ตรวจสอบว่าเทิร์นนั้นกำลัง
|
||||
ใช้โหมดความคืบหน้าจริง ไม่ใช่ `streaming.mode: "off"` หรือเส้นทางช่องทางที่
|
||||
ไม่สามารถสร้างร่างสำหรับข้อความนั้นได้
|
||||
|
||||
**Teams ทำงานต่างจาก Discord หรือ Telegram**
|
||||
|
||||
Microsoft Teams ใช้สตรีมแบบ native ในแชตส่วนตัว แทน transport พรีวิว
|
||||
แบบส่งแล้วแก้ไขทั่วไป Teams ยังถือว่า `streaming.mode: "block"` เป็น
|
||||
การส่งแบบบล็อกของ Teams เพราะไม่มีโหมดบล็อกพรีวิวร่างแบบเดียวกับ
|
||||
ที่ Discord และ Telegram ใช้
|
||||
Microsoft Teams ใช้สตรีมเนทีฟในแชตส่วนตัวแทนการขนส่งตัวอย่างแบบ
|
||||
ส่งแล้วแก้ไขทั่วไป นอกจากนี้ Teams ยังถือว่า `streaming.mode: "block"` เป็น
|
||||
การส่งแบบบล็อกของ Teams เพราะไม่มีโหมดบล็อกตัวอย่างร่างแบบเดียวกับที่
|
||||
Discord และ Telegram ใช้
|
||||
|
||||
## ที่เกี่ยวข้อง
|
||||
|
||||
- [การสตรีมและการแบ่งก้อน](/th/concepts/streaming)
|
||||
- [การสตรีมและการแบ่งชิ้น](/th/concepts/streaming)
|
||||
- [ข้อความ](/th/concepts/messages)
|
||||
- [การกำหนดค่าช่องทาง](/th/gateway/config-channels)
|
||||
- [Discord](/th/channels/discord)
|
||||
|
||||
@ -1,33 +1,34 @@
|
||||
---
|
||||
read_when:
|
||||
- ทำความเข้าใจว่าสแต็ก QA เชื่อมโยงกันอย่างไร
|
||||
- การขยาย qa-lab, qa-channel หรืออะแดปเตอร์การขนส่ง
|
||||
- การเพิ่มสถานการณ์ QA ที่อิงกับรีโป
|
||||
- การสร้างระบบอัตโนมัติด้านการประกันคุณภาพที่สมจริงยิ่งขึ้นสำหรับแดชบอร์ด Gateway
|
||||
summary: 'ภาพรวมสแต็ก QA: qa-lab, qa-channel, สถานการณ์ที่อิง repo, ช่องทางการขนส่งแบบ live, อะแดปเตอร์การขนส่ง และการรายงาน.'
|
||||
title: ภาพรวมการประกันคุณภาพ
|
||||
- การขยาย qa-lab, qa-channel หรืออะแดปเตอร์การรับส่งข้อมูล
|
||||
- การเพิ่มสถานการณ์ QA ที่อ้างอิงจากรีโป
|
||||
- การสร้างระบบอัตโนมัติ QA ที่สมจริงยิ่งขึ้นรอบแดชบอร์ด Gateway
|
||||
summary: 'ภาพรวมสแต็ก QA: qa-lab, qa-channel, สถานการณ์ที่รองรับด้วยรีโป, เลนการส่งผ่านแบบสด, อะแดปเตอร์การส่งผ่าน และการรายงาน.'
|
||||
title: ภาพรวม QA
|
||||
x-i18n:
|
||||
generated_at: "2026-05-04T02:23:57Z"
|
||||
generated_at: "2026-05-04T07:05:07Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 0b376767b967a51cc8a45ca5ce420f78067b52e6368d2abe921ffed533f6f9ba
|
||||
source_hash: 067f5aa0831724659ae36d548ef2e7bd28b40aad9cef45f325a01a2748003b29
|
||||
source_path: concepts/qa-e2e-automation.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
สแตก QA ส่วนตัวมีไว้เพื่อทดสอบ OpenClaw ในรูปแบบที่สมจริงและมีลักษณะเหมือนช่องทางมากกว่าที่ unit test เดี่ยวจะทำได้
|
||||
Private QA stack มีไว้เพื่อทดสอบ OpenClaw ในลักษณะที่สมจริงกว่าและมีรูปทรงตามช่องทาง
|
||||
มากกว่าที่ unit test เดียวจะทำได้
|
||||
|
||||
ส่วนประกอบปัจจุบัน:
|
||||
ชิ้นส่วนปัจจุบัน:
|
||||
|
||||
- `extensions/qa-channel`: ช่องทางข้อความสังเคราะห์ที่มีพื้นผิว DM, ช่องทาง, เธรด,
|
||||
รีแอ็กชัน, การแก้ไข และการลบ
|
||||
- `extensions/qa-channel`: ช่องทางข้อความสังเคราะห์ที่มีพื้นผิว DM, channel, thread,
|
||||
reaction, edit และ delete
|
||||
- `extensions/qa-lab`: UI ดีบักเกอร์และบัส QA สำหรับสังเกต transcript,
|
||||
แทรกข้อความขาเข้า และส่งออกรายงาน Markdown
|
||||
- `extensions/qa-matrix`, Plugin ตัวรันเนอร์ในอนาคต: อะแดปเตอร์ live-transport ที่
|
||||
ขับช่องทางจริงภายใน Gateway QA ย่อย
|
||||
- `qa/`: แอสเซต seed ที่รองรับโดยรีโปสำหรับงาน kickoff และสถานการณ์ QA
|
||||
- `extensions/qa-matrix`, Plugin รันเนอร์ในอนาคต: อะแดปเตอร์ live-transport ที่
|
||||
ขับช่องทางจริงภายใน child QA gateway
|
||||
- `qa/`: แอสเซ็ต seed ที่อิงกับ repo สำหรับงานเริ่มต้นและสถานการณ์ QA
|
||||
baseline
|
||||
- [Mantis](/th/concepts/mantis): การตรวจสอบแบบ live ก่อนและหลังสำหรับบั๊กที่
|
||||
- [Mantis](/th/concepts/mantis): การยืนยันสดก่อนและหลังสำหรับบั๊กที่
|
||||
ต้องใช้ transport จริง, ภาพหน้าจอเบราว์เซอร์, สถานะ VM และหลักฐาน PR
|
||||
|
||||
## พื้นผิวคำสั่ง
|
||||
@ -35,33 +36,33 @@ x-i18n:
|
||||
ทุกโฟลว์ QA ทำงานภายใต้ `pnpm openclaw qa <subcommand>` หลายรายการมี alias สคริปต์ `pnpm qa:*`;
|
||||
รองรับทั้งสองรูปแบบ
|
||||
|
||||
| คำสั่ง | วัตถุประสงค์ |
|
||||
| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `qa run` | self-check QA ที่บันเดิลมา; เขียนรายงาน Markdown |
|
||||
| `qa suite` | รันสถานการณ์ที่รองรับโดยรีโปกับเลน Gateway QA Alias: `pnpm openclaw qa suite --runner multipass` สำหรับ Linux VM แบบใช้แล้วทิ้ง |
|
||||
| `qa coverage` | พิมพ์ inventory ความครอบคลุมของสถานการณ์ใน markdown (`--json` สำหรับเอาต์พุตสำหรับเครื่อง) |
|
||||
| `qa parity-report` | เปรียบเทียบไฟล์ `qa-suite-summary.json` สองไฟล์และเขียนรายงาน parity แบบ agentic |
|
||||
| `qa character-eval` | รันสถานการณ์ QA ด้านคาแรกเตอร์กับโมเดล live หลายตัวพร้อมรายงานที่มีการตัดสิน ดู [การรายงาน](#reporting) |
|
||||
| `qa manual` | รัน prompt แบบครั้งเดียวกับเลน provider/model ที่เลือก |
|
||||
| `qa ui` | เริ่ม UI ดีบักเกอร์ QA และบัส QA ภายในเครื่อง (alias: `pnpm qa:lab:ui`) |
|
||||
| `qa docker-build-image` | สร้างอิมเมจ Docker QA ที่ prebake ไว้ |
|
||||
| `qa docker-scaffold` | เขียน scaffold docker-compose สำหรับแดชบอร์ด QA + เลน Gateway |
|
||||
| `qa up` | สร้างไซต์ QA, เริ่มสแตกที่รองรับด้วย Docker, พิมพ์ URL (alias: `pnpm qa:lab:up`; variant `:fast` เพิ่ม `--use-prebuilt-image --bind-ui-dist --skip-ui-build`) |
|
||||
| `qa aimock` | เริ่มเฉพาะเซิร์ฟเวอร์ provider AIMock |
|
||||
| `qa mock-openai` | เริ่มเฉพาะเซิร์ฟเวอร์ provider `mock-openai` ที่รู้จักสถานการณ์ |
|
||||
| `qa credentials doctor` / `add` / `list` / `remove` | จัดการพูล credential Convex ที่ใช้ร่วมกัน |
|
||||
| `qa matrix` | เลน transport live กับ homeserver Tuwunel แบบใช้แล้วทิ้ง ดู [Matrix QA](/th/concepts/qa-matrix) |
|
||||
| `qa telegram` | เลน transport live กับกลุ่ม Telegram ส่วนตัวจริง |
|
||||
| `qa discord` | เลน transport live กับช่อง guild Discord ส่วนตัวจริง |
|
||||
| `qa slack` | เลน transport live กับช่อง Slack ส่วนตัวจริง |
|
||||
| `qa mantis` | ตัวรันตรวจสอบก่อนและหลังสำหรับบั๊ก transport live พร้อมหลักฐาน status-reactions ของ Discord และ smoke เดสก์ท็อป/เบราว์เซอร์ Crabbox ดู [Mantis](/th/concepts/mantis) |
|
||||
| คำสั่ง | วัตถุประสงค์ |
|
||||
| --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `qa run` | self-check QA ที่บันเดิลมา; เขียนรายงาน Markdown |
|
||||
| `qa suite` | รันสถานการณ์ที่อิงกับ repo กับเลน QA gateway Alias: `pnpm openclaw qa suite --runner multipass` สำหรับ Linux VM แบบใช้แล้วทิ้ง |
|
||||
| `qa coverage` | พิมพ์ inventory coverage ของสถานการณ์ในรูปแบบ markdown (`--json` สำหรับเอาต์พุตเครื่อง) |
|
||||
| `qa parity-report` | เปรียบเทียบไฟล์ `qa-suite-summary.json` สองไฟล์และเขียนรายงาน agentic parity |
|
||||
| `qa character-eval` | รันสถานการณ์ character QA ข้ามโมเดลสดหลายตัวพร้อมรายงานที่มีการตัดสิน ดู [การรายงาน](#reporting) |
|
||||
| `qa manual` | รัน prompt แบบครั้งเดียวกับเลน provider/model ที่เลือกไว้ |
|
||||
| `qa ui` | เริ่ม UI ดีบักเกอร์ QA และบัส QA ในเครื่อง (alias: `pnpm qa:lab:ui`) |
|
||||
| `qa docker-build-image` | สร้างอิมเมจ QA Docker ที่อบไว้ล่วงหน้า |
|
||||
| `qa docker-scaffold` | เขียน scaffold docker-compose สำหรับแดชบอร์ด QA + เลน gateway |
|
||||
| `qa up` | สร้างไซต์ QA, เริ่ม stack ที่อิงกับ Docker, พิมพ์ URL (alias: `pnpm qa:lab:up`; variant `:fast` เพิ่ม `--use-prebuilt-image --bind-ui-dist --skip-ui-build`) |
|
||||
| `qa aimock` | เริ่มเฉพาะเซิร์ฟเวอร์ provider AIMock |
|
||||
| `qa mock-openai` | เริ่มเฉพาะเซิร์ฟเวอร์ provider `mock-openai` ที่รับรู้สถานการณ์ |
|
||||
| `qa credentials doctor` / `add` / `list` / `remove` | จัดการ pool credential Convex ที่ใช้ร่วมกัน |
|
||||
| `qa matrix` | เลน live transport กับ Tuwunel homeserver แบบใช้แล้วทิ้ง ดู [Matrix QA](/th/concepts/qa-matrix) |
|
||||
| `qa telegram` | เลน live transport กับกลุ่ม Telegram ส่วนตัวจริง |
|
||||
| `qa discord` | เลน live transport กับช่อง guild Discord ส่วนตัวจริง |
|
||||
| `qa slack` | เลน live transport กับช่อง Slack ส่วนตัวจริง |
|
||||
| `qa mantis` | รันเนอร์การยืนยันก่อนและหลังสำหรับบั๊ก live transport พร้อมหลักฐาน status-reactions ของ Discord, smoke เดสก์ท็อป/เบราว์เซอร์ Crabbox และ smoke Slack-in-VNC ดู [Mantis](/th/concepts/mantis) |
|
||||
|
||||
## โฟลว์ผู้ปฏิบัติการ
|
||||
|
||||
โฟลว์ผู้ปฏิบัติการ QA ปัจจุบันเป็นไซต์ QA แบบสองพาเนล:
|
||||
โฟลว์ผู้ปฏิบัติการ QA ปัจจุบันคือไซต์ QA แบบสอง pane:
|
||||
|
||||
- ซ้าย: แดชบอร์ด Gateway (Control UI) พร้อม agent
|
||||
- ขวา: QA Lab แสดง transcript แบบคล้าย Slack และแผนสถานการณ์
|
||||
- ขวา: QA Lab แสดง transcript แบบ Slack-ish และแผนสถานการณ์
|
||||
|
||||
รันด้วย:
|
||||
|
||||
@ -69,12 +70,13 @@ x-i18n:
|
||||
pnpm qa:lab:up
|
||||
```
|
||||
|
||||
คำสั่งนั้นสร้างไซต์ QA, เริ่มเลน Gateway ที่รองรับด้วย Docker และเปิดหน้า
|
||||
QA Lab ซึ่งผู้ปฏิบัติการหรือ automation loop สามารถให้ภารกิจ QA กับ agent,
|
||||
สังเกตพฤติกรรมช่องทางจริง และบันทึกว่าสิ่งใดทำงาน ล้มเหลว หรือยังถูกบล็อก
|
||||
คำสั่งนี้สร้างไซต์ QA, เริ่มเลน gateway ที่อิงกับ Docker และเปิดเผยหน้า
|
||||
QA Lab ที่ผู้ปฏิบัติการหรือลูปอัตโนมัติสามารถมอบภารกิจ QA ให้ agent,
|
||||
สังเกตพฤติกรรมช่องทางจริง และบันทึกสิ่งที่ทำงานได้ ล้มเหลว หรือ
|
||||
ยังติดบล็อกอยู่
|
||||
|
||||
สำหรับการวนปรับ UI ของ QA Lab ภายในเครื่องให้เร็วขึ้นโดยไม่ต้องสร้างอิมเมจ Docker ใหม่ทุกครั้ง,
|
||||
ให้เริ่มสแตกด้วยบันเดิล QA Lab แบบ bind-mounted:
|
||||
สำหรับการวนแก้ UI ของ QA Lab ในเครื่องให้เร็วขึ้นโดยไม่ต้องสร้างอิมเมจ Docker ใหม่ทุกครั้ง,
|
||||
ให้เริ่ม stack ด้วยบันเดิล QA Lab แบบ bind-mounted:
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa docker-build-image
|
||||
@ -84,39 +86,39 @@ pnpm qa:lab:watch
|
||||
```
|
||||
|
||||
`qa:lab:up:fast` คงบริการ Docker ไว้บนอิมเมจที่สร้างไว้ล่วงหน้าและ bind-mount
|
||||
`extensions/qa-lab/web/dist` เข้าในคอนเทนเนอร์ `qa-lab` ส่วน `qa:lab:watch`
|
||||
จะสร้างบันเดิลนั้นใหม่เมื่อมีการเปลี่ยนแปลง และเบราว์เซอร์จะ reload อัตโนมัติเมื่อ hash แอสเซต QA Lab
|
||||
`extensions/qa-lab/web/dist` เข้าไปใน container `qa-lab` `qa:lab:watch`
|
||||
สร้างบันเดิลนั้นใหม่เมื่อมีการเปลี่ยนแปลง และเบราว์เซอร์จะโหลดซ้ำอัตโนมัติเมื่อ hash แอสเซ็ต QA Lab
|
||||
เปลี่ยนไป
|
||||
|
||||
สำหรับ smoke trace OpenTelemetry ภายในเครื่อง ให้รัน:
|
||||
สำหรับ smoke trace OpenTelemetry ในเครื่อง ให้รัน:
|
||||
|
||||
```bash
|
||||
pnpm qa:otel:smoke
|
||||
```
|
||||
|
||||
สคริปต์นั้นเริ่มตัวรับ trace OTLP/HTTP ภายในเครื่อง, รันสถานการณ์ QA
|
||||
`otel-trace-smoke` โดยเปิดใช้ Plugin `diagnostics-otel` จากนั้น
|
||||
decode protobuf spans ที่ export แล้วตรวจยืนยันรูปร่างที่สำคัญต่อ release:
|
||||
สคริปต์นั้นเริ่ม receiver trace OTLP/HTTP ในเครื่อง, รันสถานการณ์ QA
|
||||
`otel-trace-smoke` โดยเปิดใช้งาน Plugin `diagnostics-otel`, จากนั้น
|
||||
ถอดรหัส protobuf spans ที่ส่งออกและ assert รูปทรงที่สำคัญต่อ release:
|
||||
ต้องมี `openclaw.run`, `openclaw.harness.run`, `openclaw.model.call`,
|
||||
`openclaw.context.assembled` และ `openclaw.message.delivery`;
|
||||
การเรียกโมเดลต้องไม่ export `StreamAbandoned` ในเทิร์นที่สำเร็จ; raw diagnostic IDs และ
|
||||
แอตทริบิวต์ `openclaw.content.*` ต้องไม่อยู่ใน trace โดยเขียน
|
||||
`otel-smoke-summary.json` ไว้ถัดจาก artifacts ของ QA suite
|
||||
model calls ต้องไม่ส่งออก `StreamAbandoned` ใน turn ที่สำเร็จ; ID diagnostic ดิบและ
|
||||
attribute `openclaw.content.*` ต้องไม่อยู่ใน trace คำสั่งนี้เขียน
|
||||
`otel-smoke-summary.json` ข้าง artifacts ของ QA suite
|
||||
|
||||
Observability QA ใช้ได้เฉพาะจาก source checkout เท่านั้น npm tarball จงใจละเว้น
|
||||
QA Lab ดังนั้นเลน Docker release ของแพ็กเกจจึงไม่รันคำสั่ง `qa` ใช้
|
||||
QA ด้าน observability ยังคงเป็น source-checkout เท่านั้น npm tarball จงใจละเว้น
|
||||
QA Lab ดังนั้นเลน release Docker ของแพ็กเกจจะไม่รันคำสั่ง `qa` ใช้
|
||||
`pnpm qa:otel:smoke` จาก source checkout ที่ build แล้วเมื่อเปลี่ยน instrumentation
|
||||
ด้าน diagnostics
|
||||
diagnostics
|
||||
|
||||
สำหรับเลน smoke Matrix ที่ใช้ transport จริง ให้รัน:
|
||||
สำหรับเลน smoke Matrix ที่เป็น transport จริง ให้รัน:
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa matrix --profile fast --fail-fast
|
||||
```
|
||||
|
||||
เอกสารอ้างอิง CLI ฉบับเต็ม, แคตตาล็อก profile/scenario, env vars และเลย์เอาต์ artifact สำหรับเลนนี้อยู่ใน [Matrix QA](/th/concepts/qa-matrix) โดยสรุป: มัน provision homeserver Tuwunel แบบใช้แล้วทิ้งใน Docker, ลงทะเบียนผู้ใช้ driver/SUT/observer ชั่วคราว, รัน Plugin Matrix จริงภายใน Gateway QA ย่อยที่ scope กับ transport นั้น (ไม่มี `qa-channel`) จากนั้นเขียนรายงาน Markdown, สรุป JSON, artifact observed-events และ log เอาต์พุตรวมภายใต้ `.artifacts/qa-e2e/matrix-<timestamp>/`
|
||||
เอกสารอ้างอิง CLI ฉบับเต็ม, catalog ของ profile/scenario, env vars และ layout artifact สำหรับเลนนี้อยู่ใน [Matrix QA](/th/concepts/qa-matrix) สรุปโดยย่อ: คำสั่งนี้ provision Tuwunel homeserver แบบใช้แล้วทิ้งใน Docker, ลงทะเบียนผู้ใช้ driver/SUT/observer ชั่วคราว, รัน Plugin Matrix จริงภายใน child QA gateway ที่จำกัดขอบเขตไว้กับ transport นั้น (ไม่มี `qa-channel`), จากนั้นเขียนรายงาน Markdown, summary JSON, artifact observed-events และ log เอาต์พุตรวมไว้ใต้ `.artifacts/qa-e2e/matrix-<timestamp>/`
|
||||
|
||||
สำหรับเลน smoke Telegram, Discord และ Slack ที่ใช้ transport จริง:
|
||||
สำหรับเลน smoke Telegram, Discord และ Slack ที่เป็น transport จริง:
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa telegram
|
||||
@ -124,92 +126,109 @@ pnpm openclaw qa discord
|
||||
pnpm openclaw qa slack
|
||||
```
|
||||
|
||||
เลนเหล่านี้เล็งไปที่ช่องทางจริงที่มีอยู่แล้วพร้อมบอตสองตัว (driver + SUT) env vars ที่จำเป็น, รายการสถานการณ์, output artifacts และพูล credential Convex มีเอกสารอยู่ใน [เอกสารอ้างอิง QA สำหรับ Telegram, Discord และ Slack](#telegram-discord-and-slack-qa-reference) ด้านล่าง
|
||||
เลนเหล่านี้มุ่งเป้าไปที่ช่องทางจริงที่มีอยู่แล้วพร้อม bot สองตัว (driver + SUT) env vars ที่จำเป็น, รายการสถานการณ์, output artifacts และ pool credential Convex มีเอกสารอยู่ใน [เอกสารอ้างอิง QA ของ Telegram, Discord และ Slack](#telegram-discord-and-slack-qa-reference) ด้านล่าง
|
||||
|
||||
ก่อนใช้ credential live แบบ pooled ให้รัน:
|
||||
สำหรับการรัน Slack desktop VM เต็มรูปแบบพร้อม VNC rescue ให้รัน:
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa mantis slack-desktop-smoke \
|
||||
--gateway-setup \
|
||||
--scenario slack-canary \
|
||||
--keep-lease
|
||||
```
|
||||
|
||||
คำสั่งนั้นเช่าเครื่องเดสก์ท็อป/เบราว์เซอร์ Crabbox, รันเลนสด Slack
|
||||
ภายใน VM, เปิด Slack Web ในเบราว์เซอร์ VNC, จับภาพเดสก์ท็อป และ
|
||||
คัดลอก `slack-qa/` พร้อม `slack-desktop-smoke.png` กลับไปยังไดเรกทอรี artifact
|
||||
ของ Mantis ใช้ `--lease-id <cbx_...>` ซ้ำหลังจากล็อกอิน Slack Web ด้วยตนเอง
|
||||
ผ่าน VNC เมื่อใช้ `--gateway-setup` Mantis จะคง Gateway Slack ของ OpenClaw
|
||||
แบบถาวรที่ทำงานอยู่ภายใน VM บนพอร์ต `38973`; ถ้าไม่ใช้ คำสั่งจะรัน
|
||||
เลน QA Slack แบบ bot-to-bot ปกติและออกหลังจากจับ artifact แล้ว
|
||||
|
||||
ก่อนใช้ credential สดจาก pool ให้รัน:
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa credentials doctor
|
||||
```
|
||||
|
||||
doctor ตรวจ env ของ broker Convex, ตรวจสอบการตั้งค่า endpoint และตรวจยืนยันว่าเข้าถึง admin/list ได้เมื่อมี secret ของ maintainer อยู่ โดยรายงานเฉพาะสถานะตั้งค่าแล้ว/ขาดหายสำหรับ secrets
|
||||
doctor ตรวจสอบ env ของ broker Convex, validate การตั้งค่า endpoint และยืนยันการเข้าถึง admin/list เมื่อมี maintainer secret อยู่ โดยจะรายงานเฉพาะสถานะ set/missing สำหรับ secrets
|
||||
|
||||
## ความครอบคลุม transport live
|
||||
## Coverage ของ live transport
|
||||
|
||||
เลน transport live ใช้ contract เดียวร่วมกันแทนที่แต่ละเลนจะประดิษฐ์รูปร่างรายการสถานการณ์ของตัวเอง `qa-channel` เป็นชุดทดสอบพฤติกรรมผลิตภัณฑ์สังเคราะห์แบบกว้างและไม่เป็นส่วนหนึ่งของเมทริกซ์ความครอบคลุม transport live
|
||||
เลน live transport ใช้ contract เดียวกันแทนที่แต่ละเลนจะสร้างรูปทรงรายการสถานการณ์ของตัวเอง `qa-channel` คือ suite พฤติกรรมผลิตภัณฑ์สังเคราะห์แบบกว้าง และไม่ได้เป็นส่วนหนึ่งของ matrix coverage ของ live transport
|
||||
|
||||
| เลน | Canary | Mention gating | Bot-to-bot | บล็อก allowlist | การตอบกลับระดับบนสุด | กลับมาทำต่อหลัง restart | follow-up ของเธรด | การแยกเธรด | การสังเกตรีแอ็กชัน | คำสั่งช่วยเหลือ | การลงทะเบียนคำสั่ง native |
|
||||
| เลน | Canary | การ gate mention | Bot-to-bot | บล็อก allowlist | การตอบกลับระดับบนสุด | resume หลัง restart | follow-up ใน thread | isolation ของ thread | การสังเกต reaction | คำสั่ง help | การลงทะเบียนคำสั่ง native |
|
||||
| -------- | ------ | -------------- | ---------- | --------------- | --------------- | -------------- | ---------------- | ---------------- | -------------------- | ------------ | --------------------------- |
|
||||
| Matrix | x | x | x | x | x | x | x | x | x | | |
|
||||
| Telegram | x | x | x | | | | | | | x | |
|
||||
| Discord | x | x | x | | | | | | | | x |
|
||||
| Slack | x | x | x | | | | | | | | |
|
||||
|
||||
สิ่งนี้คง `qa-channel` ไว้เป็นชุดทดสอบพฤติกรรมผลิตภัณฑ์แบบกว้าง ขณะที่ Matrix,
|
||||
Telegram และ transport live ในอนาคตใช้ checklist transport-contract ที่ชัดเจนร่วมกัน
|
||||
สิ่งนี้คง `qa-channel` ไว้เป็น suite พฤติกรรมผลิตภัณฑ์แบบกว้าง ขณะที่ Matrix,
|
||||
Telegram และ live transports ในอนาคตใช้ checklist transport-contract ที่ชัดเจนร่วมกัน
|
||||
|
||||
สำหรับเลน Linux VM แบบใช้แล้วทิ้งโดยไม่ต้องนำ Docker เข้ามาในเส้นทาง QA ให้รัน:
|
||||
สำหรับเลน Linux VM แบบใช้แล้วทิ้งโดยไม่ดึง Docker เข้ามาในเส้นทาง QA ให้รัน:
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa suite --runner multipass --scenario channel-chat-baseline
|
||||
```
|
||||
|
||||
คำสั่งนี้บูต guest Multipass ใหม่, ติดตั้ง dependency, build OpenClaw
|
||||
ภายใน guest, รัน `qa suite` จากนั้นคัดลอกรายงาน QA และ
|
||||
สรุปปกติกลับเข้า `.artifacts/qa-e2e/...` บน host
|
||||
มันใช้พฤติกรรมการเลือกสถานการณ์เดียวกับ `qa suite` บน host
|
||||
การรัน suite บน host และ Multipass จะ execute สถานการณ์ที่เลือกหลายรายการพร้อมกัน
|
||||
ด้วย worker Gateway ที่แยกกันโดยค่าเริ่มต้น `qa-channel` ค่าเริ่มต้น concurrency
|
||||
คือ 4 โดยถูก cap ตามจำนวนสถานการณ์ที่เลือก ใช้ `--concurrency <count>` เพื่อปรับ
|
||||
จำนวน worker หรือ `--concurrency 1` สำหรับการ execute แบบ serial
|
||||
คำสั่งจะ exit ด้วยค่าไม่เป็นศูนย์เมื่อสถานการณ์ใดล้มเหลว ใช้ `--allow-failures` เมื่อ
|
||||
คุณต้องการ artifacts โดยไม่มี exit code ที่ล้มเหลว
|
||||
การรัน live จะส่งต่ออินพุต auth ของ QA ที่รองรับและใช้ได้จริงสำหรับ
|
||||
guest: provider keys ผ่าน env, path คอนฟิก QA live provider และ
|
||||
`CODEX_HOME` เมื่อมีอยู่ คง `--output-dir` ไว้ภายใต้ root ของรีโปเพื่อให้ guest
|
||||
คำสั่งนี้บูต Multipass guest ใหม่ ติดตั้ง dependency สร้าง OpenClaw
|
||||
ภายใน guest รัน `qa suite` จากนั้นคัดลอกรายงาน QA ปกติและ
|
||||
สรุปกลับไปยัง `.artifacts/qa-e2e/...` บน host
|
||||
คำสั่งนี้ใช้พฤติกรรมการเลือก scenario เดียวกับ `qa suite` บน host
|
||||
การรันชุดทดสอบบน host และ Multipass จะดำเนินการ scenario ที่เลือกหลายรายการแบบขนาน
|
||||
ด้วย worker ของ Gateway ที่แยกกันโดยค่าเริ่มต้น `qa-channel` ตั้งค่าเริ่มต้นของ concurrency
|
||||
เป็น 4 โดยจำกัดไม่เกินจำนวน scenario ที่เลือก ใช้ `--concurrency <count>` เพื่อปรับ
|
||||
จำนวน worker หรือ `--concurrency 1` สำหรับการดำเนินการแบบลำดับเดียว
|
||||
คำสั่งจะออกด้วยสถานะไม่เป็นศูนย์เมื่อ scenario ใดล้มเหลว ใช้ `--allow-failures` เมื่อ
|
||||
คุณต้องการ artifact โดยไม่มี exit code ที่ล้มเหลว
|
||||
การรันแบบ live จะส่งต่อ input การยืนยันตัวตน QA ที่รองรับและใช้งานได้จริงสำหรับ
|
||||
guest ได้แก่ key ของ provider จาก env, path config ของ QA live provider และ
|
||||
`CODEX_HOME` เมื่อมีอยู่ เก็บ `--output-dir` ไว้ใต้ repo root เพื่อให้ guest
|
||||
เขียนกลับผ่าน workspace ที่ mount ไว้ได้
|
||||
|
||||
## เอกสารอ้างอิง QA สำหรับ Telegram, Discord และ Slack
|
||||
## อ้างอิง QA สำหรับ Telegram, Discord และ Slack
|
||||
|
||||
Matrix มี [หน้าเฉพาะ](/th/concepts/qa-matrix) เนื่องจากจำนวนสถานการณ์และการ provision homeserver ที่รองรับด้วย Docker Telegram, Discord และ Slack มีขนาดเล็กกว่า — มีสถานการณ์ไม่กี่รายการต่อแต่ละตัว, ไม่มีระบบ profile, ทำงานกับช่องทางจริงที่มีอยู่แล้ว — ดังนั้นเอกสารอ้างอิงของพวกมันจึงอยู่ที่นี่
|
||||
Matrix มี[หน้าเฉพาะ](/th/concepts/qa-matrix)เนื่องจากมีจำนวน scenario มากและมีการจัดเตรียม homeserver ที่ใช้ Docker รองรับ Telegram, Discord และ Slack มีขนาดเล็กกว่า โดยมีเพียงไม่กี่ scenario ต่อรายการ ไม่มีระบบ profile และทดสอบกับ channel จริงที่มีอยู่แล้ว ดังนั้นอ้างอิงของรายการเหล่านี้จึงอยู่ที่นี่
|
||||
|
||||
### แฟล็ก CLI ที่ใช้ร่วมกัน
|
||||
### flag ของ CLI ที่ใช้ร่วมกัน
|
||||
|
||||
เลนเหล่านี้ลงทะเบียนผ่าน `extensions/qa-lab/src/live-transports/shared/live-transport-cli.ts` และรับแฟล็กเดียวกัน:
|
||||
lane เหล่านี้ลงทะเบียนผ่าน `extensions/qa-lab/src/live-transports/shared/live-transport-cli.ts` และรับ flag เดียวกัน:
|
||||
|
||||
| แฟล็ก | ค่าเริ่มต้น | คำอธิบาย |
|
||||
| Flag | ค่าเริ่มต้น | คำอธิบาย |
|
||||
| ------------------------------------- | --------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
|
||||
| `--scenario <id>` | — | เรียกใช้เฉพาะสถานการณ์นี้ ทำซ้ำได้ |
|
||||
| `--output-dir <path>` | `<repo>/.artifacts/qa-e2e/{telegram,discord,slack}-<timestamp>` | ตำแหน่งที่เขียนรายงาน/สรุป/ข้อความที่สังเกตได้ และบันทึกเอาต์พุต พาธสัมพัทธ์จะอิงจาก `--repo-root` |
|
||||
| `--repo-root <path>` | `process.cwd()` | รากของ repository เมื่อเรียกใช้จาก cwd ที่เป็นกลาง |
|
||||
| `--sut-account <id>` | `sut` | ID บัญชีชั่วคราวภายในคอนฟิก Gateway ของ QA |
|
||||
| `--provider-mode <mode>` | `live-frontier` | `mock-openai` หรือ `live-frontier` (`live-openai` แบบเดิมยังใช้งานได้) |
|
||||
| `--model <ref>` / `--alt-model <ref>` | ค่าเริ่มต้นของผู้ให้บริการ | การอ้างอิงโมเดลหลัก/สำรอง |
|
||||
| `--fast` | ปิด | โหมดเร็วของผู้ให้บริการเมื่อรองรับ |
|
||||
| `--credential-source <env\|convex>` | `env` | ดู [กลุ่มข้อมูลประจำตัว Convex](#convex-credential-pool) |
|
||||
| `--credential-role <maintainer\|ci>` | `ci` ใน CI, มิฉะนั้นเป็น `maintainer` | บทบาทที่ใช้เมื่อ `--credential-source convex` |
|
||||
| `--scenario <id>` | — | รันเฉพาะ scenario นี้ ทำซ้ำได้ |
|
||||
| `--output-dir <path>` | `<repo>/.artifacts/qa-e2e/{telegram,discord,slack}-<timestamp>` | ตำแหน่งที่เขียน report/summary/observed message และ output log path แบบ relative จะ resolve เทียบกับ `--repo-root` |
|
||||
| `--repo-root <path>` | `process.cwd()` | root ของ repository เมื่อเรียกใช้จาก cwd ที่เป็นกลาง |
|
||||
| `--sut-account <id>` | `sut` | id บัญชีชั่วคราวภายใน config ของ QA Gateway |
|
||||
| `--provider-mode <mode>` | `live-frontier` | `mock-openai` หรือ `live-frontier` (`live-openai` แบบ legacy ยังใช้งานได้) |
|
||||
| `--model <ref>` / `--alt-model <ref>` | ค่าเริ่มต้นของ provider | ref ของ model หลัก/สำรอง |
|
||||
| `--fast` | ปิด | โหมดเร็วของ provider ในที่ที่รองรับ |
|
||||
| `--credential-source <env\|convex>` | `env` | ดู [pool ของ credential ใน Convex](#convex-credential-pool) |
|
||||
| `--credential-role <maintainer\|ci>` | `ci` ใน CI, นอกนั้นเป็น `maintainer` | role ที่ใช้เมื่อ `--credential-source convex` |
|
||||
|
||||
แต่ละ lane จะออกด้วยค่าที่ไม่ใช่ศูนย์เมื่อมีสถานการณ์ใดล้มเหลว `--allow-failures` จะเขียน artifacts โดยไม่ตั้งค่า exit code เป็นล้มเหลว
|
||||
แต่ละ lane จะออกด้วยสถานะไม่เป็นศูนย์เมื่อ scenario ใดล้มเหลว `--allow-failures` จะเขียน artifact โดยไม่ตั้ง exit code ที่ล้มเหลว
|
||||
|
||||
### QA ของ Telegram
|
||||
### Telegram QA
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa telegram
|
||||
```
|
||||
|
||||
กำหนดเป้าหมายไปยังกลุ่ม Telegram ส่วนตัวจริงหนึ่งกลุ่มที่มีบอทแตกต่างกันสองตัว (driver + SUT) บอท SUT ต้องมีชื่อผู้ใช้ Telegram; การสังเกตแบบบอทถึงบอททำงานได้ดีที่สุดเมื่อบอททั้งสองเปิดใช้ **โหมดการสื่อสารแบบบอทถึงบอท** ใน `@BotFather`
|
||||
เป้าหมายคือกลุ่ม Telegram ส่วนตัวจริงหนึ่งกลุ่มที่มี bot สองตัวแยกกัน (driver + SUT) SUT bot ต้องมี username ของ Telegram; การสังเกตการณ์ bot-to-bot ทำงานได้ดีที่สุดเมื่อ bot ทั้งสองตัวเปิดใช้ **Bot-to-Bot Communication Mode** ใน `@BotFather`
|
||||
|
||||
env ที่จำเป็นเมื่อ `--credential-source env`:
|
||||
|
||||
- `OPENCLAW_QA_TELEGRAM_GROUP_ID` — ID แชตแบบตัวเลข (สตริง)
|
||||
- `OPENCLAW_QA_TELEGRAM_GROUP_ID` — id ของ chat แบบตัวเลข (string)
|
||||
- `OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN`
|
||||
- `OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN`
|
||||
|
||||
ตัวเลือกเสริม:
|
||||
|
||||
- `OPENCLAW_QA_TELEGRAM_CAPTURE_CONTENT=1` เก็บเนื้อหาข้อความไว้ใน artifacts ของข้อความที่สังเกตได้ (ค่าเริ่มต้นจะปกปิด)
|
||||
- `OPENCLAW_QA_TELEGRAM_CAPTURE_CONTENT=1` เก็บเนื้อหาข้อความไว้ใน artifact ของ observed-message (ค่าเริ่มต้นจะ redact)
|
||||
|
||||
สถานการณ์ (`extensions/qa-lab/src/live-transports/telegram/telegram-live.runtime.ts:44`):
|
||||
Scenario (`extensions/qa-lab/src/live-transports/telegram/telegram-live.runtime.ts:44`):
|
||||
|
||||
- `telegram-canary`
|
||||
- `telegram-mention-gating`
|
||||
@ -220,19 +239,19 @@ env ที่จำเป็นเมื่อ `--credential-source env`:
|
||||
- `telegram-whoami-command`
|
||||
- `telegram-context-command`
|
||||
|
||||
Artifacts เอาต์พุต:
|
||||
Artifact ที่ส่งออก:
|
||||
|
||||
- `telegram-qa-report.md`
|
||||
- `telegram-qa-summary.json` — รวม RTT ต่อการตอบกลับ (driver ส่ง → สังเกตเห็น SUT ตอบกลับ) โดยเริ่มจาก canary
|
||||
- `telegram-qa-observed-messages.json` — เนื้อหาถูกปกปิด เว้นแต่ `OPENCLAW_QA_TELEGRAM_CAPTURE_CONTENT=1`
|
||||
- `telegram-qa-summary.json` — รวม RTT ต่อ reply (driver ส่ง → สังเกตเห็น SUT reply) เริ่มจาก canary
|
||||
- `telegram-qa-observed-messages.json` — redact เนื้อหา เว้นแต่ตั้งค่า `OPENCLAW_QA_TELEGRAM_CAPTURE_CONTENT=1`
|
||||
|
||||
### QA ของ Discord
|
||||
### Discord QA
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa discord
|
||||
```
|
||||
|
||||
กำหนดเป้าหมายไปยังช่อง guild ส่วนตัวจริงหนึ่งช่องใน Discord ด้วยบอทสองตัว: บอท driver ที่ควบคุมโดย harness และบอท SUT ที่เริ่มโดย Gateway ลูกของ OpenClaw ผ่าน Plugin Discord ที่ bundled มา ตรวจสอบการจัดการการกล่าวถึงช่อง, การที่บอท SUT ลงทะเบียนคำสั่งเนทีฟ `/help` กับ Discord แล้ว, และสถานการณ์หลักฐาน Mantis แบบ opt-in
|
||||
เป้าหมายคือ channel ของ Discord guild ส่วนตัวจริงหนึ่ง channel ที่มี bot สองตัว: driver bot ที่ควบคุมโดย harness และ SUT bot ที่เริ่มโดย child OpenClaw Gateway ผ่าน Plugin Discord ที่ bundle มา ตรวจสอบการจัดการการ mention ใน channel, การที่ SUT bot ลงทะเบียนคำสั่ง native `/help` กับ Discord แล้ว และ scenario หลักฐานของ Mantis แบบ opt-in
|
||||
|
||||
env ที่จำเป็นเมื่อ `--credential-source env`:
|
||||
|
||||
@ -240,20 +259,20 @@ env ที่จำเป็นเมื่อ `--credential-source env`:
|
||||
- `OPENCLAW_QA_DISCORD_CHANNEL_ID`
|
||||
- `OPENCLAW_QA_DISCORD_DRIVER_BOT_TOKEN`
|
||||
- `OPENCLAW_QA_DISCORD_SUT_BOT_TOKEN`
|
||||
- `OPENCLAW_QA_DISCORD_SUT_APPLICATION_ID` — ต้องตรงกับ ID ผู้ใช้ของบอท SUT ที่ Discord ส่งคืน (มิฉะนั้น lane จะล้มเหลวอย่างรวดเร็ว)
|
||||
- `OPENCLAW_QA_DISCORD_SUT_APPLICATION_ID` — ต้องตรงกับ user id ของ SUT bot ที่ Discord ส่งคืน (ไม่เช่นนั้น lane จะล้มเหลวอย่างรวดเร็ว)
|
||||
|
||||
ตัวเลือกเสริม:
|
||||
|
||||
- `OPENCLAW_QA_DISCORD_CAPTURE_CONTENT=1` เก็บเนื้อหาข้อความไว้ใน artifacts ของข้อความที่สังเกตได้
|
||||
- `OPENCLAW_QA_DISCORD_CAPTURE_CONTENT=1` เก็บเนื้อหาข้อความไว้ใน artifact ของ observed-message
|
||||
|
||||
สถานการณ์ (`extensions/qa-lab/src/live-transports/discord/discord-live.runtime.ts:36`):
|
||||
Scenario (`extensions/qa-lab/src/live-transports/discord/discord-live.runtime.ts:36`):
|
||||
|
||||
- `discord-canary`
|
||||
- `discord-mention-gating`
|
||||
- `discord-native-help-command-registration`
|
||||
- `discord-status-reactions-tool-only` — สถานการณ์ Mantis แบบ opt-in ทำงานด้วยตัวเองเพราะจะสลับ SUT ให้ตอบกลับ guild แบบเปิดตลอดเวลาและใช้เฉพาะเครื่องมือด้วย `messages.statusReactions.enabled=true` จากนั้นจับไทม์ไลน์ reaction ผ่าน REST พร้อม artifact ภาพ HTML/PNG
|
||||
- `discord-status-reactions-tool-only` — scenario ของ Mantis แบบ opt-in รันเดี่ยวเพราะจะสลับ SUT เป็นการ reply ใน guild แบบ always-on และ tool-only ด้วย `messages.statusReactions.enabled=true` จากนั้นจับ timeline ของ REST reaction พร้อม artifact ภาพ HTML/PNG
|
||||
|
||||
เรียกใช้สถานการณ์ status-reaction ของ Mantis อย่างชัดเจน:
|
||||
รัน scenario status-reaction ของ Mantis โดยระบุอย่างชัดเจน:
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa discord \
|
||||
@ -264,20 +283,20 @@ pnpm openclaw qa discord \
|
||||
--fast
|
||||
```
|
||||
|
||||
Artifacts เอาต์พุต:
|
||||
Artifact ที่ส่งออก:
|
||||
|
||||
- `discord-qa-report.md`
|
||||
- `discord-qa-summary.json`
|
||||
- `discord-qa-observed-messages.json` — เนื้อหาถูกปกปิด เว้นแต่ `OPENCLAW_QA_DISCORD_CAPTURE_CONTENT=1`
|
||||
- `discord-qa-reaction-timelines.json` และ `discord-status-reactions-tool-only-timeline.png` เมื่อสถานการณ์ status-reaction ทำงาน
|
||||
- `discord-qa-observed-messages.json` — redact เนื้อหา เว้นแต่ตั้งค่า `OPENCLAW_QA_DISCORD_CAPTURE_CONTENT=1`
|
||||
- `discord-qa-reaction-timelines.json` และ `discord-status-reactions-tool-only-timeline.png` เมื่อรัน scenario status-reaction
|
||||
|
||||
### QA ของ Slack
|
||||
### Slack QA
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa slack
|
||||
```
|
||||
|
||||
กำหนดเป้าหมายไปยังช่อง Slack ส่วนตัวจริงหนึ่งช่องที่มีบอทแตกต่างกันสองตัว: บอท driver ที่ควบคุมโดย harness และบอท SUT ที่เริ่มโดย Gateway ลูกของ OpenClaw ผ่าน Plugin Slack ที่ bundled มา
|
||||
เป้าหมายคือ channel ของ Slack ส่วนตัวจริงหนึ่ง channel ที่มี bot สองตัวแยกกัน: driver bot ที่ควบคุมโดย harness และ SUT bot ที่เริ่มโดย child OpenClaw Gateway ผ่าน Plugin Slack ที่ bundle มา
|
||||
|
||||
env ที่จำเป็นเมื่อ `--credential-source env`:
|
||||
|
||||
@ -288,144 +307,147 @@ env ที่จำเป็นเมื่อ `--credential-source env`:
|
||||
|
||||
ตัวเลือกเสริม:
|
||||
|
||||
- `OPENCLAW_QA_SLACK_CAPTURE_CONTENT=1` เก็บเนื้อหาข้อความไว้ใน artifacts ของข้อความที่สังเกตได้
|
||||
- `OPENCLAW_QA_SLACK_CAPTURE_CONTENT=1` เก็บเนื้อหาข้อความไว้ใน artifact ของ observed-message
|
||||
|
||||
สถานการณ์ (`extensions/qa-lab/src/live-transports/slack/slack-live.runtime.ts:39`):
|
||||
Scenario (`extensions/qa-lab/src/live-transports/slack/slack-live.runtime.ts:39`):
|
||||
|
||||
- `slack-canary`
|
||||
- `slack-mention-gating`
|
||||
|
||||
Artifacts เอาต์พุต:
|
||||
Artifact ที่ส่งออก:
|
||||
|
||||
- `slack-qa-report.md`
|
||||
- `slack-qa-summary.json`
|
||||
- `slack-qa-observed-messages.json` — เนื้อหาถูกปกปิด เว้นแต่ `OPENCLAW_QA_SLACK_CAPTURE_CONTENT=1`
|
||||
- `slack-qa-observed-messages.json` — redact เนื้อหา เว้นแต่ตั้งค่า `OPENCLAW_QA_SLACK_CAPTURE_CONTENT=1`
|
||||
|
||||
### กลุ่มข้อมูลประจำตัว Convex
|
||||
### pool ของ credential ใน Convex
|
||||
|
||||
lane ของ Telegram, Discord, และ Slack สามารถเช่าข้อมูลประจำตัวจากกลุ่ม Convex ที่ใช้ร่วมกันแทนการอ่าน env vars ข้างต้นได้ ส่ง `--credential-source convex` (หรือตั้งค่า `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`); QA Lab จะขอ lease แบบเอกสิทธิ์ ส่ง Heartbeat ตลอดช่วงเวลาการรัน และปล่อย lease เมื่อปิดระบบ ชนิดของกลุ่มคือ `"telegram"`, `"discord"`, และ `"slack"`
|
||||
lane ของ Telegram, Discord และ Slack สามารถเช่า credential จาก pool ของ Convex ที่ใช้ร่วมกันแทนการอ่าน env var ข้างต้น ส่ง `--credential-source convex` (หรือตั้งค่า `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`); QA Lab จะรับ lease แบบ exclusive, ส่ง Heartbeat ตลอดระยะเวลาการรัน และ release เมื่อ shutdown kind ของ pool คือ `"telegram"`, `"discord"` และ `"slack"`
|
||||
|
||||
รูปแบบ payload ที่ broker ตรวจสอบบน `admin/add`:
|
||||
รูปทรง payload ที่ broker ตรวจสอบใน `admin/add`:
|
||||
|
||||
- Telegram (`kind: "telegram"`): `{ groupId: string, driverToken: string, sutToken: string }` — `groupId` ต้องเป็นสตริง chat-id แบบตัวเลข
|
||||
- Telegram (`kind: "telegram"`): `{ groupId: string, driverToken: string, sutToken: string }` — `groupId` ต้องเป็น string ของ chat-id แบบตัวเลข
|
||||
- Discord (`kind: "discord"`): `{ guildId: string, channelId: string, driverBotToken: string, sutBotToken: string, sutApplicationId: string }`
|
||||
|
||||
env vars สำหรับปฏิบัติการและสัญญา endpoint ของ broker Convex อยู่ใน [การทดสอบ → ข้อมูลประจำตัว Telegram ที่ใช้ร่วมกันผ่าน Convex](/th/help/testing#shared-telegram-credentials-via-convex-v1) (ชื่อส่วนนี้มีมาก่อนการรองรับ Discord; ความหมายของ broker เหมือนกันสำหรับทั้งสองชนิด)
|
||||
env var สำหรับการปฏิบัติงานและ contract endpoint ของ broker Convex อยู่ใน [การทดสอบ → credential Telegram ที่ใช้ร่วมกันผ่าน Convex](/th/help/testing#shared-telegram-credentials-via-convex-v1) (ชื่อ section เกิดก่อนการรองรับ Discord; semantic ของ broker เหมือนกันสำหรับทั้งสอง kind)
|
||||
|
||||
## Seeds ที่อิงจาก repo
|
||||
## seed ที่รองรับด้วย repo
|
||||
|
||||
Seed assets อยู่ใน `qa/`:
|
||||
asset ของ seed อยู่ใน `qa/`:
|
||||
|
||||
- `qa/scenarios/index.md`
|
||||
- `qa/scenarios/<theme>/*.md`
|
||||
|
||||
สิ่งเหล่านี้ตั้งใจให้อยู่ใน git เพื่อให้แผน QA มองเห็นได้ทั้งสำหรับมนุษย์และ
|
||||
agent
|
||||
สิ่งเหล่านี้ตั้งใจให้อยู่ใน git เพื่อให้ทั้งมนุษย์และ
|
||||
agent มองเห็นแผน QA
|
||||
|
||||
`qa-lab` ควรยังคงเป็น runner markdown ทั่วไป ไฟล์ markdown ของแต่ละสถานการณ์คือ
|
||||
แหล่งความจริงสำหรับการทดสอบหนึ่งครั้ง และควรกำหนด:
|
||||
`qa-lab` ควรคงเป็น runner markdown ทั่วไป แต่ละไฟล์ markdown ของ scenario คือ
|
||||
source of truth สำหรับการรันทดสอบหนึ่งครั้ง และควรกำหนด:
|
||||
|
||||
- metadata ของสถานการณ์
|
||||
- metadata หมวดหมู่, capability, lane, และความเสี่ยงแบบเลือกได้
|
||||
- refs ของเอกสารและโค้ด
|
||||
- ข้อกำหนด Plugin แบบเลือกได้
|
||||
- patch คอนฟิก Gateway แบบเลือกได้
|
||||
- `qa-flow` ที่เรียกใช้ได้
|
||||
- metadata ของ scenario
|
||||
- metadata ของ category, capability, lane และ risk แบบเสริม
|
||||
- ref ของ docs และ code
|
||||
- ข้อกำหนด Plugin แบบเสริม
|
||||
- patch ของ config Gateway แบบเสริม
|
||||
- `qa-flow` ที่ดำเนินการได้
|
||||
|
||||
พื้นผิว runtime ที่ใช้ซ้ำได้ซึ่งรองรับ `qa-flow` สามารถคงความทั่วไป
|
||||
และข้ามหลายส่วนได้ ตัวอย่างเช่น สถานการณ์ markdown สามารถรวม helper ฝั่ง transport
|
||||
กับ helper ฝั่งเบราว์เซอร์ที่ขับ Control UI แบบฝังผ่าน
|
||||
seam `browser.request` ของ Gateway ได้โดยไม่ต้องเพิ่ม runner แบบกรณีพิเศษ
|
||||
พื้นผิว runtime ที่ใช้ซ้ำได้ซึ่งรองรับ `qa-flow` สามารถคงความเป็นทั่วไป
|
||||
และข้ามส่วนงานได้ ตัวอย่างเช่น scenario markdown สามารถรวม helper ฝั่ง transport
|
||||
กับ helper ฝั่ง browser ที่ขับ Control UI ที่ฝังไว้ผ่าน
|
||||
seam `browser.request` ของ Gateway โดยไม่ต้องเพิ่ม runner แบบกรณีพิเศษ
|
||||
|
||||
ควรจัดกลุ่มไฟล์สถานการณ์ตาม capability ของผลิตภัณฑ์แทนที่จะตามโฟลเดอร์ source tree
|
||||
ให้ ID สถานการณ์คงที่เมื่อย้ายไฟล์; ใช้ `docsRefs` และ `codeRefs`
|
||||
เพื่อให้ตามรอยการ implement ได้
|
||||
ไฟล์ scenario ควรถูกจัดกลุ่มตาม capability ของผลิตภัณฑ์แทน folder ของ source tree
|
||||
คง id ของ scenario ให้เสถียรเมื่อย้ายไฟล์; ใช้ `docsRefs` และ `codeRefs`
|
||||
เพื่อ trace การ implementation
|
||||
|
||||
รายการ baseline ควรกว้างพอที่จะครอบคลุม:
|
||||
|
||||
- แชต DM และช่อง
|
||||
- พฤติกรรมของ thread
|
||||
- chat แบบ DM และ channel
|
||||
- พฤติกรรม thread
|
||||
- lifecycle ของ message action
|
||||
- callbacks ของ cron
|
||||
- การเรียกคืน memory
|
||||
- การสลับโมเดล
|
||||
- callback ของ Cron
|
||||
- การ recall memory
|
||||
- การสลับ model
|
||||
- การส่งต่อให้ subagent
|
||||
- การอ่าน repo และการอ่านเอกสาร
|
||||
- การอ่าน repo และการอ่าน docs
|
||||
- งาน build ขนาดเล็กหนึ่งงาน เช่น Lobster Invaders
|
||||
|
||||
## Lane mock ของผู้ให้บริการ
|
||||
## lane ของ provider mock
|
||||
|
||||
`qa suite` มี lane mock ผู้ให้บริการแบบ local สอง lane:
|
||||
`qa suite` มี lane provider mock ใน local สอง lane:
|
||||
|
||||
- `mock-openai` คือ mock ของ OpenClaw ที่รับรู้สถานการณ์ มันยังคงเป็น lane mock แบบกำหนดแน่นอนค่าเริ่มต้นสำหรับ QA ที่อิงจาก repo และ parity gates
|
||||
- `aimock` เริ่ม server ผู้ให้บริการที่อิงจาก AIMock สำหรับความครอบคลุมของ protocol, fixture, record/replay, และ chaos เชิงทดลอง เป็นส่วนเสริมและไม่แทนที่ dispatcher สถานการณ์ `mock-openai`
|
||||
- `mock-openai` คือ mock ของ OpenClaw ที่รับรู้ scenario ยังคงเป็น lane mock แบบกำหนดผลได้
|
||||
เริ่มต้นสำหรับ QA ที่รองรับด้วย repo และ parity gate
|
||||
- `aimock` เริ่ม server ของ provider ที่รองรับด้วย AIMock สำหรับ protocol,
|
||||
fixture, record/replay และ coverage แบบ chaos เชิงทดลอง เป็นส่วนเสริมและไม่ได้
|
||||
แทนที่ dispatcher ของ scenario `mock-openai`
|
||||
|
||||
การ implement provider-lane อยู่ใต้ `extensions/qa-lab/src/providers/`
|
||||
ผู้ให้บริการแต่ละรายเป็นเจ้าของค่าเริ่มต้น, การเริ่ม server local, คอนฟิกโมเดล Gateway,
|
||||
ความต้องการ staging ของ auth-profile, และ flag capability แบบ live/mock โค้ด suite และ
|
||||
Gateway ที่ใช้ร่วมกันควร route ผ่าน provider registry แทนการ branch ตาม
|
||||
ชื่อผู้ให้บริการ
|
||||
implementation ของ provider-lane อยู่ใต้ `extensions/qa-lab/src/providers/`
|
||||
แต่ละ provider เป็นเจ้าของค่าเริ่มต้นของตนเอง, การเริ่ม server local, config model ของ Gateway,
|
||||
ความต้องการ staging ของ auth-profile และ flag capability แบบ live/mock code ของ suite และ
|
||||
Gateway ที่ใช้ร่วมกันควร route ผ่าน registry ของ provider แทนการ branch ตาม
|
||||
ชื่อ provider
|
||||
|
||||
## Transport adapters
|
||||
## adapter ของ transport
|
||||
|
||||
`qa-lab` เป็นเจ้าของ seam transport ทั่วไปสำหรับสถานการณ์ QA แบบ markdown `qa-channel` คือ adapter ตัวแรกบน seam นั้น แต่เป้าหมายการออกแบบกว้างกว่า: channel จริงหรือสังเคราะห์ในอนาคตควร plug into suite runner เดียวกันแทนการเพิ่ม runner QA เฉพาะ transport
|
||||
`qa-lab` เป็นเจ้าของ seam transport ทั่วไปสำหรับ scenario QA แบบ markdown `qa-channel` คือ adapter แรกบน seam นั้น แต่เป้าหมายการออกแบบกว้างกว่า: channel จริงหรือสังเคราะห์ในอนาคตควรเสียบเข้ากับ suite runner เดียวกันแทนการเพิ่ม runner QA เฉพาะ transport
|
||||
|
||||
ในระดับสถาปัตยกรรม การแบ่งคือ:
|
||||
|
||||
- `qa-lab` เป็นเจ้าของการดำเนินการสถานการณ์ทั่วไป, concurrency ของ worker, การเขียน artifact, และการรายงาน
|
||||
- transport adapter เป็นเจ้าของคอนฟิก Gateway, readiness, การสังเกต inbound และ outbound, transport actions, และสถานะ transport ที่ normalize แล้ว
|
||||
- ไฟล์สถานการณ์ markdown ใต้ `qa/scenarios/` กำหนดการทดสอบ; `qa-lab` ให้พื้นผิว runtime ที่ใช้ซ้ำได้ซึ่งเรียกใช้ไฟล์เหล่านั้น
|
||||
- `qa-lab` เป็นเจ้าของการดำเนินการ scenario ทั่วไป, concurrency ของ worker, การเขียน artifact และการรายงาน
|
||||
- adapter ของ transport เป็นเจ้าของ config Gateway, readiness, การสังเกตการณ์ inbound และ outbound, action ของ transport และสถานะ transport ที่ normalize แล้ว
|
||||
- ไฟล์ scenario markdown ใต้ `qa/scenarios/` กำหนดการรันทดสอบ; `qa-lab` ให้พื้นผิว runtime ที่ใช้ซ้ำได้เพื่อดำเนินการไฟล์เหล่านั้น
|
||||
|
||||
### การเพิ่ม channel
|
||||
|
||||
การเพิ่ม channel ให้ระบบ QA แบบ markdown ต้องมีสองสิ่งเท่านั้น:
|
||||
การเพิ่ม channel ลงในระบบ QA markdown ต้องมีสองอย่างพอดี:
|
||||
|
||||
1. transport adapter สำหรับ channel
|
||||
2. scenario pack ที่ทดสอบสัญญา channel
|
||||
1. adapter ของ transport สำหรับ channel
|
||||
2. pack ของ scenario ที่ทดสอบ contract ของ channel
|
||||
|
||||
อย่าเพิ่มรากคำสั่ง QA ระดับบนใหม่เมื่อ host `qa-lab` ที่ใช้ร่วมกันสามารถเป็นเจ้าของ flow ได้
|
||||
อย่าเพิ่ม root คำสั่ง QA ระดับบนสุดใหม่เมื่อ host `qa-lab` ที่ใช้ร่วมกันสามารถเป็นเจ้าของ flow ได้
|
||||
|
||||
`qa-lab` เป็นเจ้าของกลไก host ที่ใช้ร่วมกัน:
|
||||
`qa-lab` เป็นเจ้าของกลไกโฮสต์ที่ใช้ร่วมกัน:
|
||||
|
||||
- รากคำสั่ง `openclaw qa`
|
||||
- การเริ่มและ teardown ของ suite
|
||||
- concurrency ของ worker
|
||||
- รูทคำสั่ง `openclaw qa`
|
||||
- การเริ่มต้นและการปิดชุดทดสอบ
|
||||
- ภาวะพร้อมกันของ worker
|
||||
- การเขียน artifact
|
||||
- การสร้างรายงาน
|
||||
- การดำเนินการสถานการณ์
|
||||
- alias เพื่อ compatibility สำหรับสถานการณ์ `qa-channel` เก่า
|
||||
- การดำเนินการ scenario
|
||||
- นามแฝงความเข้ากันได้สำหรับ scenario `qa-channel` รุ่นเก่า
|
||||
|
||||
Runner plugins เป็นเจ้าของสัญญา transport:
|
||||
Plugin ตัวรันเป็นเจ้าของสัญญาของ transport:
|
||||
|
||||
- วิธี mount `openclaw qa <runner>` ใต้ราก `qa` ที่ใช้ร่วมกัน
|
||||
- วิธีคอนฟิก Gateway สำหรับ transport นั้น
|
||||
- วิธีตรวจ readiness
|
||||
- วิธี inject เหตุการณ์ inbound
|
||||
- วิธีสังเกตข้อความ outbound
|
||||
- วิธีเปิดเผย transcripts และสถานะ transport ที่ normalize แล้ว
|
||||
- วิธีดำเนินการ actions ที่อิงจาก transport
|
||||
- วิธีจัดการ reset หรือ cleanup เฉพาะ transport
|
||||
- วิธี mount `openclaw qa <runner>` ใต้รูท `qa` ที่ใช้ร่วมกัน
|
||||
- วิธีกำหนดค่า Gateway สำหรับ transport นั้น
|
||||
- วิธีตรวจสอบความพร้อม
|
||||
- วิธีฉีด event ขาเข้า
|
||||
- วิธีสังเกตข้อความขาออก
|
||||
- วิธีเปิดเผย transcript และสถานะ transport ที่ normalized แล้ว
|
||||
- วิธีดำเนิน action ที่มี transport รองรับ
|
||||
- วิธีจัดการการ reset หรือ cleanup เฉพาะ transport
|
||||
|
||||
เกณฑ์ขั้นต่ำในการนำ channel ใหม่มาใช้:
|
||||
เกณฑ์ขั้นต่ำในการนำช่องทางใหม่มาใช้:
|
||||
|
||||
1. ให้ `qa-lab` เป็นเจ้าของ root `qa` ที่ใช้ร่วมกันต่อไป
|
||||
2. นำ transport runner ไปใช้งานบนจุดเชื่อมของโฮสต์ `qa-lab` ที่ใช้ร่วมกัน
|
||||
3. เก็บกลไกเฉพาะ transport ไว้ใน Plugin ของ runner หรือ harness ของ channel
|
||||
4. เมานต์ runner เป็น `openclaw qa <runner>` แทนการลงทะเบียนคำสั่ง root ที่แข่งขันกัน Plugin ของ runner ควรประกาศ `qaRunners` ใน `openclaw.plugin.json` และส่งออกอาร์เรย์ `qaRunnerCliRegistrations` ที่ตรงกันจาก `runtime-api.ts` ทำให้ `runtime-api.ts` เบาไว้; การทำงานของ CLI และ runner แบบ lazy ควรอยู่หลัง entrypoint แยกต่างหาก
|
||||
5. เขียนหรือปรับสถานการณ์ markdown ภายใต้ไดเรกทอรี `qa/scenarios/` ตามธีม
|
||||
6. ใช้ helper สถานการณ์แบบทั่วไปสำหรับสถานการณ์ใหม่
|
||||
7. รักษา alias สำหรับความเข้ากันได้เดิมให้ใช้งานได้ต่อไป เว้นแต่ repo กำลังทำ migration โดยตั้งใจ
|
||||
1. ให้ `qa-lab` เป็นเจ้าของรูท `qa` ที่ใช้ร่วมกันต่อไป
|
||||
2. Implement ตัวรัน transport บน seam โฮสต์ `qa-lab` ที่ใช้ร่วมกัน
|
||||
3. เก็บกลไกเฉพาะ transport ไว้ภายใน Plugin ตัวรันหรือ harness ของช่องทาง
|
||||
4. Mount ตัวรันเป็น `openclaw qa <runner>` แทนการลงทะเบียนคำสั่งรูทที่แข่งขันกัน Plugin ตัวรันควรประกาศ `qaRunners` ใน `openclaw.plugin.json` และ export อาร์เรย์ `qaRunnerCliRegistrations` ที่ตรงกันจาก `runtime-api.ts` ให้ `runtime-api.ts` เบาไว้ ส่วน CLI แบบ lazy และการดำเนินการตัวรันควรอยู่หลัง entrypoint แยกต่างหาก
|
||||
5. เขียนหรือปรับ scenario แบบ Markdown ใต้ไดเรกทอรี `qa/scenarios/` ตามธีม
|
||||
6. ใช้ helper scenario แบบ generic สำหรับ scenario ใหม่
|
||||
7. รักษานามแฝงความเข้ากันได้ที่มีอยู่ให้ใช้งานได้ เว้นแต่ repo กำลังทำการ migration โดยตั้งใจ
|
||||
|
||||
กฎการตัดสินใจเข้มงวด:
|
||||
|
||||
- ถ้าพฤติกรรมสามารถอธิบายได้ครั้งเดียวใน `qa-lab` ให้ใส่ไว้ใน `qa-lab`
|
||||
- ถ้าพฤติกรรมขึ้นกับ channel transport หนึ่งรายการ ให้เก็บไว้ใน Plugin ของ runner หรือ harness ของ Plugin นั้น
|
||||
- ถ้าสถานการณ์ต้องการความสามารถใหม่ที่มากกว่าหนึ่ง channel ใช้ได้ ให้เพิ่ม helper แบบทั่วไปแทน branch เฉพาะ channel ใน `suite.ts`
|
||||
- ถ้าพฤติกรรมมีความหมายเฉพาะกับ transport เดียว ให้สถานการณ์เป็นแบบเฉพาะ transport และระบุเรื่องนั้นให้ชัดเจนในสัญญาของสถานการณ์
|
||||
- หากพฤติกรรมสามารถแสดงได้ครั้งเดียวใน `qa-lab` ให้ใส่ไว้ใน `qa-lab`
|
||||
- หากพฤติกรรมขึ้นกับ transport ของช่องทางเดียว ให้เก็บไว้ใน Plugin ตัวรันนั้นหรือ harness ของ Plugin
|
||||
- หาก scenario ต้องการ capability ใหม่ที่มากกว่าหนึ่งช่องทางสามารถใช้ได้ ให้เพิ่ม helper แบบ generic แทน branch เฉพาะช่องทางใน `suite.ts`
|
||||
- หากพฤติกรรมมีความหมายเฉพาะกับ transport เดียวเท่านั้น ให้คง scenario นั้นเป็นแบบเฉพาะ transport และระบุให้ชัดเจนในสัญญาของ scenario
|
||||
|
||||
### ชื่อ helper ของสถานการณ์
|
||||
### ชื่อ helper ของ scenario
|
||||
|
||||
helper แบบทั่วไปที่แนะนำสำหรับสถานการณ์ใหม่:
|
||||
helper แบบ generic ที่แนะนำสำหรับ scenario ใหม่:
|
||||
|
||||
- `waitForTransportReady`
|
||||
- `waitForChannelReady`
|
||||
@ -440,22 +462,22 @@ helper แบบทั่วไปที่แนะนำสำหรับส
|
||||
- `formatTransportTranscript`
|
||||
- `resetTransport`
|
||||
|
||||
alias สำหรับความเข้ากันได้ยังคงมีให้ใช้สำหรับสถานการณ์เดิม — `waitForQaChannelReady`, `waitForOutboundMessage`, `waitForNoOutbound`, `formatConversationTranscript`, `resetBus` — แต่การเขียนสถานการณ์ใหม่ควรใช้ชื่อแบบทั่วไป alias เหล่านี้มีไว้เพื่อหลีกเลี่ยงการ migration แบบบังคับพร้อมกันทั้งหมด ไม่ใช่โมเดลสำหรับอนาคต
|
||||
นามแฝงความเข้ากันได้ยังพร้อมใช้งานสำหรับ scenario ที่มีอยู่ — `waitForQaChannelReady`, `waitForOutboundMessage`, `waitForNoOutbound`, `formatConversationTranscript`, `resetBus` — แต่การเขียน scenario ใหม่ควรใช้ชื่อแบบ generic นามแฝงเหล่านี้มีไว้เพื่อหลีกเลี่ยงการ migration แบบ flag-day ไม่ใช่โมเดลสำหรับอนาคต
|
||||
|
||||
## การรายงาน
|
||||
|
||||
`qa-lab` ส่งออกรายงานโปรโตคอล Markdown จากไทม์ไลน์ของ bus ที่สังเกตได้
|
||||
`qa-lab` export รายงานโปรโตคอล Markdown จาก timeline ของ bus ที่สังเกตได้
|
||||
รายงานควรตอบว่า:
|
||||
|
||||
- อะไรทำงานได้
|
||||
- อะไรล้มเหลว
|
||||
- อะไรยังถูกบล็อกอยู่
|
||||
- สถานการณ์ติดตามผลใดควรเพิ่ม
|
||||
- อะไรยังคงถูกบล็อก
|
||||
- scenario ติดตามผลใดที่ควรค่าแก่การเพิ่ม
|
||||
|
||||
สำหรับรายการสถานการณ์ที่มีอยู่ — ซึ่งมีประโยชน์เมื่อประเมินขนาดงานติดตามผลหรือเชื่อมต่อ transport ใหม่ — ให้รัน `pnpm openclaw qa coverage` (เพิ่ม `--json` สำหรับเอาต์พุตที่เครื่องอ่านได้)
|
||||
สำหรับ inventory ของ scenario ที่พร้อมใช้งาน ซึ่งมีประโยชน์เมื่อประเมินขนาดงานติดตามผลหรือเชื่อม transport ใหม่ ให้รัน `pnpm openclaw qa coverage` (เพิ่ม `--json` สำหรับ output ที่ machine-readable)
|
||||
|
||||
สำหรับการตรวจสอบลักษณะตัวละครและสไตล์ ให้รันสถานการณ์เดียวกันกับ ref ของโมเดล live หลายรายการ
|
||||
แล้วเขียนรายงาน Markdown ที่ผ่านการตัดสิน:
|
||||
สำหรับการตรวจ character และ style ให้รัน scenario เดียวกันกับ ref ของโมเดล live หลายตัว
|
||||
และเขียนรายงาน Markdown ที่ตัดสินแล้ว:
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa character-eval \
|
||||
@ -474,42 +496,41 @@ pnpm openclaw qa character-eval \
|
||||
--judge-concurrency 16
|
||||
```
|
||||
|
||||
คำสั่งนี้รันโปรเซสลูกของ QA gateway ในเครื่อง ไม่ใช่ Docker สถานการณ์ character eval
|
||||
ควรกำหนด persona ผ่าน `SOUL.md` จากนั้นรัน turn ผู้ใช้ตามปกติ
|
||||
เช่น chat, ความช่วยเหลือใน workspace และงานไฟล์ขนาดเล็ก ไม่ควรบอกโมเดลผู้สมัคร
|
||||
ว่ากำลังถูกประเมิน คำสั่งจะเก็บ transcript ฉบับเต็มแต่ละรายการ
|
||||
บันทึกสถิติพื้นฐานของการรัน จากนั้นถามโมเดลผู้ตัดสินในโหมด fast พร้อมการให้เหตุผล
|
||||
`xhigh` เมื่อรองรับ เพื่อจัดอันดับการรันตามความเป็นธรรมชาติ vibe และอารมณ์ขัน
|
||||
ใช้ `--blind-judge-models` เมื่อเปรียบเทียบผู้ให้บริการ: prompt ของผู้ตัดสินยังคงได้รับ
|
||||
transcript และสถานะการรันทุกอย่าง แต่ ref ของผู้สมัครจะถูกแทนที่ด้วย
|
||||
ป้ายกำกับกลาง เช่น `candidate-01`; รายงานจะแมปอันดับกลับไปยัง ref จริงหลังจาก
|
||||
คำสั่งนี้รันกระบวนการลูกของ Gateway QA ในเครื่อง ไม่ใช่ Docker scenario ประเมิน character
|
||||
ควรตั้ง persona ผ่าน `SOUL.md` จากนั้นรัน turn ผู้ใช้ทั่วไป
|
||||
เช่น แชต ความช่วยเหลือเกี่ยวกับ workspace และงานไฟล์เล็ก ๆ ไม่ควรบอกโมเดล candidate
|
||||
ว่ากำลังถูกประเมิน คำสั่งจะเก็บ transcript เต็มแต่ละรายการ
|
||||
บันทึกสถิติการรันพื้นฐาน แล้วถามโมเดล judge ในโหมด fast พร้อม
|
||||
reasoning `xhigh` เมื่อรองรับ เพื่อจัดอันดับการรันตามความเป็นธรรมชาติ vibe และอารมณ์ขัน
|
||||
ใช้ `--blind-judge-models` เมื่อเปรียบเทียบ provider: prompt ของ judge ยังได้รับ
|
||||
ทุก transcript และสถานะการรัน แต่ ref ของ candidate จะถูกแทนที่ด้วย label กลาง
|
||||
เช่น `candidate-01`; รายงานจะ map การจัดอันดับกลับไปยัง ref จริงหลังจาก
|
||||
parse แล้ว
|
||||
การรันผู้สมัครมีค่าเริ่มต้นเป็น thinking `high` โดยใช้ `medium` สำหรับ GPT-5.5 และ `xhigh`
|
||||
สำหรับ ref eval ของ OpenAI รุ่นเก่าที่รองรับ กำหนดทับผู้สมัครเฉพาะรายแบบ inline ด้วย
|
||||
`--model provider/model,thinking=<level>` `--thinking <level>` ยังคงตั้งค่า
|
||||
fallback ส่วนกลาง และรูปแบบเก่า `--model-thinking <provider/model=level>` ยังคง
|
||||
เก็บไว้เพื่อความเข้ากันได้
|
||||
ref ผู้สมัครของ OpenAI มีค่าเริ่มต้นเป็นโหมด fast เพื่อให้ใช้ priority processing ในจุดที่
|
||||
ผู้ให้บริการรองรับ เพิ่ม `,fast`, `,no-fast` หรือ `,fast=false` แบบ inline เมื่อ
|
||||
ผู้สมัครหรือผู้ตัดสินรายเดียวต้องการ override ส่ง `--fast` เฉพาะเมื่อคุณต้องการ
|
||||
บังคับเปิดโหมด fast สำหรับโมเดลผู้สมัครทุกตัว ระยะเวลาของผู้สมัครและผู้ตัดสินจะ
|
||||
ถูกบันทึกในรายงานสำหรับการวิเคราะห์ benchmark แต่ prompt ของผู้ตัดสินระบุอย่างชัดเจน
|
||||
การรัน candidate ใช้ thinking ค่าเริ่มต้นเป็น `high` โดยใช้ `medium` สำหรับ GPT-5.5 และ `xhigh`
|
||||
สำหรับ ref eval ของ OpenAI รุ่นเก่าที่รองรับ Override candidate เฉพาะรายการแบบ inline ด้วย
|
||||
`--model provider/model,thinking=<level>` ส่วน `--thinking <level>` ยังตั้งค่า
|
||||
fallback ส่วนกลาง และรูปแบบเก่า `--model-thinking <provider/model=level>` ยังคงไว้เพื่อความเข้ากันได้
|
||||
ref candidate ของ OpenAI ใช้โหมด fast เป็นค่าเริ่มต้นเพื่อใช้ priority processing ในที่ที่
|
||||
provider รองรับ เพิ่ม `,fast`, `,no-fast`, หรือ `,fast=false` แบบ inline เมื่อ
|
||||
candidate หรือ judge รายเดียวต้องการ override ส่ง `--fast` เฉพาะเมื่อต้องการ
|
||||
บังคับเปิดโหมด fast สำหรับโมเดล candidate ทุกตัว ระยะเวลาของ candidate และ judge
|
||||
จะถูกบันทึกในรายงานสำหรับการวิเคราะห์ benchmark แต่ prompt ของ judge ระบุอย่างชัดเจน
|
||||
ว่าอย่าจัดอันดับตามความเร็ว
|
||||
การรันโมเดลผู้สมัครและผู้ตัดสินมีค่า concurrency เริ่มต้นเป็น 16 ทั้งคู่ ลด
|
||||
`--concurrency` หรือ `--judge-concurrency` เมื่อขีดจำกัดของผู้ให้บริการหรือแรงกดบน gateway
|
||||
ในเครื่องทำให้การรันมีสัญญาณรบกวนมากเกินไป
|
||||
เมื่อไม่ได้ส่ง `--model` ของผู้สมัคร character eval จะใช้ค่าเริ่มต้นเป็น
|
||||
การรันโมเดล candidate และ judge ใช้ concurrency 16 เป็นค่าเริ่มต้น ลด
|
||||
`--concurrency` หรือ `--judge-concurrency` เมื่อข้อจำกัดของ provider หรือแรงกดดันต่อ Gateway
|
||||
ในเครื่องทำให้การรันมี noise มากเกินไป
|
||||
เมื่อไม่ได้ส่ง candidate `--model` การประเมิน character จะใช้ค่าเริ่มต้นเป็น
|
||||
`openai/gpt-5.5`, `openai/gpt-5.2`, `openai/gpt-5`, `anthropic/claude-opus-4-6`,
|
||||
`anthropic/claude-sonnet-4-6`, `zai/glm-5.1`,
|
||||
`moonshot/kimi-k2.5` และ
|
||||
`moonshot/kimi-k2.5`, และ
|
||||
`google/gemini-3.1-pro-preview` เมื่อไม่ได้ส่ง `--model`
|
||||
เมื่อไม่ได้ส่ง `--judge-model` ผู้ตัดสินจะใช้ค่าเริ่มต้นเป็น
|
||||
เมื่อไม่ได้ส่ง `--judge-model` judge จะใช้ค่าเริ่มต้นเป็น
|
||||
`openai/gpt-5.5,thinking=xhigh,fast` และ
|
||||
`anthropic/claude-opus-4-6,thinking=high`
|
||||
|
||||
## เอกสารที่เกี่ยวข้อง
|
||||
|
||||
- [QA แบบเมทริกซ์](/th/concepts/qa-matrix)
|
||||
- [QA Channel](/th/channels/qa-channel)
|
||||
- [ช่องทาง QA](/th/channels/qa-channel)
|
||||
- [การทดสอบ](/th/help/testing)
|
||||
- [แดชบอร์ด](/th/web/dashboard)
|
||||
|
||||
@ -1,29 +1,29 @@
|
||||
---
|
||||
read_when:
|
||||
- อธิบายวิธีการทำงานของการสตรีมหรือการแบ่งเป็นส่วนย่อยในช่องทาง
|
||||
- การเปลี่ยนลักษณะการทำงานของการสตรีมแบบบล็อกหรือการแบ่งส่วนของช่องทาง
|
||||
- การดีบักการตอบกลับแบบบล็อกที่ซ้ำกัน/เร็วเกินไป หรือการสตรีมตัวอย่างช่องทาง
|
||||
summary: พฤติกรรมการสตรีม + การแบ่งเป็นชิ้น (การตอบกลับแบบบล็อก, การสตรีมพรีวิวช่องทาง, การแมปโหมด)
|
||||
title: การสตรีมและการแบ่งเป็นชิ้นข้อมูล
|
||||
- อธิบายวิธีการทำงานของการสตรีมหรือการแบ่งเป็นชิ้นส่วนในช่องทาง
|
||||
- การเปลี่ยนพฤติกรรมการสตรีมแบบบล็อกหรือการแบ่งเป็นชิ้นของช่องทาง
|
||||
- การดีบักการตอบกลับแบบบล็อกที่ซ้ำ/เร็วเกินไป หรือการสตรีมตัวอย่างของช่องทาง
|
||||
summary: พฤติกรรมการสตรีม + การแบ่งเป็นชิ้น (การตอบกลับแบบบล็อก, การสตรีมตัวอย่างช่องทาง, การแมปโหมด)
|
||||
title: การสตรีมและการแบ่งเป็นชิ้น
|
||||
x-i18n:
|
||||
generated_at: "2026-05-03T21:30:53Z"
|
||||
generated_at: "2026-05-04T07:05:05Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 1335f4f5532060bd8bf839683a2b1fbab38f38887c5583135652b4753e0f6a50
|
||||
source_hash: ff7b6cd8127255352fe16fb746469e9828e7d5aea183d3799ab10cc768515bd1
|
||||
source_path: concepts/streaming.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
OpenClaw มีเลเยอร์สตรีมมิงแยกกันสองชั้น:
|
||||
OpenClaw มีเลเยอร์การสตรีมสองชั้นที่แยกจากกัน:
|
||||
|
||||
- **สตรีมมิงแบบบล็อก (ช่องทาง):** ส่ง **บล็อก** ที่เสร็จแล้วออกไปขณะที่ผู้ช่วยกำลังเขียน ข้อความเหล่านี้เป็นข้อความช่องทางปกติ (ไม่ใช่ token deltas)
|
||||
- **สตรีมมิงแบบพรีวิว (Telegram/Discord/Slack):** อัปเดต **ข้อความพรีวิว** ชั่วคราวระหว่างกำลังสร้างคำตอบ
|
||||
- **การสตรีมแบบบล็อก (ช่องทาง):** ส่ง **บล็อก** ที่เสร็จแล้วขณะที่ผู้ช่วยเขียนอยู่ ข้อความเหล่านี้เป็นข้อความช่องทางปกติ (ไม่ใช่เดลตาโทเค็น)
|
||||
- **การสตรีมตัวอย่าง (Telegram/Discord/Slack):** อัปเดต **ข้อความตัวอย่าง** ชั่วคราวระหว่างการสร้างคำตอบ
|
||||
|
||||
ปัจจุบันยัง **ไม่มีสตรีมมิง token-delta จริง** ไปยังข้อความช่องทาง สตรีมมิงแบบพรีวิวอิงข้อความ (ส่ง + แก้ไข/ต่อท้าย)
|
||||
ปัจจุบันยังไม่มี **การสตรีมเดลตาโทเค็นจริง** ไปยังข้อความช่องทาง การสตรีมตัวอย่างอิงตามข้อความ (ส่ง + แก้ไข/ต่อท้าย)
|
||||
|
||||
## สตรีมมิงแบบบล็อก (ข้อความช่องทาง)
|
||||
## การสตรีมแบบบล็อก (ข้อความช่องทาง)
|
||||
|
||||
สตรีมมิงแบบบล็อกส่งเอาต์พุตของผู้ช่วยเป็นชังก์หยาบ ๆ เมื่อพร้อมใช้งาน
|
||||
การสตรีมแบบบล็อกส่งเอาต์พุตของผู้ช่วยเป็นชิ้นหยาบ ๆ เมื่อพร้อมใช้งาน
|
||||
|
||||
```
|
||||
Model output
|
||||
@ -35,183 +35,165 @@ Model output
|
||||
└─ channel send (block replies)
|
||||
```
|
||||
|
||||
คำอธิบาย:
|
||||
คำอธิบายสัญลักษณ์:
|
||||
|
||||
- `text_delta/events`: อีเวนต์สตรีมของโมเดล (อาจมีแบบห่าง ๆ สำหรับโมเดลที่ไม่สตรีม)
|
||||
- `chunker`: `EmbeddedBlockChunker` ที่ใช้ขอบเขต min/max + การตั้งค่า break preference
|
||||
- `channel send`: ข้อความขาออกจริง (การตอบกลับแบบบล็อก)
|
||||
- `text_delta/events`: เหตุการณ์สตรีมของโมเดล (อาจมีน้อยสำหรับโมเดลที่ไม่สตรีม)
|
||||
- `chunker`: `EmbeddedBlockChunker` ที่ใช้ขอบเขตขั้นต่ำ/สูงสุด + การตั้งค่าแบ่ง
|
||||
- `channel send`: ข้อความขาออกจริง (คำตอบแบบบล็อก)
|
||||
|
||||
**การควบคุม:**
|
||||
|
||||
- `agents.defaults.blockStreamingDefault`: `"on"`/`"off"` (ค่าเริ่มต้นคือปิด)
|
||||
- การ override ระดับช่องทาง: `*.blockStreaming` (และตัวแปรต่อบัญชี) เพื่อบังคับ `"on"`/`"off"` ต่อช่องทาง
|
||||
- การเขียนทับระดับช่องทาง: `*.blockStreaming` (และรูปแบบต่อบัญชี) เพื่อบังคับ `"on"`/`"off"` ต่อช่องทาง
|
||||
- `agents.defaults.blockStreamingBreak`: `"text_end"` หรือ `"message_end"`
|
||||
- `agents.defaults.blockStreamingChunk`: `{ minChars, maxChars, breakPreference? }`
|
||||
- `agents.defaults.blockStreamingCoalesce`: `{ minChars?, maxChars?, idleMs? }` (รวมบล็อกที่สตรีมก่อนส่ง)
|
||||
- เพดานสูงสุดของช่องทาง: `*.textChunkLimit` (เช่น `channels.whatsapp.textChunkLimit`)
|
||||
- โหมดชังก์ของช่องทาง: `*.chunkMode` (`length` เป็นค่าเริ่มต้น, `newline` แยกตามบรรทัดว่าง (ขอบเขตย่อหน้า) ก่อนแยกตามความยาว)
|
||||
- เพดานแบบนุ่มของ Discord: `channels.discord.maxLinesPerMessage` (ค่าเริ่มต้น 17) แยกการตอบกลับที่สูงเพื่อหลีกเลี่ยงการถูกตัดใน UI
|
||||
- เพดานตายตัวของช่องทาง: `*.textChunkLimit` (เช่น `channels.whatsapp.textChunkLimit`)
|
||||
- โหมดการแบ่งชิ้นของช่องทาง: `*.chunkMode` (`length` เป็นค่าเริ่มต้น, `newline` แบ่งตามบรรทัดว่าง (ขอบเขตย่อหน้า) ก่อนแบ่งตามความยาว)
|
||||
- เพดานแบบยืดหยุ่นของ Discord: `channels.discord.maxLinesPerMessage` (ค่าเริ่มต้น 17) แบ่งคำตอบที่สูงเพื่อหลีกเลี่ยงการถูกตัดใน UI
|
||||
|
||||
**ความหมายของขอบเขต:**
|
||||
|
||||
- `text_end`: สตรีมบล็อกทันทีที่ chunker ส่งออก; flush ในแต่ละ `text_end`
|
||||
- `message_end`: รอจนข้อความผู้ช่วยจบ แล้วจึง flush เอาต์พุตที่ buffer ไว้
|
||||
- `text_end`: สตรีมบล็อกทันทีที่ตัวแบ่งชิ้นส่งออกมา; ล้างบัฟเฟอร์เมื่อถึงแต่ละ `text_end`
|
||||
- `message_end`: รอจนข้อความผู้ช่วยเสร็จสิ้น แล้วจึงล้างเอาต์พุตที่บัฟเฟอร์ไว้
|
||||
|
||||
`message_end` ยังคงใช้ chunker ถ้าข้อความที่ buffer ไว้เกิน `maxChars` ดังนั้นจึงอาจส่งออกได้หลายชังก์ในตอนท้าย
|
||||
`message_end` ยังคงใช้ตัวแบ่งชิ้นหากข้อความที่บัฟเฟอร์ไว้เกิน `maxChars` ดังนั้นจึงอาจส่งออกหลายชิ้นในตอนท้ายได้
|
||||
|
||||
### การส่งสื่อด้วยสตรีมมิงแบบบล็อก
|
||||
### การส่งสื่อด้วยการสตรีมแบบบล็อก
|
||||
|
||||
คำสั่ง `MEDIA:` เป็นเมตาดาต้าการส่งตามปกติ เมื่อสตรีมมิงแบบบล็อกส่ง
|
||||
บล็อกสื่อออกไปก่อน OpenClaw จะจดจำการส่งนั้นสำหรับเทิร์นนี้ ถ้า payload สุดท้าย
|
||||
ของผู้ช่วยมี URL สื่อเดียวกันซ้ำ การส่งสุดท้ายจะตัดสื่อที่ซ้ำออก
|
||||
แทนการส่งไฟล์แนบอีกครั้ง
|
||||
คำสั่ง `MEDIA:` เป็นเมตาดาต้าการส่งปกติ เมื่อการสตรีมแบบบล็อกส่งบล็อกสื่อตั้งแต่เนิ่น ๆ OpenClaw จะจดจำการส่งนั้นไว้สำหรับเทิร์นดังกล่าว หากเพย์โหลดผู้ช่วยสุดท้ายซ้ำ URL สื่อเดียวกัน การส่งสุดท้ายจะตัดสื่อที่ซ้ำออกแทนที่จะส่งไฟล์แนบอีกครั้ง
|
||||
|
||||
payload สุดท้ายที่ซ้ำกันทุกประการจะถูกระงับ ถ้า payload สุดท้ายเพิ่ม
|
||||
ข้อความที่แตกต่างรอบสื่อที่สตรีมไปแล้ว OpenClaw ยังส่ง
|
||||
ข้อความใหม่โดยคงสื่อให้มีการส่งเพียงครั้งเดียว วิธีนี้ป้องกัน voice notes
|
||||
หรือไฟล์ซ้ำบนช่องทางอย่าง Telegram เมื่อ agent ส่ง `MEDIA:` ระหว่าง
|
||||
สตรีมมิงและ provider รวมสิ่งนั้นไว้ในคำตอบที่เสร็จแล้วด้วย
|
||||
เพย์โหลดสุดท้ายที่ซ้ำกันทุกประการจะถูกระงับ หากเพย์โหลดสุดท้ายเพิ่มข้อความที่แตกต่างรอบสื่อที่สตรีมไปแล้ว OpenClaw จะยังส่งข้อความใหม่ขณะคงให้สื่อถูกส่งเพียงครั้งเดียว สิ่งนี้ป้องกันโน้ตเสียงหรือไฟล์ซ้ำบนช่องทางอย่าง Telegram เมื่อเอเจนต์ส่ง `MEDIA:` ระหว่างสตรีม และผู้ให้บริการรวมสิ่งนั้นไว้ในคำตอบที่เสร็จสมบูรณ์ด้วย
|
||||
|
||||
## อัลกอริทึมการแบ่งชังก์ (ขอบเขตต่ำ/สูง)
|
||||
## อัลกอริทึมการแบ่งชิ้น (ขอบเขตต่ำ/สูง)
|
||||
|
||||
การแบ่งชังก์แบบบล็อกถูกใช้งานโดย `EmbeddedBlockChunker`:
|
||||
การแบ่งชิ้นแบบบล็อกดำเนินการโดย `EmbeddedBlockChunker`:
|
||||
|
||||
- **ขอบเขตต่ำ:** อย่าส่งออกจนกว่า buffer >= `minChars` (เว้นแต่ถูกบังคับ)
|
||||
- **ขอบเขตสูง:** เลือกแยกก่อน `maxChars`; ถ้าถูกบังคับ ให้แยกที่ `maxChars`
|
||||
- **การตั้งค่า break preference:** `paragraph` → `newline` → `sentence` → `whitespace` → hard break
|
||||
- **Code fences:** ไม่แยกภายใน fences; เมื่อถูกบังคับที่ `maxChars` ให้ปิด + เปิด fence ใหม่เพื่อให้ Markdown ยังถูกต้อง
|
||||
- **ขอบเขตต่ำ:** อย่าส่งออกจนกว่าบัฟเฟอร์ >= `minChars` (ยกเว้นเมื่อถูกบังคับ)
|
||||
- **ขอบเขตสูง:** เลือกแบ่งก่อน `maxChars`; หากถูกบังคับ ให้แบ่งที่ `maxChars`
|
||||
- **การตั้งค่าแบ่ง:** `paragraph` → `newline` → `sentence` → `whitespace` → แบ่งแบบแข็ง
|
||||
- **รั้วโค้ด:** ไม่แบ่งภายในรั้วเด็ดขาด; เมื่อถูกบังคับที่ `maxChars` ให้ปิด + เปิดรั้วใหม่เพื่อให้ Markdown ยังคงถูกต้อง
|
||||
|
||||
`maxChars` ถูก clamp ตาม `textChunkLimit` ของช่องทาง ดังนั้นคุณจึงไม่สามารถเกินเพดานต่อช่องทางได้
|
||||
`maxChars` ถูกจำกัดไว้ที่ `textChunkLimit` ของช่องทาง ดังนั้นคุณจึงไม่สามารถเกินเพดานต่อช่องทางได้
|
||||
|
||||
## การรวมชังก์ (รวมบล็อกที่สตรีม)
|
||||
## การรวมชิ้น (รวมบล็อกที่สตรีม)
|
||||
|
||||
เมื่อเปิดใช้งานสตรีมมิงแบบบล็อก OpenClaw สามารถ **รวมชังก์บล็อกที่ต่อเนื่องกัน**
|
||||
ก่อนส่งออกได้ วิธีนี้ลด “สแปมบรรทัดเดียว” ในขณะที่ยังคงให้
|
||||
เอาต์พุตแบบค่อยเป็นค่อยไป
|
||||
เมื่อเปิดใช้การสตรีมแบบบล็อก OpenClaw สามารถ **รวมชิ้นบล็อกที่ต่อเนื่องกัน** ก่อนส่งออกได้ สิ่งนี้ช่วยลด “สแปมบรรทัดเดียว” ขณะที่ยังคงให้เอาต์พุตแบบค่อยเป็นค่อยไป
|
||||
|
||||
- การรวมชังก์รอ **ช่วงว่างที่ idle** (`idleMs`) ก่อน flush
|
||||
- Buffer ถูกจำกัดด้วย `maxChars` และจะ flush ถ้าเกินค่านั้น
|
||||
- `minChars` ป้องกันไม่ให้ส่งส่วนย่อยที่เล็กมากจนกว่าจะสะสมข้อความได้พอ
|
||||
(final flush จะส่งข้อความที่เหลือเสมอ)
|
||||
- ตัวเชื่อมได้มาจาก `blockStreamingChunk.breakPreference`
|
||||
- การรวมชิ้นจะรอ **ช่วงว่างที่ไม่มีความเคลื่อนไหว** (`idleMs`) ก่อนล้างบัฟเฟอร์
|
||||
- บัฟเฟอร์ถูกจำกัดด้วย `maxChars` และจะล้างหากเกินค่านั้น
|
||||
- `minChars` ป้องกันไม่ให้ส่งเศษข้อความเล็ก ๆ จนกว่าจะสะสมข้อความได้เพียงพอ (การล้างครั้งสุดท้ายจะส่งข้อความที่เหลือเสมอ)
|
||||
- ตัวเชื่อมมาจาก `blockStreamingChunk.breakPreference`
|
||||
(`paragraph` → `\n\n`, `newline` → `\n`, `sentence` → เว้นวรรค)
|
||||
- การ override ระดับช่องทางใช้ได้ผ่าน `*.blockStreamingCoalesce` (รวมถึง config ต่อบัญชี)
|
||||
- ค่าเริ่มต้นของการรวมชังก์ `minChars` ถูกเพิ่มเป็น 1500 สำหรับ Signal/Slack/Discord เว้นแต่จะ override
|
||||
- การเขียนทับระดับช่องทางพร้อมใช้งานผ่าน `*.blockStreamingCoalesce` (รวมถึงการกำหนดค่าต่อบัญชี)
|
||||
- ค่าเริ่มต้น `minChars` ของการรวมชิ้นถูกเพิ่มเป็น 1500 สำหรับ Signal/Slack/Discord เว้นแต่จะถูกเขียนทับ
|
||||
|
||||
## จังหวะเว้นระหว่างบล็อกแบบเหมือนมนุษย์
|
||||
## จังหวะระหว่างบล็อกที่เหมือนมนุษย์
|
||||
|
||||
เมื่อเปิดใช้งานสตรีมมิงแบบบล็อก คุณสามารถเพิ่ม **การหยุดแบบสุ่ม** ระหว่าง
|
||||
การตอบกลับแบบบล็อก (หลังบล็อกแรก) ได้ วิธีนี้ทำให้คำตอบแบบหลาย bubble ดู
|
||||
เป็นธรรมชาติมากขึ้น
|
||||
เมื่อเปิดใช้การสตรีมแบบบล็อก คุณสามารถเพิ่ม **การหยุดแบบสุ่ม** ระหว่างคำตอบแบบบล็อก (หลังบล็อกแรก) ได้ สิ่งนี้ทำให้คำตอบแบบหลายบับเบิลรู้สึกเป็นธรรมชาติมากขึ้น
|
||||
|
||||
- Config: `agents.defaults.humanDelay` (override ต่อ agent ผ่าน `agents.list[].humanDelay`)
|
||||
- การกำหนดค่า: `agents.defaults.humanDelay` (เขียนทับต่อเอเจนต์ได้ผ่าน `agents.list[].humanDelay`)
|
||||
- โหมด: `off` (ค่าเริ่มต้น), `natural` (800–2500ms), `custom` (`minMs`/`maxMs`)
|
||||
- ใช้กับ **การตอบกลับแบบบล็อก** เท่านั้น ไม่ใช่การตอบกลับสุดท้ายหรือสรุปเครื่องมือ
|
||||
- ใช้กับ **คำตอบแบบบล็อก** เท่านั้น ไม่ใช้กับคำตอบสุดท้ายหรือสรุปเครื่องมือ
|
||||
|
||||
## "สตรีมชังก์หรือทุกอย่าง"
|
||||
## "สตรีมเป็นชิ้นหรือทั้งหมด"
|
||||
|
||||
สิ่งนี้แมปเป็น:
|
||||
|
||||
- **สตรีมชังก์:** `blockStreamingDefault: "on"` + `blockStreamingBreak: "text_end"` (ส่งออกไปเรื่อย ๆ) ช่องทางที่ไม่ใช่ Telegram ยังต้องมี `*.blockStreaming: true` ด้วย
|
||||
- **สตรีมทุกอย่างตอนท้าย:** `blockStreamingBreak: "message_end"` (flush หนึ่งครั้ง อาจเป็นหลายชังก์ถ้ายาวมาก)
|
||||
- **ไม่มีสตรีมมิงแบบบล็อก:** `blockStreamingDefault: "off"` (เฉพาะการตอบกลับสุดท้าย)
|
||||
- **สตรีมเป็นชิ้น:** `blockStreamingDefault: "on"` + `blockStreamingBreak: "text_end"` (ส่งออกไปเรื่อย ๆ) ช่องทางที่ไม่ใช่ Telegram ต้องมี `*.blockStreaming: true` ด้วย
|
||||
- **สตรีมทั้งหมดเมื่อจบ:** `blockStreamingBreak: "message_end"` (ล้างครั้งเดียว อาจเป็นหลายชิ้นหากยาวมาก)
|
||||
- **ไม่ใช้การสตรีมแบบบล็อก:** `blockStreamingDefault: "off"` (เฉพาะคำตอบสุดท้าย)
|
||||
|
||||
**หมายเหตุช่องทาง:** สตรีมมิงแบบบล็อกจะ **ปิด เว้นแต่**
|
||||
`*.blockStreaming` ถูกตั้งเป็น `true` อย่างชัดเจน ช่องทางสามารถสตรีมพรีวิวสด
|
||||
(`channels.<channel>.streaming`) ได้โดยไม่มีการตอบกลับแบบบล็อก
|
||||
**หมายเหตุช่องทาง:** การสตรีมแบบบล็อกจะ **ปิดอยู่ เว้นแต่**
|
||||
จะตั้งค่า `*.blockStreaming` เป็น `true` อย่างชัดเจน ช่องทางสามารถสตรีมตัวอย่างสด (`channels.<channel>.streaming`) ได้โดยไม่ต้องมีคำตอบแบบบล็อก
|
||||
|
||||
ตัวเตือนตำแหน่ง config: ค่าเริ่มต้น `blockStreaming*` อยู่ใต้
|
||||
`agents.defaults` ไม่ใช่ config ราก
|
||||
เตือนตำแหน่งการกำหนดค่า: ค่าเริ่มต้น `blockStreaming*` อยู่ภายใต้
|
||||
`agents.defaults` ไม่ใช่การกำหนดค่าราก
|
||||
|
||||
## โหมดสตรีมมิงแบบพรีวิว
|
||||
## โหมดการสตรีมตัวอย่าง
|
||||
|
||||
คีย์มาตรฐาน: `channels.<channel>.streaming`
|
||||
|
||||
โหมด:
|
||||
|
||||
- `off`: ปิดสตรีมมิงแบบพรีวิว
|
||||
- `partial`: พรีวิวเดียวที่ถูกแทนที่ด้วยข้อความล่าสุด
|
||||
- `block`: พรีวิวอัปเดตแบบแบ่งชังก์/ต่อท้ายเป็นขั้น ๆ
|
||||
- `progress`: พรีวิวความคืบหน้า/สถานะระหว่างสร้าง และคำตอบสุดท้ายเมื่อเสร็จ
|
||||
- `off`: ปิดใช้การสตรีมตัวอย่าง
|
||||
- `partial`: ตัวอย่างเดียวที่ถูกแทนที่ด้วยข้อความล่าสุด
|
||||
- `block`: อัปเดตตัวอย่างเป็นขั้นตอนแบบแบ่งชิ้น/ต่อท้าย
|
||||
- `progress`: ตัวอย่างความคืบหน้า/สถานะระหว่างการสร้าง และคำตอบสุดท้ายเมื่อเสร็จสิ้น
|
||||
|
||||
`streaming.mode: "block"` เป็นโหมดสตรีมมิงแบบพรีวิวสำหรับช่องทางที่แก้ไขได้
|
||||
เช่น Discord และ Telegram โหมดนี้ไม่ได้เปิดการส่งแบบบล็อกของช่องทางที่นั่น
|
||||
ใช้ `streaming.block.enabled` หรือคีย์ช่องทาง legacy `blockStreaming` เมื่อ
|
||||
คุณต้องการการตอบกลับแบบบล็อกปกติ Microsoft Teams เป็นข้อยกเว้น: ไม่มี
|
||||
draft-preview block transport ดังนั้น `streaming.mode: "block"` จึงแมปเป็นการส่งแบบบล็อกของ Teams
|
||||
แทนสตรีมมิง partial/progress แบบ native
|
||||
`streaming.mode: "block"` เป็นโหมดการสตรีมตัวอย่างสำหรับช่องทางที่แก้ไขได้ เช่น Discord และ Telegram ซึ่งไม่ได้เปิดใช้การส่งแบบบล็อกของช่องทางที่นั่น ใช้ `streaming.block.enabled` หรือคีย์ช่องทางเดิม `blockStreaming` เมื่อคุณต้องการคำตอบแบบบล็อกปกติ Microsoft Teams เป็นข้อยกเว้น: ไม่มีการขนส่งบล็อกแบบร่างตัวอย่าง ดังนั้น `streaming.mode: "block"` จึงแมปไปยังการส่งแบบบล็อกของ Teams แทนการสตรีมแบบบางส่วน/ความคืบหน้าเนทีฟ
|
||||
|
||||
### การแมประดับช่องทาง
|
||||
### การแมปช่องทาง
|
||||
|
||||
| ช่องทาง | `off` | `partial` | `block` | `progress` |
|
||||
| ---------- | ----- | --------- | ------- | ----------------------- |
|
||||
| Telegram | ✅ | ✅ | ✅ | draft ความคืบหน้าที่แก้ไขได้ |
|
||||
| Discord | ✅ | ✅ | ✅ | draft ความคืบหน้าที่แก้ไขได้ |
|
||||
| Telegram | ✅ | ✅ | ✅ | ร่างความคืบหน้าที่แก้ไขได้ |
|
||||
| Discord | ✅ | ✅ | ✅ | ร่างความคืบหน้าที่แก้ไขได้ |
|
||||
| Slack | ✅ | ✅ | ✅ | ✅ |
|
||||
| Mattermost | ✅ | ✅ | ✅ | ✅ |
|
||||
| MS Teams | ✅ | ✅ | ✅ | สตรีมความคืบหน้าแบบ native |
|
||||
| MS Teams | ✅ | ✅ | ✅ | สตรีมความคืบหน้าเนทีฟ |
|
||||
|
||||
เฉพาะ Slack:
|
||||
สำหรับ Slack เท่านั้น:
|
||||
|
||||
- `channels.slack.streaming.nativeTransport` สลับการเรียก Slack native streaming API เมื่อ `channels.slack.streaming.mode="partial"` (ค่าเริ่มต้น: `true`)
|
||||
- Slack native streaming และสถานะเธรดผู้ช่วยของ Slack ต้องมีเป้าหมายเป็นเธรดตอบกลับ DMs ระดับบนสุดจะไม่แสดงพรีวิวแบบ thread-style นั้น แต่ยังใช้โพสต์พรีวิว draft ของ Slack และการแก้ไขได้
|
||||
- Slack native streaming และสถานะเธรดผู้ช่วยของ Slack ต้องมีเป้าหมายเธรดตอบกลับ DM ระดับบนสุดไม่แสดงตัวอย่างแบบเธรดนั้น แต่ยังสามารถใช้โพสต์และการแก้ไขตัวอย่างร่างของ Slack ได้
|
||||
|
||||
การย้ายคีย์ legacy:
|
||||
การย้ายคีย์เดิม:
|
||||
|
||||
- Telegram: ค่า legacy `streamMode` และค่า scalar/boolean `streaming` จะถูกตรวจพบและย้ายโดยเส้นทางความเข้ากันได้ของ doctor/config ไปยัง `streaming.mode`
|
||||
- Discord: `streamMode` + boolean `streaming` ย้ายอัตโนมัติเป็น enum `streaming`
|
||||
- Slack: `streamMode` ย้ายอัตโนมัติเป็น `streaming.mode`; boolean `streaming` ย้ายอัตโนมัติเป็น `streaming.mode` พร้อม `streaming.nativeTransport`; legacy `nativeStreaming` ย้ายอัตโนมัติเป็น `streaming.nativeTransport`
|
||||
- Telegram: ค่าเดิม `streamMode` และค่า `streaming` แบบสเกลาร์/บูลีนจะถูกตรวจพบและย้ายโดยเส้นทางความเข้ากันได้ของ doctor/config ไปยัง `streaming.mode`
|
||||
- Discord: `streamMode` + `streaming` แบบบูลีนจะย้ายอัตโนมัติไปยัง enum `streaming`
|
||||
- Slack: `streamMode` จะย้ายอัตโนมัติไปยัง `streaming.mode`; `streaming` แบบบูลีนจะย้ายอัตโนมัติไปยัง `streaming.mode` พร้อม `streaming.nativeTransport`; `nativeStreaming` แบบเดิมจะย้ายอัตโนมัติไปยัง `streaming.nativeTransport`
|
||||
|
||||
### พฤติกรรมขณะรันไทม์
|
||||
### พฤติกรรมรันไทม์
|
||||
|
||||
Telegram:
|
||||
|
||||
- ใช้ `sendMessage` + `editMessageText` สำหรับอัปเดตพรีวิวใน DMs และกลุ่ม/หัวข้อ
|
||||
- ส่งข้อความสุดท้ายใหม่แทนการแก้ไขข้อความเดิมเมื่อพรีวิวมองเห็นมาประมาณหนึ่งนาที จากนั้นล้างพรีวิวเพื่อให้ timestamp ของ Telegram สะท้อนเวลาที่ตอบเสร็จ
|
||||
- ข้ามสตรีมมิงแบบพรีวิวเมื่อเปิดสตรีมมิงแบบบล็อกของ Telegram อย่างชัดเจน (เพื่อหลีกเลี่ยงการสตรีมซ้ำสองทาง)
|
||||
- `/reasoning stream` สามารถเขียน reasoning ไปยังพรีวิวได้
|
||||
- ใช้การอัปเดตตัวอย่างด้วย `sendMessage` + `editMessageText` ทั้งใน DM และกลุ่ม/หัวข้อ
|
||||
- ส่งข้อความสุดท้ายใหม่แทนการแก้ไขที่เดิมเมื่อมีตัวอย่างแสดงอยู่ประมาณหนึ่งนาที จากนั้นล้างตัวอย่างเพื่อให้เวลาประทับของ Telegram สะท้อนการตอบกลับเสร็จสิ้น
|
||||
- ข้ามการสตรีมตัวอย่างเมื่อเปิดใช้การสตรีมแบบบล็อกของ Telegram อย่างชัดเจน (เพื่อหลีกเลี่ยงการสตรีมซ้ำซ้อน)
|
||||
- `/reasoning stream` สามารถเขียนเหตุผลไปยังตัวอย่างชั่วคราวที่ถูกลบหลังการส่งสุดท้าย
|
||||
|
||||
Discord:
|
||||
|
||||
- ใช้ข้อความพรีวิวแบบส่ง + แก้ไข
|
||||
- โหมด `block` ใช้การแบ่งชังก์ draft (`draftChunk`)
|
||||
- ข้ามสตรีมมิงแบบพรีวิวเมื่อเปิดสตรีมมิงแบบบล็อกของ Discord อย่างชัดเจน
|
||||
- payload สื่อสุดท้าย ข้อผิดพลาด และ explicit-reply จะยกเลิกพรีวิวที่ค้างอยู่โดยไม่ flush draft ใหม่ แล้วใช้การส่งตามปกติ
|
||||
- ใช้การส่ง + แก้ไขข้อความตัวอย่าง
|
||||
- โหมด `block` ใช้การแบ่งชิ้นร่าง (`draftChunk`)
|
||||
- ข้ามการสตรีมตัวอย่างเมื่อเปิดใช้การสตรีมแบบบล็อกของ Discord อย่างชัดเจน
|
||||
- เพย์โหลดสื่อสุดท้าย ข้อผิดพลาด และการตอบกลับแบบชัดเจนจะยกเลิกตัวอย่างที่ค้างอยู่โดยไม่ล้างร่างใหม่ แล้วใช้การส่งปกติ
|
||||
|
||||
Slack:
|
||||
|
||||
- `partial` สามารถใช้ Slack native streaming (`chat.startStream`/`append`/`stop`) เมื่อพร้อมใช้งาน
|
||||
- `block` ใช้พรีวิว draft แบบต่อท้าย
|
||||
- `progress` ใช้ข้อความพรีวิวสถานะ แล้วตามด้วยคำตอบสุดท้าย
|
||||
- DMs ระดับบนสุดที่ไม่มีเธรดตอบกลับใช้โพสต์พรีวิว draft และการแก้ไขแทน Slack native streaming
|
||||
- Native และ draft preview streaming จะระงับการตอบกลับแบบบล็อกสำหรับเทิร์นนั้น ดังนั้นการตอบกลับของ Slack จึงถูกสตรีมผ่านเส้นทางการส่งเพียงเส้นทางเดียว
|
||||
- payload สื่อ/ข้อผิดพลาดสุดท้ายและ progress finals จะไม่สร้างข้อความ draft ชั่วคราวที่ทิ้งได้; เฉพาะ text/block finals ที่แก้ไขพรีวิวได้เท่านั้นที่จะ flush ข้อความ draft ที่ค้างอยู่
|
||||
- `block` ใช้ตัวอย่างร่างแบบต่อท้าย
|
||||
- `progress` ใช้ข้อความตัวอย่างสถานะ แล้วตามด้วยคำตอบสุดท้าย
|
||||
- DM ระดับบนสุดที่ไม่มีเธรดตอบกลับจะใช้โพสต์และการแก้ไขตัวอย่างร่างแทน Slack native streaming
|
||||
- การสตรีมตัวอย่างทั้งแบบเนทีฟและแบบร่างจะระงับคำตอบแบบบล็อกสำหรับเทิร์นนั้น ดังนั้นคำตอบของ Slack จะถูกสตรีมผ่านเส้นทางการส่งเพียงเส้นทางเดียว
|
||||
- เพย์โหลดสื่อ/ข้อผิดพลาดสุดท้ายและผลลัพธ์สุดท้ายของความคืบหน้าจะไม่สร้างข้อความร่างชั่วคราว; เฉพาะผลลัพธ์สุดท้ายแบบข้อความ/บล็อกที่แก้ไขตัวอย่างได้เท่านั้นที่จะล้างข้อความร่างที่ค้างอยู่
|
||||
|
||||
Mattermost:
|
||||
|
||||
- สตรีมการคิด กิจกรรมเครื่องมือ และข้อความตอบกลับบางส่วนลงในโพสต์พรีวิว draft เดียวที่ finalize ในที่เดิมเมื่อส่งคำตอบสุดท้ายได้อย่างปลอดภัย
|
||||
- fallback ไปส่งโพสต์สุดท้ายใหม่ถ้าโพสต์พรีวิวถูกลบหรือไม่พร้อมใช้งานในเวลา finalize
|
||||
- payload สื่อ/ข้อผิดพลาดสุดท้ายจะยกเลิกการอัปเดตพรีวิวที่ค้างอยู่ก่อนการส่งปกติ แทนการ flush โพสต์พรีวิวชั่วคราว
|
||||
- สตรีมการคิด กิจกรรมเครื่องมือ และข้อความตอบกลับบางส่วนเข้าไปในโพสต์ตัวอย่างร่างเดียว ซึ่งจะสรุปจบที่เดิมเมื่อคำตอบสุดท้ายปลอดภัยที่จะส่ง
|
||||
- ถอยกลับไปส่งโพสต์สุดท้ายใหม่หากโพสต์ตัวอย่างถูกลบหรือไม่พร้อมใช้งานด้วยเหตุผลอื่นเมื่อถึงเวลาสรุปจบ
|
||||
- เพย์โหลดสื่อ/ข้อผิดพลาดสุดท้ายจะยกเลิกการอัปเดตตัวอย่างที่ค้างอยู่ก่อนการส่งปกติ แทนที่จะล้างโพสต์ตัวอย่างชั่วคราว
|
||||
|
||||
Matrix:
|
||||
|
||||
- พรีวิว draft finalize ในที่เดิมเมื่อข้อความสุดท้ายสามารถใช้ event พรีวิวซ้ำได้
|
||||
- finals ที่เป็นเฉพาะสื่อ ข้อผิดพลาด และเป้าหมายตอบกลับไม่ตรงกันจะยกเลิกการอัปเดตพรีวิวที่ค้างอยู่ก่อนการส่งปกติ; พรีวิวเก่าที่มองเห็นอยู่แล้วจะถูก redact
|
||||
- ตัวอย่างร่างจะสรุปจบที่เดิมเมื่อข้อความสุดท้ายสามารถใช้เหตุการณ์ตัวอย่างซ้ำได้
|
||||
- ผลลัพธ์สุดท้ายแบบเฉพาะสื่อ ข้อผิดพลาด และเป้าหมายตอบกลับไม่ตรงกันจะยกเลิกการอัปเดตตัวอย่างที่ค้างอยู่ก่อนการส่งปกติ; ตัวอย่างเก่าที่มองเห็นอยู่แล้วจะถูกแก้ไขทับ
|
||||
|
||||
### การอัปเดตพรีวิวความคืบหน้าของเครื่องมือ
|
||||
### การอัปเดตตัวอย่างความคืบหน้าของเครื่องมือ
|
||||
|
||||
สตรีมมิงแบบพรีวิวยังสามารถรวมการอัปเดต **tool-progress** ได้ด้วย เช่น บรรทัดสถานะสั้น ๆ อย่าง "กำลังค้นหาเว็บ", "กำลังอ่านไฟล์", หรือ "กำลังเรียกเครื่องมือ" ซึ่งปรากฏในข้อความพรีวิวเดียวกันระหว่างที่เครื่องมือกำลังทำงาน ก่อนคำตอบสุดท้าย วิธีนี้ทำให้เทิร์นที่มีเครื่องมือหลายขั้นตอนยังดูมีความเคลื่อนไหว แทนที่จะเงียบระหว่างพรีวิวการคิดครั้งแรกกับคำตอบสุดท้าย
|
||||
การสตรีมตัวอย่างยังสามารถรวมการอัปเดต **ความคืบหน้าของเครื่องมือ** ได้ด้วย ซึ่งเป็นบรรทัดสถานะสั้น ๆ เช่น "กำลังค้นหาเว็บ", "กำลังอ่านไฟล์" หรือ "กำลังเรียกเครื่องมือ" ที่ปรากฏในข้อความตัวอย่างเดียวกันขณะเครื่องมือกำลังทำงาน ก่อนคำตอบสุดท้าย สิ่งนี้ทำให้เทิร์นเครื่องมือหลายขั้นตอนยังดูมีการเคลื่อนไหว แทนที่จะเงียบระหว่างตัวอย่างการคิดแรกกับคำตอบสุดท้าย
|
||||
|
||||
พื้นผิวที่รองรับ:
|
||||
|
||||
- **Discord**, **Slack**, **Telegram**, และ **Matrix** สตรีม tool-progress ลงในการแก้ไขพรีวิวสดตามค่าเริ่มต้นเมื่อสตรีมมิงแบบพรีวิวทำงาน Microsoft Teams ใช้สตรีมความคืบหน้าแบบ native ในแชตส่วนตัว
|
||||
- Telegram ได้เผยแพร่พร้อมการอัปเดตพรีวิว tool-progress ที่เปิดใช้งานตั้งแต่ `v2026.4.22`; การเปิดไว้ต่อไปจะรักษาพฤติกรรมที่ปล่อยแล้วนั้น
|
||||
- **Mattermost** รวมกิจกรรมเครื่องมือเข้าในโพสต์พรีวิว draft เดียวอยู่แล้ว (ดูด้านบน)
|
||||
- การแก้ไข tool-progress จะตามโหมดสตรีมมิงแบบพรีวิวที่ใช้งานอยู่; จะถูกข้ามเมื่อสตรีมมิงแบบพรีวิวเป็น `off` หรือเมื่อสตรีมมิงแบบบล็อกเข้าควบคุมข้อความแล้ว บน Telegram, `streaming.mode: "off"` คือ final-only: ข้อความความคืบหน้าทั่วไปจะถูกระงับด้วยแทนที่จะถูกส่งเป็นข้อความสถานะแยกต่างหาก ในขณะที่ approval prompts, payload สื่อ และข้อผิดพลาดยัง route ตามปกติ
|
||||
- หากต้องการคงสตรีมมิงแบบพรีวิวไว้แต่ซ่อนบรรทัด tool-progress ให้ตั้ง `streaming.preview.toolProgress` เป็น `false` สำหรับช่องทางนั้น หากต้องการปิดการแก้ไขพรีวิวทั้งหมด ให้ตั้ง `streaming.mode` เป็น `off`
|
||||
- การตอบกลับ quote ที่เลือกใน Telegram เป็นข้อยกเว้น: เมื่อ `replyToMode` ไม่ใช่ `"off"` และมีข้อความ quote ที่เลือก OpenClaw จะข้ามสตรีมพรีวิวคำตอบสำหรับเทิร์นนั้น ดังนั้นบรรทัดพรีวิว tool-progress จึงไม่สามารถเรนเดอร์ได้ การตอบกลับข้อความปัจจุบันที่ไม่มีข้อความ quote ที่เลือกยังคงใช้สตรีมมิงแบบพรีวิว ดูรายละเอียดใน [เอกสารช่องทาง Telegram](/th/channels/telegram)
|
||||
- **Discord**, **Slack**, **Telegram** และ **Matrix** สตรีมความคืบหน้าของเครื่องมือเข้าไปในการแก้ไขตัวอย่างสดโดยค่าเริ่มต้นเมื่อการสตรีมตัวอย่างทำงานอยู่ Microsoft Teams ใช้สตรีมความคืบหน้าเนทีฟในแชตส่วนตัว
|
||||
- Telegram ส่งมาพร้อมการเปิดใช้การอัปเดตตัวอย่างความคืบหน้าของเครื่องมือตั้งแต่ `v2026.4.22`; การเปิดไว้ต่อไปจะรักษาพฤติกรรมที่เผยแพร่แล้วนั้น
|
||||
- **Mattermost** รวมกิจกรรมเครื่องมือเข้าไปในโพสต์ตัวอย่างร่างเดียวอยู่แล้ว (ดูด้านบน)
|
||||
- การแก้ไขความคืบหน้าของเครื่องมือจะทำตามโหมดการสตรีมตัวอย่างที่ใช้งานอยู่; จะถูกข้ามเมื่อการสตรีมตัวอย่างเป็น `off` หรือเมื่อการสตรีมแบบบล็อกเข้าควบคุมข้อความแล้ว บน Telegram, `streaming.mode: "off"` คือเฉพาะคำตอบสุดท้าย: ข้อความคืบหน้าทั่วไปจะถูกระงับด้วย แทนที่จะถูกส่งเป็นข้อความสถานะแยกต่างหาก ขณะที่พรอมป์อนุมัติ เพย์โหลดสื่อ และข้อผิดพลาดยังคงถูกส่งตามปกติ
|
||||
- หากต้องการคงการสตรีมตัวอย่างไว้แต่ซ่อนบรรทัดความคืบหน้าของเครื่องมือ ให้ตั้งค่า `streaming.preview.toolProgress` เป็น `false` สำหรับช่องทางนั้น หากต้องการให้บรรทัดความคืบหน้าของเครื่องมือยังมองเห็นได้ขณะซ่อนข้อความคำสั่ง/การดำเนินการ ให้ตั้งค่า `streaming.preview.commandText` เป็น `"status"` หรือ `streaming.progress.commandText` เป็น `"status"`; ค่าเริ่มต้นคือ `"raw"` เพื่อรักษาพฤติกรรมที่เผยแพร่แล้ว นโยบายนี้ใช้ร่วมกันโดยช่องทางแบบร่าง/ความคืบหน้าที่ใช้ตัวแสดงผลความคืบหน้าแบบกะทัดรัดของ OpenClaw รวมถึง Discord, Matrix, Microsoft Teams, Mattermost, ตัวอย่างร่างของ Slack และ Telegram หากต้องการปิดการแก้ไขตัวอย่างทั้งหมด ให้ตั้งค่า `streaming.mode` เป็น `off`
|
||||
- การตอบกลับด้วยข้อความอ้างอิงที่เลือกใน Telegram เป็นข้อยกเว้น: เมื่อ `replyToMode` ไม่ใช่ `"off"` และมีข้อความอ้างอิงที่เลือกอยู่ OpenClaw จะข้ามสตรีมตัวอย่างคำตอบสำหรับเทิร์นนั้น ดังนั้นบรรทัดตัวอย่างความคืบหน้าของเครื่องมือจึงไม่สามารถแสดงผลได้ การตอบกลับข้อความปัจจุบันที่ไม่มีข้อความอ้างอิงที่เลือกยังคงใช้การสตรีมตัวอย่าง ดูรายละเอียดใน [เอกสารช่องทาง Telegram](/th/channels/telegram)
|
||||
|
||||
ตัวอย่าง:
|
||||
ให้บรรทัดความคืบหน้ายังคงมองเห็นได้ แต่ซ่อนข้อความ command/exec ดิบ:
|
||||
|
||||
```json
|
||||
{
|
||||
@ -220,7 +202,26 @@ Matrix:
|
||||
"streaming": {
|
||||
"mode": "partial",
|
||||
"preview": {
|
||||
"toolProgress": false
|
||||
"toolProgress": true,
|
||||
"commandText": "status"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
ใช้โครงสร้างเดียวกันภายใต้คีย์ช่องทางความคืบหน้าแบบกะทัดรัดอื่น เช่น `channels.discord`, `channels.matrix`, `channels.msteams`, `channels.mattermost` หรือการแสดงตัวอย่างร่างของ Slack สำหรับโหมดร่างความคืบหน้า ให้ใส่นโยบายเดียวกันภายใต้ `streaming.progress`:
|
||||
|
||||
```json
|
||||
{
|
||||
"channels": {
|
||||
"telegram": {
|
||||
"streaming": {
|
||||
"mode": "progress",
|
||||
"progress": {
|
||||
"toolProgress": true,
|
||||
"commandText": "status"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -230,7 +231,7 @@ Matrix:
|
||||
|
||||
## ที่เกี่ยวข้อง
|
||||
|
||||
- [Progress drafts](/th/concepts/progress-drafts) — ข้อความงานที่กำลังดำเนินอยู่ซึ่งมองเห็นได้และอัปเดตระหว่างเทิร์นที่ยาว
|
||||
- [ร่างความคืบหน้า](/th/concepts/progress-drafts) — ข้อความงานที่กำลังดำเนินการซึ่งมองเห็นได้และอัปเดตระหว่างเทิร์นที่ใช้เวลานาน
|
||||
- [ข้อความ](/th/concepts/messages) — วงจรชีวิตและการส่งข้อความ
|
||||
- [ลองใหม่](/th/concepts/retry) — พฤติกรรมการลองใหม่เมื่อการส่งล้มเหลว
|
||||
- [ช่องทาง](/th/channels) — การรองรับสตรีมมิงต่อช่องทาง
|
||||
- [ช่องทาง](/th/channels) — การรองรับการสตรีมแยกตามช่องทาง
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,29 +1,29 @@
|
||||
---
|
||||
read_when:
|
||||
- การอัปเดต OpenClaw
|
||||
- มีบางอย่างใช้งานไม่ได้หลังจากอัปเดต
|
||||
summary: การอัปเดต OpenClaw อย่างปลอดภัย (ติดตั้งแบบโกลบอลหรือจากซอร์ส) พร้อมกลยุทธ์การย้อนกลับ
|
||||
- มีบางอย่างขัดข้องหลังจากการอัปเดต
|
||||
summary: การอัปเดต OpenClaw อย่างปลอดภัย (การติดตั้งทั่วทั้งระบบหรือจากซอร์สโค้ด) พร้อมกลยุทธ์การย้อนกลับ
|
||||
title: การอัปเดต
|
||||
x-i18n:
|
||||
generated_at: "2026-05-03T21:34:50Z"
|
||||
generated_at: "2026-05-04T07:05:15Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: f9e26ea71748dfd1573cdca01126bf29ebc56be56eac604e2b6a009b463820d1
|
||||
source_hash: 3c9ff1d70d74f45efea3c148718e5cbc74001ce3d924b760edc4d68622d23714
|
||||
source_path: install/updating.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
อัปเดต OpenClaw ให้เป็นปัจจุบันอยู่เสมอ
|
||||
ทำให้ OpenClaw เป็นปัจจุบันอยู่เสมอ
|
||||
|
||||
## แนะนำ: `openclaw update`
|
||||
|
||||
วิธีอัปเดตที่เร็วที่สุด คำสั่งนี้ตรวจหาประเภทการติดตั้งของคุณ (npm หรือ git), ดึงเวอร์ชันล่าสุด, รัน `openclaw doctor`, และรีสตาร์ต Gateway
|
||||
วิธีอัปเดตที่เร็วที่สุด โดยจะตรวจจับประเภทการติดตั้งของคุณ (npm หรือ git), ดึงเวอร์ชันล่าสุด, รัน `openclaw doctor`, และรีสตาร์ต Gateway
|
||||
|
||||
```bash
|
||||
openclaw update
|
||||
```
|
||||
|
||||
หากต้องการสลับช่องทางหรือตั้งเป้าเป็นเวอร์ชันเฉพาะ:
|
||||
หากต้องการสลับช่องทางหรือระบุเวอร์ชันเป้าหมาย:
|
||||
|
||||
```bash
|
||||
openclaw update --channel beta
|
||||
@ -32,22 +32,22 @@ openclaw update --tag main
|
||||
openclaw update --dry-run # preview without applying
|
||||
```
|
||||
|
||||
`openclaw update` ไม่รับ `--verbose` สำหรับการวินิจฉัยการอัปเดต ให้ใช้
|
||||
`openclaw update` ไม่รองรับ `--verbose` สำหรับการวินิจฉัยการอัปเดต ให้ใช้
|
||||
`--dry-run` เพื่อดูตัวอย่างการดำเนินการที่วางแผนไว้, `--json` สำหรับผลลัพธ์แบบมีโครงสร้าง, หรือ
|
||||
`openclaw update status --json` เพื่อตรวจสอบสถานะช่องทางและความพร้อมใช้งาน
|
||||
ตัวติดตั้งมีแฟล็ก `--verbose` ของตัวเอง แต่แฟล็กนั้นไม่ได้เป็นส่วนหนึ่งของ
|
||||
`openclaw update status --json` เพื่อตรวจสอบสถานะช่องทางและความพร้อมใช้งาน ตัวติดตั้ง
|
||||
มีแฟล็ก `--verbose` ของตัวเอง แต่แฟล็กนั้นไม่ได้เป็นส่วนหนึ่งของ
|
||||
`openclaw update`
|
||||
|
||||
`--channel beta` จะเลือก beta ก่อน แต่ runtime จะ fallback ไปที่ stable/latest เมื่อ
|
||||
แท็ก beta ไม่มีอยู่หรือเก่ากว่ารีลีส stable ล่าสุด ใช้ `--tag beta`
|
||||
หากคุณต้องการ npm beta dist-tag ดิบสำหรับการอัปเดตแพ็กเกจแบบครั้งเดียว
|
||||
`--channel beta` จะเลือก beta เป็นหลัก แต่รันไทม์จะย้อนกลับไปใช้ stable/latest เมื่อ
|
||||
แท็ก beta หายไปหรือเก่ากว่ารุ่น stable ล่าสุด ใช้ `--tag beta`
|
||||
หากคุณต้องการ dist-tag beta ดิบของ npm สำหรับการอัปเดตแพ็กเกจแบบครั้งเดียว
|
||||
|
||||
ดู [ช่องทางการพัฒนา](/th/install/development-channels) สำหรับความหมายของช่องทาง
|
||||
|
||||
## สลับระหว่างการติดตั้ง npm และ git
|
||||
## สลับระหว่างการติดตั้งแบบ npm และ git
|
||||
|
||||
ใช้ช่องทางเมื่อคุณต้องการเปลี่ยนประเภทการติดตั้ง ตัวอัปเดตจะเก็บ
|
||||
สถานะ, config, credentials, และ workspace ของคุณไว้ใน `~/.openclaw`; มันจะเปลี่ยนเฉพาะ
|
||||
สถานะ, คอนฟิก, ข้อมูลประจำตัว, และเวิร์กสเปซของคุณไว้ใน `~/.openclaw`; โดยจะเปลี่ยนเฉพาะ
|
||||
การติดตั้งโค้ด OpenClaw ที่ CLI และ Gateway ใช้เท่านั้น
|
||||
|
||||
```bash
|
||||
@ -65,10 +65,10 @@ openclaw update --channel dev --dry-run
|
||||
openclaw update --channel stable --dry-run
|
||||
```
|
||||
|
||||
ช่องทาง `dev` ทำให้มั่นใจว่ามี git checkout, build มัน, และติดตั้ง CLI แบบ global
|
||||
จาก checkout นั้น ช่องทาง `stable` และ `beta` ใช้การติดตั้งแพ็กเกจ หาก
|
||||
Gateway ติดตั้งอยู่แล้ว `openclaw update` จะรีเฟรช service metadata
|
||||
และรีสตาร์ต เว้นแต่คุณจะส่ง `--no-restart`
|
||||
ช่องทาง `dev` จะทำให้แน่ใจว่ามี git checkout, สร้างมัน, และติดตั้ง CLI แบบ global
|
||||
จาก checkout นั้น ช่องทาง `stable` และ `beta` ใช้การติดตั้งแบบแพ็กเกจ หาก
|
||||
Gateway ติดตั้งอยู่แล้ว `openclaw update` จะรีเฟรชข้อมูลเมตาของบริการ
|
||||
และรีสตาร์ตบริการนั้น เว้นแต่คุณจะส่ง `--no-restart`
|
||||
|
||||
## ทางเลือก: รันตัวติดตั้งอีกครั้ง
|
||||
|
||||
@ -76,37 +76,42 @@ Gateway ติดตั้งอยู่แล้ว `openclaw update` จะ
|
||||
curl -fsSL https://openclaw.ai/install.sh | bash
|
||||
```
|
||||
|
||||
เพิ่ม `--no-onboard` เพื่อข้าม onboarding หากต้องการบังคับประเภทการติดตั้งเฉพาะผ่าน
|
||||
เพิ่ม `--no-onboard` เพื่อข้ามการเริ่มต้นใช้งาน หากต้องการบังคับประเภทการติดตั้งเฉพาะผ่าน
|
||||
ตัวติดตั้ง ให้ส่ง `--install-method git --no-onboard` หรือ
|
||||
`--install-method npm --no-onboard`
|
||||
|
||||
หาก `openclaw update` ล้มเหลวหลังจากขั้นตอนติดตั้งแพ็กเกจ npm ให้รัน
|
||||
ตัวติดตั้งอีกครั้ง ตัวติดตั้งจะไม่เรียกตัวอัปเดตเก่า; มันรันการติดตั้งแพ็กเกจ
|
||||
global โดยตรงและสามารถกู้คืนการติดตั้ง npm ที่อัปเดตไปบางส่วนได้
|
||||
ตัวติดตั้งอีกครั้ง ตัวติดตั้งจะไม่เรียกตัวอัปเดตเก่า แต่จะรันการติดตั้งแพ็กเกจ
|
||||
global โดยตรง และสามารถกู้คืนการติดตั้ง npm ที่อัปเดตไปบางส่วนได้
|
||||
|
||||
```bash
|
||||
curl -fsSL https://openclaw.ai/install.sh | bash -s -- --install-method npm
|
||||
```
|
||||
|
||||
หากต้องการตรึงการกู้คืนไว้ที่เวอร์ชันหรือ dist-tag เฉพาะ ให้เพิ่ม `--version`:
|
||||
หากต้องการตรึงการกู้คืนไว้กับเวอร์ชันหรือ dist-tag เฉพาะ ให้เพิ่ม `--version`:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://openclaw.ai/install.sh | bash -s -- --install-method npm --version <version-or-dist-tag>
|
||||
```
|
||||
|
||||
## ทางเลือก: npm, pnpm, หรือ bun แบบแมนนวล
|
||||
## ทางเลือก: npm, pnpm, หรือ bun แบบ manual
|
||||
|
||||
```bash
|
||||
npm i -g openclaw@latest
|
||||
```
|
||||
|
||||
เมื่อ `openclaw update` จัดการการติดตั้ง npm แบบ global มันจะติดตั้งเป้าหมายลงใน
|
||||
temporary npm prefix ก่อน, ตรวจสอบ packaged `dist` inventory, แล้วจึงสลับ
|
||||
package tree ที่สะอาดเข้าไปใน global prefix จริง วิธีนี้หลีกเลี่ยงไม่ให้ npm ซ้อนทับ
|
||||
แพ็กเกจใหม่ลงบนไฟล์เก่าที่ค้างจากแพ็กเกจเดิม หากคำสั่งติดตั้งล้มเหลว
|
||||
OpenClaw จะลองอีกครั้งหนึ่งพร้อม `--omit=optional` การลองซ้ำนี้ช่วยโฮสต์ที่ native
|
||||
optional dependencies คอมไพล์ไม่ได้ ขณะเดียวกันก็ยังทำให้เห็น failure เดิม
|
||||
หาก fallback ล้มเหลวเช่นกัน
|
||||
ควรใช้ `openclaw update` สำหรับการติดตั้งที่มีการควบคุมดูแล เพราะสามารถประสาน
|
||||
การสลับแพ็กเกจกับบริการ Gateway ที่กำลังทำงานอยู่ได้ หากคุณอัปเดตแบบ manual ขณะที่
|
||||
Gateway ที่จัดการอยู่กำลังทำงาน ให้รีสตาร์ต Gateway ทันทีหลังจากตัวจัดการแพ็กเกจ
|
||||
ทำงานเสร็จ เพื่อไม่ให้โปรเซสเก่ายังคงให้บริการจากไฟล์แพ็กเกจที่ถูกแทนที่แล้ว
|
||||
|
||||
เมื่อ `openclaw update` จัดการการติดตั้ง npm แบบ global จะติดตั้งเป้าหมายลงใน
|
||||
prefix npm ชั่วคราวก่อน, ตรวจสอบรายการ `dist` ที่แพ็กไว้, แล้วจึงสลับ
|
||||
แผนผังแพ็กเกจที่สะอาดเข้าไปใน prefix global จริง วิธีนี้หลีกเลี่ยงไม่ให้ npm ทับซ้อน
|
||||
แพ็กเกจใหม่ลงบนไฟล์ค้างเก่าจากแพ็กเกจเดิม หากคำสั่งติดตั้งล้มเหลว
|
||||
OpenClaw จะลองอีกครั้งหนึ่งด้วย `--omit=optional` การลองใหม่นี้ช่วยโฮสต์ที่ dependency
|
||||
แบบ optional ที่เป็น native ไม่สามารถคอมไพล์ได้ ขณะที่ยังคงแสดงความล้มเหลวเดิม
|
||||
หาก fallback ก็ล้มเหลวเช่นกัน
|
||||
|
||||
```bash
|
||||
pnpm add -g openclaw@latest
|
||||
@ -116,31 +121,31 @@ pnpm add -g openclaw@latest
|
||||
bun add -g openclaw@latest
|
||||
```
|
||||
|
||||
### หัวข้อการติดตั้ง npm ขั้นสูง
|
||||
### หัวข้อขั้นสูงสำหรับการติดตั้ง npm
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Package tree แบบอ่านอย่างเดียว">
|
||||
OpenClaw ถือว่าการติดตั้ง global แบบแพ็กเกจเป็นแบบอ่านอย่างเดียวใน runtime แม้ว่า directory แพ็กเกจ global จะเขียนได้โดยผู้ใช้ปัจจุบันก็ตาม การติดตั้งแพ็กเกจ Plugin จะอยู่ใน npm/git roots ที่ OpenClaw เป็นเจ้าของภายใต้ directory config ของผู้ใช้ และการเริ่มต้น Gateway จะไม่แก้ไข package tree ของ OpenClaw
|
||||
<Accordion title="Read-only package tree">
|
||||
OpenClaw ถือว่าการติดตั้ง global แบบแพ็กเกจเป็นแบบอ่านอย่างเดียวขณะรันไทม์ แม้ว่าไดเรกทอรีแพ็กเกจ global จะเขียนได้โดยผู้ใช้ปัจจุบันก็ตาม การติดตั้งแพ็กเกจ Plugin จะอยู่ในราก npm/git ที่ OpenClaw เป็นเจ้าของภายใต้ไดเรกทอรีคอนฟิกของผู้ใช้ และการเริ่มต้น Gateway จะไม่แก้ไขแผนผังแพ็กเกจ OpenClaw
|
||||
|
||||
การตั้งค่า npm บน Linux บางแบบติดตั้งแพ็กเกจ global ไว้ใน directory ที่ root เป็นเจ้าของ เช่น `/usr/lib/node_modules/openclaw` OpenClaw รองรับ layout นี้เพราะคำสั่งติดตั้ง/อัปเดต Plugin จะเขียนนอก directory แพ็กเกจ global นั้น
|
||||
การตั้งค่า npm บน Linux บางแบบติดตั้งแพ็กเกจ global ไว้ใต้ไดเรกทอรีที่ root เป็นเจ้าของ เช่น `/usr/lib/node_modules/openclaw` OpenClaw รองรับรูปแบบนี้ เพราะคำสั่งติดตั้ง/อัปเดต Plugin จะเขียนนอกไดเรกทอรีแพ็กเกจ global นั้น
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="systemd units ที่ทำให้แข็งแรงขึ้น">
|
||||
ให้ OpenClaw มีสิทธิ์เขียนไปยัง config/state roots ของมัน เพื่อให้การติดตั้ง Plugin แบบ explicit, การอัปเดต Plugin, และการล้างข้อมูลของ doctor สามารถบันทึกการเปลี่ยนแปลงได้:
|
||||
<Accordion title="Hardened systemd units">
|
||||
ให้สิทธิ์ OpenClaw เขียนไปยังรากคอนฟิก/สถานะ เพื่อให้การติดตั้ง Plugin แบบ explicit, การอัปเดต Plugin, และการล้างข้อมูลโดย doctor สามารถบันทึกการเปลี่ยนแปลงได้:
|
||||
|
||||
```ini
|
||||
ReadWritePaths=/var/lib/openclaw /home/openclaw/.openclaw /tmp
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="การตรวจสอบพื้นที่ดิสก์ล่วงหน้า">
|
||||
ก่อนการอัปเดตแพ็กเกจและการติดตั้ง Plugin แบบ explicit, OpenClaw จะพยายามตรวจสอบพื้นที่ดิสก์แบบ best-effort สำหรับ volume เป้าหมาย พื้นที่เหลือน้อยจะสร้างคำเตือนพร้อม path ที่ตรวจสอบ แต่จะไม่บล็อกการอัปเดต เพราะ filesystem quotas, snapshots, และ network volumes อาจเปลี่ยนหลังจากการตรวจสอบได้ การติดตั้งของ package-manager จริงและการตรวจสอบหลังติดตั้งยังคงเป็นแหล่งอ้างอิงหลัก
|
||||
<Accordion title="Disk-space preflight">
|
||||
ก่อนการอัปเดตแพ็กเกจและการติดตั้ง Plugin แบบ explicit OpenClaw จะพยายามตรวจสอบพื้นที่ดิสก์แบบ best-effort สำหรับโวลุ่มเป้าหมาย พื้นที่เหลือน้อยจะสร้างคำเตือนพร้อม path ที่ตรวจสอบ แต่จะไม่บล็อกการอัปเดต เพราะ quota ของไฟล์ซิสเต็ม, snapshot, และโวลุ่มเครือข่ายอาจเปลี่ยนหลังการตรวจสอบได้ การติดตั้งจริงด้วยตัวจัดการแพ็กเกจและการตรวจสอบหลังติดตั้งยังคงเป็นหลักฐานชี้ขาด
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## ตัวอัปเดตอัตโนมัติ
|
||||
|
||||
ตัวอัปเดตอัตโนมัติปิดอยู่ตามค่าเริ่มต้น เปิดใช้งานใน `~/.openclaw/openclaw.json`:
|
||||
ตัวอัปเดตอัตโนมัติปิดอยู่เป็นค่าเริ่มต้น เปิดใช้งานใน `~/.openclaw/openclaw.json`:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -156,21 +161,21 @@ bun add -g openclaw@latest
|
||||
}
|
||||
```
|
||||
|
||||
| ช่องทาง | พฤติกรรม |
|
||||
| ช่องทาง | พฤติกรรม |
|
||||
| -------- | ------------------------------------------------------------------------------------------------------------- |
|
||||
| `stable` | รอ `stableDelayHours` แล้วจึง apply พร้อม deterministic jitter ทั่ว `stableJitterHours` (กระจาย rollout) |
|
||||
| `beta` | ตรวจสอบทุก `betaCheckIntervalHours` (ค่าเริ่มต้น: ทุกชั่วโมง) และ apply ทันที |
|
||||
| `dev` | ไม่มีการ apply อัตโนมัติ ใช้ `openclaw update` แบบแมนนวล |
|
||||
| `stable` | รอ `stableDelayHours` แล้วจึงใช้การอัปเดตพร้อม jitter แบบกำหนดแน่นอนทั่ว `stableJitterHours` (การทยอยปล่อยแบบกระจาย) |
|
||||
| `beta` | ตรวจสอบทุก `betaCheckIntervalHours` (ค่าเริ่มต้น: ทุกชั่วโมง) และใช้การอัปเดตทันที |
|
||||
| `dev` | ไม่มีการใช้การอัปเดตโดยอัตโนมัติ ใช้ `openclaw update` แบบ manual |
|
||||
|
||||
Gateway ยัง log คำแนะนำการอัปเดตเมื่อเริ่มต้นด้วย (ปิดได้ด้วย `update.checkOnStart: false`)
|
||||
สำหรับการ downgrade หรือการกู้คืนจากเหตุการณ์ ให้ตั้ง `OPENCLAW_NO_AUTO_UPDATE=1` ใน environment ของ Gateway เพื่อบล็อกการ apply อัตโนมัติ แม้เมื่อกำหนดค่า `update.auto.enabled` ไว้ คำแนะนำการอัปเดตตอนเริ่มต้นยังคงรันได้ เว้นแต่ `update.checkOnStart` จะถูกปิดด้วย
|
||||
Gateway ยังบันทึกคำใบ้การอัปเดตเมื่อเริ่มทำงานด้วย (ปิดได้ด้วย `update.checkOnStart: false`)
|
||||
สำหรับการดาวน์เกรดหรือการกู้คืนจากเหตุการณ์ ให้ตั้ง `OPENCLAW_NO_AUTO_UPDATE=1` ในสภาพแวดล้อมของ Gateway เพื่อบล็อกการใช้การอัปเดตอัตโนมัติ แม้จะกำหนดค่า `update.auto.enabled` ไว้แล้วก็ตาม คำใบ้การอัปเดตตอนเริ่มทำงานยังคงรันได้ เว้นแต่ `update.checkOnStart` จะถูกปิดด้วย
|
||||
|
||||
การอัปเดต package-manager ที่ร้องขอผ่าน handler ของ live Gateway control-plane
|
||||
จะบังคับให้รีสตาร์ตการอัปเดตแบบไม่เลื่อนเวลาและไม่มี cooldown หลังจากสลับแพ็กเกจ
|
||||
วิธีนี้หลีกเลี่ยงการปล่อย process ในหน่วยความจำเก่าให้อยู่ต่อไปนานพอที่จะ lazy-load chunks
|
||||
จาก package tree ที่ถูกแทนที่ไปแล้ว Shell `openclaw update`
|
||||
ยังคงเป็นเส้นทางที่แนะนำสำหรับการติดตั้งที่มีการกำกับดูแล เพราะมันสามารถหยุดและ
|
||||
รีสตาร์ต service รอบการอัปเดตได้
|
||||
การอัปเดตตัวจัดการแพ็กเกจที่ร้องขอผ่าน handler ของ control-plane ของ Gateway สด
|
||||
จะบังคับให้รีสตาร์ตการอัปเดตแบบไม่เลื่อนเวลาและไม่มี cooldown หลังจากการสลับแพ็กเกจ
|
||||
วิธีนี้หลีกเลี่ยงการทิ้งโปรเซสเก่าในหน่วยความจำไว้นานพอที่จะ lazy-load ชังก์
|
||||
จากแผนผังแพ็กเกจที่ถูกแทนที่ไปแล้ว คำสั่งเชลล์ `openclaw update`
|
||||
ยังคงเป็นเส้นทางที่แนะนำสำหรับการติดตั้งที่มีการควบคุมดูแล เพราะสามารถหยุดและ
|
||||
รีสตาร์ตบริการรอบการอัปเดตได้
|
||||
|
||||
## หลังจากอัปเดต
|
||||
|
||||
@ -182,7 +187,7 @@ Gateway ยัง log คำแนะนำการอัปเดตเมื
|
||||
openclaw doctor
|
||||
```
|
||||
|
||||
ย้าย config, audit นโยบาย DM, และตรวจสอบสุขภาพ Gateway รายละเอียด: [Doctor](/th/gateway/doctor)
|
||||
ย้ายคอนฟิก, ตรวจสอบนโยบาย DM, และตรวจสอบสุขภาพ Gateway รายละเอียด: [Doctor](/th/gateway/doctor)
|
||||
|
||||
### รีสตาร์ต Gateway
|
||||
|
||||
@ -198,7 +203,7 @@ openclaw health
|
||||
|
||||
</Steps>
|
||||
|
||||
## Rollback
|
||||
## ย้อนกลับ
|
||||
|
||||
### ตรึงเวอร์ชัน (npm)
|
||||
|
||||
@ -221,17 +226,17 @@ pnpm install && pnpm build
|
||||
openclaw gateway restart
|
||||
```
|
||||
|
||||
หากต้องการกลับไปเป็นล่าสุด: `git checkout main && git pull`
|
||||
หากต้องการกลับไปยังล่าสุด: `git checkout main && git pull`
|
||||
|
||||
## หากคุณติดขัด
|
||||
|
||||
- รัน `openclaw doctor` อีกครั้งและอ่านผลลัพธ์อย่างละเอียด
|
||||
- สำหรับ `openclaw update --channel dev` บน source checkouts, ตัวอัปเดตจะ auto-bootstrap `pnpm` เมื่อจำเป็น หากคุณเห็น pnpm/corepack bootstrap error ให้ติดตั้ง `pnpm` แบบแมนนวล (หรือเปิดใช้งาน `corepack` อีกครั้ง) แล้วรันการอัปเดตซ้ำ
|
||||
- รัน `openclaw doctor` อีกครั้งและอ่านข้อความ output อย่างละเอียด
|
||||
- สำหรับ `openclaw update --channel dev` บน source checkout ตัวอัปเดตจะ bootstrap `pnpm` โดยอัตโนมัติเมื่อจำเป็น หากคุณเห็นข้อผิดพลาด bootstrap ของ pnpm/corepack ให้ติดตั้ง `pnpm` แบบ manual (หรือเปิด `corepack` อีกครั้ง) แล้วรันการอัปเดตใหม่
|
||||
- ตรวจสอบ: [การแก้ไขปัญหา](/th/gateway/troubleshooting)
|
||||
- ถามใน Discord: [https://discord.gg/clawd](https://discord.gg/clawd)
|
||||
|
||||
## ที่เกี่ยวข้อง
|
||||
|
||||
- [ภาพรวมการติดตั้ง](/th/install): วิธีการติดตั้งทั้งหมด
|
||||
- [Doctor](/th/gateway/doctor): การตรวจสอบสุขภาพหลังการอัปเดต
|
||||
- [การย้ายข้อมูล](/th/install/migrating): คู่มือการย้ายข้อมูลเวอร์ชันหลัก
|
||||
- [Doctor](/th/gateway/doctor): การตรวจสอบสุขภาพหลังอัปเดต
|
||||
- [การย้าย](/th/install/migrating): คู่มือการย้ายเวอร์ชันหลัก
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -2,26 +2,26 @@
|
||||
read_when:
|
||||
- คุณต้องการโทรออกด้วยเสียงจาก OpenClaw
|
||||
- คุณกำลังกำหนดค่าหรือพัฒนา Plugin การโทรด้วยเสียง
|
||||
- คุณต้องการเสียงแบบเรียลไทม์หรือการถอดเสียงแบบสตรีมบนระบบโทรศัพท์
|
||||
- คุณต้องการเสียงแบบเรียลไทม์หรือการถอดเสียงแบบสตรีมมิงบนระบบโทรศัพท์
|
||||
sidebarTitle: Voice call
|
||||
summary: โทรออกและรับสายโทรเข้าด้วยเสียงผ่าน Twilio, Telnyx หรือ Plivo พร้อมตัวเลือกสำหรับเสียงแบบเรียลไทม์และการถอดเสียงแบบสตรีมมิง
|
||||
summary: โทรออกและรับสายเสียงขาเข้าผ่าน Twilio, Telnyx หรือ Plivo พร้อมตัวเลือกเสียงแบบเรียลไทม์และการถอดเสียงแบบสตรีมมิง
|
||||
title: Plugin การโทรด้วยเสียง
|
||||
x-i18n:
|
||||
generated_at: "2026-05-02T22:22:12Z"
|
||||
generated_at: "2026-05-04T07:06:08Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 18a9a0d7095ec92036b516cc26c69219a0a2fd9bb8e0cb2e7509123bb4f3f65a
|
||||
source_hash: 8ec2c22dcc9073572963744685a432328787bcedb14025e0326c20d9d842f857
|
||||
source_path: plugins/voice-call.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
ปลั๊กอินสำหรับให้ OpenClaw โทรด้วยเสียง รองรับการแจ้งเตือนขาออก,
|
||||
การโทรด้วยเสียงสำหรับ OpenClaw ผ่าน Plugin รองรับการแจ้งเตือนขาออก,
|
||||
การสนทนาหลายรอบ, เสียงเรียลไทม์แบบฟูลดูเพล็กซ์, การถอดเสียงแบบสตรีมมิง,
|
||||
และสายขาเข้าพร้อมนโยบายรายการอนุญาต
|
||||
และสายเรียกเข้าพร้อมนโยบาย allowlist
|
||||
|
||||
**ผู้ให้บริการปัจจุบัน:** `twilio` (Programmable Voice + Media Streams),
|
||||
`telnyx` (Call Control v2), `plivo` (Voice API + XML transfer + GetInput
|
||||
speech), `mock` (การพัฒนา/ไม่มีเครือข่าย)
|
||||
speech), `mock` (dev/no network).
|
||||
|
||||
<Note>
|
||||
Plugin Voice Call ทำงาน **ภายในกระบวนการ Gateway** หากคุณใช้
|
||||
@ -32,14 +32,14 @@ Gateway จากนั้นรีสตาร์ท Gateway เพื่อโ
|
||||
## เริ่มต้นอย่างรวดเร็ว
|
||||
|
||||
<Steps>
|
||||
<Step title="ติดตั้ง Plugin">
|
||||
<Step title="Install the plugin">
|
||||
<Tabs>
|
||||
<Tab title="จาก npm">
|
||||
<Tab title="From npm">
|
||||
```bash
|
||||
openclaw plugins install @openclaw/voice-call
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="จากโฟลเดอร์ในเครื่อง (พัฒนา)">
|
||||
<Tab title="From a local folder (dev)">
|
||||
```bash
|
||||
PLUGIN_SRC=./path/to/local/voice-call-plugin
|
||||
openclaw plugins install "$PLUGIN_SRC"
|
||||
@ -48,36 +48,36 @@ Gateway จากนั้นรีสตาร์ท Gateway เพื่อโ
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
ใช้แพ็กเกจเปล่าเพื่อตามแท็กรุ่นทางการปัจจุบัน ตรึงเป็น
|
||||
ใช้แพ็กเกจเปล่าเพื่อตามแท็กรีลีสอย่างเป็นทางการปัจจุบัน ปักหมุด
|
||||
เวอร์ชันที่แน่นอนเฉพาะเมื่อคุณต้องการการติดตั้งที่ทำซ้ำได้
|
||||
|
||||
รีสตาร์ท Gateway หลังจากนั้นเพื่อให้ Plugin โหลด
|
||||
|
||||
</Step>
|
||||
<Step title="กำหนดค่าผู้ให้บริการและ Webhook">
|
||||
ตั้งค่าคอนฟิกใต้ `plugins.entries.voice-call.config` (ดู
|
||||
[การกำหนดค่า](#configuration) ด้านล่างสำหรับรูปแบบเต็ม) อย่างน้อยต้องมี:
|
||||
`provider`, ข้อมูลรับรองของผู้ให้บริการ, `fromNumber`, และ URL ของ Webhook
|
||||
ที่เข้าถึงได้สาธารณะ
|
||||
<Step title="Configure provider and webhook">
|
||||
ตั้งค่าคอนฟิกภายใต้ `plugins.entries.voice-call.config` (ดู
|
||||
[การกำหนดค่า](#configuration) ด้านล่างสำหรับโครงสร้างทั้งหมด) อย่างน้อยต้องมี:
|
||||
`provider`, ข้อมูลประจำตัวของผู้ให้บริการ, `fromNumber`, และ URL Webhook
|
||||
ที่เข้าถึงได้แบบสาธารณะ
|
||||
</Step>
|
||||
<Step title="ตรวจสอบการตั้งค่า">
|
||||
<Step title="Verify setup">
|
||||
```bash
|
||||
openclaw voicecall setup
|
||||
```
|
||||
|
||||
เอาต์พุตเริ่มต้นอ่านได้ในบันทึกแชตและเทอร์มินัล โดยตรวจสอบ
|
||||
การเปิดใช้ Plugin, ข้อมูลรับรองของผู้ให้บริการ, การเปิดเผย Webhook,
|
||||
และว่ามีโหมดเสียงเพียงโหมดเดียว (`streaming` หรือ `realtime`) ที่เปิดอยู่ ใช้
|
||||
การเปิดใช้ Plugin, ข้อมูลประจำตัวของผู้ให้บริการ, การเปิดเผย Webhook,
|
||||
และมีโหมดเสียงเพียงโหมดเดียว (`streaming` หรือ `realtime`) ที่ใช้งานอยู่ ใช้
|
||||
`--json` สำหรับสคริปต์
|
||||
|
||||
</Step>
|
||||
<Step title="ทดสอบแบบ Smoke">
|
||||
<Step title="Smoke test">
|
||||
```bash
|
||||
openclaw voicecall smoke
|
||||
openclaw voicecall smoke --to "+15555550123"
|
||||
```
|
||||
|
||||
ทั้งสองรายการเป็น dry run โดยค่าเริ่มต้น เพิ่ม `--yes` เพื่อโทรแจ้งเตือน
|
||||
ทั้งสองคำสั่งเป็น dry run โดยค่าเริ่มต้น เพิ่ม `--yes` เพื่อโทรแจ้งเตือน
|
||||
ขาออกสั้น ๆ จริง:
|
||||
|
||||
```bash
|
||||
@ -88,21 +88,21 @@ Gateway จากนั้นรีสตาร์ท Gateway เพื่อโ
|
||||
</Steps>
|
||||
|
||||
<Warning>
|
||||
สำหรับ Twilio, Telnyx และ Plivo การตั้งค่าต้องแก้ค่าเป็น **URL ของ Webhook สาธารณะ**
|
||||
หาก `publicUrl`, URL ของ tunnel, URL ของ Tailscale หรือ serve fallback
|
||||
แก้ค่าเป็น loopback หรือพื้นที่เครือข่ายส่วนตัว การตั้งค่าจะล้มเหลวแทนที่จะ
|
||||
เริ่มผู้ให้บริการที่รับ Webhook จากผู้ให้บริการเครือข่ายไม่ได้
|
||||
สำหรับ Twilio, Telnyx และ Plivo การตั้งค่าต้อง resolve เป็น **URL Webhook สาธารณะ**
|
||||
หาก `publicUrl`, URL tunnel, URL Tailscale หรือ serve fallback
|
||||
resolve เป็น loopback หรือพื้นที่เครือข่ายส่วนตัว การตั้งค่าจะล้มเหลวแทนที่จะ
|
||||
เริ่มผู้ให้บริการที่ไม่สามารถรับ carrier webhooks ได้
|
||||
</Warning>
|
||||
|
||||
## การกำหนดค่า
|
||||
|
||||
หาก `enabled: true` แต่ผู้ให้บริการที่เลือกขาดข้อมูลรับรอง,
|
||||
การเริ่มต้น Gateway จะบันทึกคำเตือนว่าการตั้งค่ายังไม่สมบูรณ์พร้อมคีย์ที่ขาด
|
||||
และข้ามการเริ่ม runtime คำสั่ง, การเรียก RPC และเครื่องมือ agent ยังคง
|
||||
คืนค่าการกำหนดค่าผู้ให้บริการที่ขาดอย่างตรงตัวเมื่อใช้งาน
|
||||
หาก `enabled: true` แต่ผู้ให้บริการที่เลือกไม่มีข้อมูลประจำตัว
|
||||
การเริ่มต้น Gateway จะบันทึกคำเตือนว่าการตั้งค่าไม่สมบูรณ์พร้อมคีย์ที่ขาดหายไป และ
|
||||
ข้ามการเริ่ม runtime คำสั่ง, การเรียก RPC และเครื่องมือ agent ยังคง
|
||||
ส่งคืนคอนฟิกผู้ให้บริการที่ขาดหายไปอย่างแม่นยำเมื่อใช้งาน
|
||||
|
||||
<Note>
|
||||
ข้อมูลรับรอง voice-call รองรับ SecretRefs `plugins.entries.voice-call.config.twilio.authToken`, `plugins.entries.voice-call.config.realtime.providers.*.apiKey`, `plugins.entries.voice-call.config.streaming.providers.*.apiKey`, และ `plugins.entries.voice-call.config.tts.providers.*.apiKey` แก้ค่าผ่านพื้นผิว SecretRef มาตรฐาน; ดู [พื้นผิวข้อมูลรับรอง SecretRef](/th/reference/secretref-credential-surface)
|
||||
ข้อมูลประจำตัว voice-call รองรับ SecretRefs `plugins.entries.voice-call.config.twilio.authToken`, `plugins.entries.voice-call.config.realtime.providers.*.apiKey`, `plugins.entries.voice-call.config.streaming.providers.*.apiKey` และ `plugins.entries.voice-call.config.tts.providers.*.apiKey` จะ resolve ผ่านพื้นผิว SecretRef มาตรฐาน; ดู [พื้นผิวข้อมูลประจำตัว SecretRef](/th/reference/secretref-credential-surface)
|
||||
</Note>
|
||||
|
||||
```json5
|
||||
@ -175,31 +175,31 @@ Gateway จากนั้นรีสตาร์ท Gateway เพื่อโ
|
||||
```
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="หมายเหตุด้านการเปิดเผยผู้ให้บริการและความปลอดภัย">
|
||||
- Twilio, Telnyx และ Plivo ทั้งหมดต้องใช้ URL ของ Webhook ที่ **เข้าถึงได้สาธารณะ**
|
||||
- `mock` เป็นผู้ให้บริการสำหรับการพัฒนาในเครื่อง (ไม่มีการเรียกเครือข่าย)
|
||||
<Accordion title="Provider exposure and security notes">
|
||||
- Twilio, Telnyx และ Plivo ทั้งหมดต้องใช้ URL Webhook ที่ **เข้าถึงได้แบบสาธารณะ**
|
||||
- `mock` คือผู้ให้บริการ dev ในเครื่อง (ไม่มีการเรียกเครือข่าย)
|
||||
- Telnyx ต้องใช้ `telnyx.publicKey` (หรือ `TELNYX_PUBLIC_KEY`) เว้นแต่ `skipSignatureVerification` เป็น true
|
||||
- `skipSignatureVerification` ใช้สำหรับการทดสอบในเครื่องเท่านั้น
|
||||
- บนระดับฟรีของ ngrok ให้ตั้งค่า `publicUrl` เป็น URL ของ ngrok ที่แน่นอน; การตรวจสอบลายเซ็นจะบังคับใช้เสมอ
|
||||
- `tunnel.allowNgrokFreeTierLoopbackBypass: true` อนุญาต Webhook ของ Twilio ที่มีลายเซ็นไม่ถูกต้อง **เฉพาะ** เมื่อ `tunnel.provider="ngrok"` และ `serve.bind` เป็น loopback (agent ในเครื่องของ ngrok) สำหรับการพัฒนาในเครื่องเท่านั้น
|
||||
- URL ระดับฟรีของ Ngrok อาจเปลี่ยนหรือเพิ่มพฤติกรรม interstitial; หาก `publicUrl` เบี่ยงไป ลายเซ็นของ Twilio จะล้มเหลว สำหรับโปรดักชัน: ควรใช้โดเมนที่เสถียรหรือ Tailscale funnel
|
||||
- ใน ngrok ระดับฟรี ให้ตั้ง `publicUrl` เป็น URL ngrok ที่แน่นอน; การตรวจสอบลายเซ็นจะถูกบังคับใช้เสมอ
|
||||
- `tunnel.allowNgrokFreeTierLoopbackBypass: true` อนุญาต Twilio webhooks ที่มีลายเซ็นไม่ถูกต้อง **เฉพาะ** เมื่อ `tunnel.provider="ngrok"` และ `serve.bind` เป็น loopback (ngrok local agent) เท่านั้น สำหรับ dev ในเครื่องเท่านั้น
|
||||
- URL ระดับฟรีของ Ngrok อาจเปลี่ยนหรือเพิ่มพฤติกรรม interstitial ได้; หาก `publicUrl` เคลื่อนออกไป ลายเซ็น Twilio จะล้มเหลว Production: แนะนำให้ใช้โดเมนที่เสถียรหรือ Tailscale funnel
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="เพดานการเชื่อมต่อสตรีมมิง">
|
||||
- `streaming.preStartTimeoutMs` ปิดซ็อกเก็ตที่ไม่เคยส่งเฟรม `start` ที่ถูกต้อง
|
||||
- `streaming.maxPendingConnections` จำกัดจำนวนซ็อกเก็ต pre-start ที่ยังไม่ตรวจสอบสิทธิ์ทั้งหมด
|
||||
- `streaming.maxPendingConnectionsPerIp` จำกัดซ็อกเก็ต pre-start ที่ยังไม่ตรวจสอบสิทธิ์ต่อ IP ต้นทาง
|
||||
- `streaming.maxConnections` จำกัดจำนวนซ็อกเก็ต media stream ที่เปิดทั้งหมด (pending + active)
|
||||
<Accordion title="Streaming connection caps">
|
||||
- `streaming.preStartTimeoutMs` ปิด socket ที่ไม่เคยส่ง frame `start` ที่ถูกต้อง
|
||||
- `streaming.maxPendingConnections` จำกัดจำนวน socket pre-start ที่ยังไม่ได้ยืนยันตัวตนทั้งหมด
|
||||
- `streaming.maxPendingConnectionsPerIp` จำกัดจำนวน socket pre-start ที่ยังไม่ได้ยืนยันตัวตนต่อ IP ต้นทาง
|
||||
- `streaming.maxConnections` จำกัดจำนวน socket media stream ที่เปิดอยู่ทั้งหมด (pending + active)
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="การย้ายคอนฟิกแบบเดิม">
|
||||
<Accordion title="Legacy config migrations">
|
||||
คอนฟิกเก่าที่ใช้ `provider: "log"`, `twilio.from` หรือคีย์ OpenAI
|
||||
`streaming.*` แบบเดิม จะถูกเขียนใหม่โดย `openclaw doctor --fix`
|
||||
runtime fallback ยังคงยอมรับคีย์ voice-call เก่าในตอนนี้ แต่
|
||||
เส้นทางการเขียนใหม่คือ `openclaw doctor --fix` และ compat shim
|
||||
เป็นเพียงชั่วคราว
|
||||
`streaming.*` แบบ legacy จะถูกเขียนใหม่โดย `openclaw doctor --fix`
|
||||
Runtime fallback ยังยอมรับคีย์ voice-call เก่าได้ในตอนนี้ แต่
|
||||
เส้นทางการเขียนใหม่คือ `openclaw doctor --fix` และ compat shim เป็น
|
||||
ชั่วคราว
|
||||
|
||||
คีย์สตรีมมิงที่ย้ายโดยอัตโนมัติ:
|
||||
คีย์ streaming ที่ย้ายอัตโนมัติ:
|
||||
|
||||
- `streaming.sttProvider` → `streaming.provider`
|
||||
- `streaming.openaiApiKey` → `streaming.providers.openai.apiKey`
|
||||
@ -212,32 +212,33 @@ Gateway จากนั้นรีสตาร์ท Gateway เพื่อโ
|
||||
|
||||
## ขอบเขตเซสชัน
|
||||
|
||||
โดยค่าเริ่มต้น Voice Call ใช้ `sessionScope: "per-phone"` เพื่อให้การโทรซ้ำจาก
|
||||
ผู้โทรคนเดิมคงหน่วยความจำการสนทนาไว้ ตั้งค่า `sessionScope: "per-call"` เมื่อ
|
||||
การโทรของผู้ให้บริการเครือข่ายแต่ละครั้งควรเริ่มด้วยบริบทใหม่ เช่น แผนกต้อนรับ,
|
||||
การจอง, IVR หรือโฟลว์บริดจ์ Google Meet ที่หมายเลขโทรศัพท์เดียวกันอาจ
|
||||
แทนการประชุมคนละครั้ง
|
||||
โดยค่าเริ่มต้น Voice Call ใช้ `sessionScope: "per-phone"` เพื่อให้สายซ้ำจาก
|
||||
ผู้โทรรายเดิมคงหน่วยความจำการสนทนาไว้ ตั้ง `sessionScope: "per-call"` เมื่อ
|
||||
แต่ละ carrier call ควรเริ่มด้วยบริบทใหม่ เช่น งานต้อนรับ,
|
||||
การจอง, IVR หรือ flow สะพาน Google Meet ที่หมายเลขโทรศัพท์เดียวกันอาจ
|
||||
แทนการประชุมคนละรายการ
|
||||
|
||||
## การสนทนาด้วยเสียงเรียลไทม์
|
||||
## การสนทนาด้วยเสียงแบบเรียลไทม์
|
||||
|
||||
`realtime` เลือกผู้ให้บริการเสียงเรียลไทม์แบบฟูลดูเพล็กซ์สำหรับเสียงสดของสายโทร
|
||||
แยกจาก `streaming` ซึ่งส่งต่อเสียงไปยังผู้ให้บริการถอดเสียงเรียลไทม์เท่านั้น
|
||||
`realtime` เลือกผู้ให้บริการเสียงเรียลไทม์แบบฟูลดูเพล็กซ์สำหรับเสียงการโทรสด
|
||||
โดยแยกจาก `streaming` ซึ่งทำหน้าที่ส่งต่อเสียงไปยัง
|
||||
ผู้ให้บริการถอดเสียงแบบเรียลไทม์เท่านั้น
|
||||
|
||||
<Warning>
|
||||
ไม่สามารถรวม `realtime.enabled` กับ `streaming.enabled` ได้ เลือก
|
||||
โหมดเสียงหนึ่งโหมดต่อสาย
|
||||
`realtime.enabled` ไม่สามารถใช้ร่วมกับ `streaming.enabled` ได้ เลือก
|
||||
โหมดเสียงหนึ่งโหมดต่อการโทร
|
||||
</Warning>
|
||||
|
||||
พฤติกรรม runtime ปัจจุบัน:
|
||||
|
||||
- รองรับ `realtime.enabled` สำหรับ Twilio Media Streams
|
||||
- `realtime.provider` เป็นตัวเลือก หากไม่ตั้งค่า Voice Call จะใช้ผู้ให้บริการเสียงเรียลไทม์ที่ลงทะเบียนไว้รายแรก
|
||||
- ผู้ให้บริการเสียงเรียลไทม์ที่รวมมา: Google Gemini Live (`google`) และ OpenAI (`openai`) ซึ่งลงทะเบียนโดย Plugin ของผู้ให้บริการเหล่านั้น
|
||||
- คอนฟิกดิบที่ผู้ให้บริการเป็นเจ้าของอยู่ใต้ `realtime.providers.<providerId>`
|
||||
- Voice Call เปิดเผยเครื่องมือเรียลไทม์ `openclaw_agent_consult` ที่ใช้ร่วมกันโดยค่าเริ่มต้น โมเดลเรียลไทม์สามารถเรียกใช้เมื่อผู้โทรขอการให้เหตุผลที่ลึกขึ้น, ข้อมูลปัจจุบัน หรือเครื่องมือ OpenClaw ปกติ
|
||||
- `realtime.fastContext.enabled` ปิดโดยค่าเริ่มต้น เมื่อเปิดใช้ Voice Call จะค้นหาบริบทหน่วยความจำ/เซสชันที่ทำดัชนีไว้สำหรับคำถาม consult ก่อน และคืน snippet เหล่านั้นให้โมเดลเรียลไทม์ภายใน `realtime.fastContext.timeoutMs` ก่อน fallback ไปยัง consult agent เต็มรูปแบบเฉพาะเมื่อ `realtime.fastContext.fallbackToConsult` เป็น true
|
||||
- `realtime.provider` เป็นตัวเลือก หากไม่ได้ตั้งค่า Voice Call จะใช้ผู้ให้บริการเสียงเรียลไทม์รายแรกที่ลงทะเบียนไว้
|
||||
- ผู้ให้บริการเสียงเรียลไทม์ที่ bundled: Google Gemini Live (`google`) และ OpenAI (`openai`) ซึ่งลงทะเบียนโดย Plugin ผู้ให้บริการของตน
|
||||
- คอนฟิกดิบที่ผู้ให้บริการเป็นเจ้าของอยู่ภายใต้ `realtime.providers.<providerId>`
|
||||
- Voice Call เปิดเผยเครื่องมือเรียลไทม์ร่วม `openclaw_agent_consult` โดยค่าเริ่มต้น โมเดลเรียลไทม์สามารถเรียกใช้ได้เมื่อผู้โทรขอการให้เหตุผลเชิงลึก ข้อมูลปัจจุบัน หรือเครื่องมือ OpenClaw ปกติ
|
||||
- `realtime.fastContext.enabled` ปิดโดยค่าเริ่มต้น เมื่อเปิดใช้งาน Voice Call จะค้นหาหน่วยความจำ/บริบทเซสชันที่ทำดัชนีไว้สำหรับคำถาม consult ก่อน และส่งคืน snippet เหล่านั้นให้โมเดลเรียลไทม์ภายใน `realtime.fastContext.timeoutMs` ก่อน fallback ไปยัง consult agent เต็มรูปแบบเฉพาะเมื่อ `realtime.fastContext.fallbackToConsult` เป็น true
|
||||
- หาก `realtime.provider` ชี้ไปยังผู้ให้บริการที่ไม่ได้ลงทะเบียน หรือไม่มีผู้ให้บริการเสียงเรียลไทม์ที่ลงทะเบียนเลย Voice Call จะบันทึกคำเตือนและข้ามสื่อเรียลไทม์แทนที่จะทำให้ Plugin ทั้งหมดล้มเหลว
|
||||
- คีย์เซสชัน consult ใช้เซสชันสายโทรที่เก็บไว้เมื่อมี จากนั้น fallback ไปยัง `sessionScope` ที่กำหนดค่าไว้ (`per-phone` โดยค่าเริ่มต้น หรือ `per-call` สำหรับสายที่แยกบริบท)
|
||||
- คีย์เซสชัน consult ใช้เซสชันการโทรที่เก็บไว้เมื่อมี จากนั้น fallback ไปยัง `sessionScope` ที่กำหนดค่าไว้ (`per-phone` โดยค่าเริ่มต้น หรือ `per-call` สำหรับการโทรที่แยกบริบท)
|
||||
|
||||
### นโยบายเครื่องมือ
|
||||
|
||||
@ -245,17 +246,20 @@ Gateway จากนั้นรีสตาร์ท Gateway เพื่อโ
|
||||
|
||||
| นโยบาย | พฤติกรรม |
|
||||
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `safe-read-only` | เปิดเผยเครื่องมือ consult และจำกัด agent ปกติให้ใช้ `read`, `web_search`, `web_fetch`, `x_search`, `memory_search` และ `memory_get` |
|
||||
| `owner` | เปิดเผยเครื่องมือ consult และให้ agent ปกติใช้นโยบายเครื่องมือ agent ตามปกติ |
|
||||
| `safe-read-only` | เปิดเผยเครื่องมือ consult และจำกัด agent ปกติไว้ที่ `read`, `web_search`, `web_fetch`, `x_search`, `memory_search` และ `memory_get` |
|
||||
| `owner` | เปิดเผยเครื่องมือ consult และให้ agent ปกติใช้นโยบายเครื่องมือ agent ปกติ |
|
||||
| `none` | ไม่เปิดเผยเครื่องมือ consult `realtime.tools` แบบกำหนดเองยังคงถูกส่งผ่านไปยังผู้ให้บริการเรียลไทม์ |
|
||||
|
||||
### ตัวอย่างผู้ให้บริการเรียลไทม์
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Google Gemini Live">
|
||||
ค่าเริ่มต้น: คีย์ API จาก `realtime.providers.google.apiKey`,
|
||||
ค่าเริ่มต้น: API key จาก `realtime.providers.google.apiKey`,
|
||||
`GEMINI_API_KEY` หรือ `GOOGLE_GENERATIVE_AI_API_KEY`; โมเดล
|
||||
`gemini-2.5-flash-native-audio-preview-12-2025`; เสียง `Kore`
|
||||
`sessionResumption` และ `contextWindowCompression` เปิดโดยค่าเริ่มต้นสำหรับการโทรที่ยาวขึ้นและ
|
||||
reconnect ได้ ใช้ `silenceDurationMs`, `startSensitivity` และ
|
||||
`endSensitivity` เพื่อปรับการสลับตาที่เร็วขึ้นบนเสียงโทรศัพท์
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -276,6 +280,8 @@ Gateway จากนั้นรีสตาร์ท Gateway เพื่อโ
|
||||
apiKey: "${GEMINI_API_KEY}",
|
||||
model: "gemini-2.5-flash-native-audio-preview-12-2025",
|
||||
voice: "Kore",
|
||||
silenceDurationMs: 500,
|
||||
startSensitivity: "high",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -311,20 +317,20 @@ Gateway จากนั้นรีสตาร์ท Gateway เพื่อโ
|
||||
</Tabs>
|
||||
|
||||
ดู [ผู้ให้บริการ Google](/th/providers/google) และ
|
||||
[ผู้ให้บริการ OpenAI](/th/providers/openai) สำหรับตัวเลือกเสียงเรียลไทม์
|
||||
[ผู้ให้บริการ OpenAI](/th/providers/openai) สำหรับตัวเลือกเสียงแบบเรียลไทม์
|
||||
เฉพาะผู้ให้บริการ
|
||||
|
||||
## การถอดเสียงแบบสตรีมมิง
|
||||
|
||||
`streaming` เลือกผู้ให้บริการถอดเสียงเรียลไทม์สำหรับเสียงสดของสายโทร
|
||||
`streaming` เลือกผู้ให้บริการถอดเสียงแบบเรียลไทม์สำหรับเสียงสายสด
|
||||
|
||||
พฤติกรรม runtime ปัจจุบัน:
|
||||
พฤติกรรมรันไทม์ปัจจุบัน:
|
||||
|
||||
- `streaming.provider` เป็นตัวเลือกเสริม หากไม่ได้ตั้งค่า Voice Call จะใช้ผู้ให้บริการถอดเสียงแบบเรียลไทม์รายแรกที่ลงทะเบียนไว้
|
||||
- ผู้ให้บริการถอดเสียงแบบเรียลไทม์ที่มาพร้อมแพ็กเกจ: Deepgram (`deepgram`), ElevenLabs (`elevenlabs`), Mistral (`mistral`), OpenAI (`openai`) และ xAI (`xai`) ซึ่งลงทะเบียนโดย Plugin ของผู้ให้บริการแต่ละราย
|
||||
- คอนฟิกดิบที่ผู้ให้บริการเป็นเจ้าของอยู่ใต้ `streaming.providers.<providerId>`
|
||||
- ผู้ให้บริการถอดเสียงแบบเรียลไทม์ที่รวมมาให้: Deepgram (`deepgram`), ElevenLabs (`elevenlabs`), Mistral (`mistral`), OpenAI (`openai`) และ xAI (`xai`) ซึ่งลงทะเบียนโดย Plugin ผู้ให้บริการของตน
|
||||
- การกำหนดค่าดิบที่ผู้ให้บริการเป็นเจ้าของอยู่ใต้ `streaming.providers.<providerId>`
|
||||
- หลังจาก Twilio ส่งข้อความ `start` ของสตรีมที่ยอมรับแล้ว Voice Call จะลงทะเบียนสตรีมทันที จัดคิวสื่อขาเข้าผ่านผู้ให้บริการถอดเสียงระหว่างที่ผู้ให้บริการกำลังเชื่อมต่อ และเริ่มคำทักทายแรกหลังจากการถอดเสียงแบบเรียลไทม์พร้อมแล้วเท่านั้น
|
||||
- หาก `streaming.provider` ชี้ไปยังผู้ให้บริการที่ไม่ได้ลงทะเบียน หรือไม่มีผู้ให้บริการที่ลงทะเบียนไว้ Voice Call จะบันทึกคำเตือนและข้ามการสตรีมสื่อแทนที่จะทำให้ Plugin ทั้งหมดล้มเหลว
|
||||
- หาก `streaming.provider` ชี้ไปยังผู้ให้บริการที่ไม่ได้ลงทะเบียน หรือไม่มีผู้ให้บริการใดลงทะเบียนไว้ Voice Call จะบันทึกคำเตือนและข้ามการสตรีมสื่อแทนที่จะทำให้ Plugin ทั้งหมดล้มเหลว
|
||||
|
||||
### ตัวอย่างผู้ให้บริการสตรีมมิง
|
||||
|
||||
@ -363,7 +369,7 @@ Gateway จากนั้นรีสตาร์ท Gateway เพื่อโ
|
||||
</Tab>
|
||||
<Tab title="xAI">
|
||||
ค่าเริ่มต้น: คีย์ API `streaming.providers.xai.apiKey` หรือ `XAI_API_KEY`;
|
||||
ปลายทาง `wss://api.x.ai/v1/stt`; การเข้ารหัส `mulaw`; อัตราสุ่มตัวอย่าง `8000`;
|
||||
เอนด์พอยต์ `wss://api.x.ai/v1/stt`; การเข้ารหัส `mulaw`; อัตราตัวอย่าง `8000`;
|
||||
`endpointingMs: 800`; `interimResults: true`.
|
||||
|
||||
```json5
|
||||
@ -394,11 +400,11 @@ Gateway จากนั้นรีสตาร์ท Gateway เพื่อโ
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## TTS สำหรับการโทร
|
||||
## TTS สำหรับสายโทรศัพท์
|
||||
|
||||
Voice Call ใช้คอนฟิกหลัก `messages.tts` สำหรับการสตรีม
|
||||
เสียงพูดในการโทร คุณสามารถเขียนทับได้ใต้คอนฟิก Plugin ด้วย
|
||||
**รูปแบบเดียวกัน** — โดยจะ deep-merge กับ `messages.tts`
|
||||
Voice Call ใช้การกำหนดค่า `messages.tts` หลักสำหรับเสียงพูดแบบสตรีมมิง
|
||||
ในสายโทรศัพท์ คุณสามารถแทนที่ได้ใต้การกำหนดค่า Plugin ด้วย
|
||||
**รูปแบบเดียวกัน** — ระบบจะผสานเชิงลึกกับ `messages.tts`
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -415,22 +421,22 @@ Voice Call ใช้คอนฟิกหลัก `messages.tts` สำหร
|
||||
```
|
||||
|
||||
<Warning>
|
||||
**Microsoft speech จะถูกละเว้นสำหรับการโทรด้วยเสียง** เสียงโทรศัพท์ต้องใช้ PCM;
|
||||
การขนส่งของ Microsoft ในปัจจุบันไม่เปิดเผยเอาต์พุต PCM สำหรับโทรศัพท์
|
||||
**Microsoft speech จะถูกละเว้นสำหรับสายเสียง** เสียงโทรศัพท์ต้องใช้ PCM;
|
||||
ทรานสปอร์ต Microsoft ปัจจุบันไม่ได้เปิดเผยเอาต์พุต PCM สำหรับโทรศัพท์
|
||||
</Warning>
|
||||
|
||||
หมายเหตุเกี่ยวกับลักษณะการทำงาน:
|
||||
หมายเหตุพฤติกรรม:
|
||||
|
||||
- คีย์ `tts.<provider>` แบบเดิมภายในคอนฟิก Plugin (`openai`, `elevenlabs`, `microsoft`, `edge`) จะถูกซ่อมแซมโดย `openclaw doctor --fix`; คอนฟิกที่คอมมิตควรใช้ `tts.providers.<provider>`
|
||||
- ใช้ TTS หลักเมื่อเปิดใช้การสตรีมสื่อของ Twilio; มิฉะนั้นการโทรจะถอยกลับไปใช้เสียงดั้งเดิมของผู้ให้บริการ
|
||||
- หากสตรีมสื่อของ Twilio กำลังทำงานอยู่ Voice Call จะไม่ถอยกลับไปใช้ TwiML `<Say>` หาก TTS สำหรับโทรศัพท์ไม่พร้อมใช้งานในสถานะนั้น คำขอเล่นเสียงจะล้มเหลวแทนที่จะผสมเส้นทางการเล่นเสียงสองแบบ
|
||||
- เมื่อ TTS สำหรับโทรศัพท์ถอยกลับไปยังผู้ให้บริการรอง Voice Call จะบันทึกคำเตือนพร้อมเชนผู้ให้บริการ (`from`, `to`, `attempts`) สำหรับการดีบัก
|
||||
- เมื่อ barge-in ของ Twilio หรือการรื้อสตรีมล้างคิว TTS ที่รออยู่ คำขอเล่นเสียงที่อยู่ในคิวจะสิ้นสุดสถานะแทนที่จะทำให้ผู้โทรค้างระหว่างรอการเล่นเสียงเสร็จสิ้น
|
||||
- คีย์ `tts.<provider>` แบบเดิมภายในการกำหนดค่า Plugin (`openai`, `elevenlabs`, `microsoft`, `edge`) จะถูกซ่อมแซมโดย `openclaw doctor --fix`; การกำหนดค่าที่คอมมิตควรใช้ `tts.providers.<provider>`
|
||||
- ใช้ TTS หลักเมื่อเปิดใช้การสตรีมสื่อ Twilio; มิฉะนั้นสายโทรศัพท์จะย้อนกลับไปใช้เสียงเนทีฟของผู้ให้บริการ
|
||||
- หากสตรีมสื่อ Twilio ทำงานอยู่แล้ว Voice Call จะไม่ย้อนกลับไปใช้ TwiML `<Say>` หาก TTS สำหรับโทรศัพท์ไม่พร้อมใช้งานในสถานะนั้น คำขอเล่นเสียงจะล้มเหลวแทนที่จะผสมเส้นทางการเล่นเสียงสองแบบ
|
||||
- เมื่อ TTS สำหรับโทรศัพท์ย้อนกลับไปใช้ผู้ให้บริการสำรอง Voice Call จะบันทึกคำเตือนพร้อมเชนผู้ให้บริการ (`from`, `to`, `attempts`) เพื่อการดีบัก
|
||||
- เมื่อ Twilio barge-in หรือการรื้อถอนสตรีมล้างคิว TTS ที่รอดำเนินการ คำขอเล่นเสียงที่เข้าคิวไว้จะจบสถานะแทนที่จะค้างผู้โทรที่รอให้การเล่นเสียงเสร็จ
|
||||
|
||||
### ตัวอย่าง TTS
|
||||
|
||||
<Tabs>
|
||||
<Tab title="เฉพาะ TTS หลัก">
|
||||
<Tab title="Core TTS only">
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
@ -444,7 +450,7 @@ Voice Call ใช้คอนฟิกหลัก `messages.tts` สำหร
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="เขียนทับเป็น ElevenLabs (เฉพาะการโทร)">
|
||||
<Tab title="Override to ElevenLabs (calls only)">
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
@ -468,7 +474,7 @@ Voice Call ใช้คอนฟิกหลัก `messages.tts` สำหร
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="เขียนทับโมเดล OpenAI (deep-merge)">
|
||||
<Tab title="OpenAI model override (deep-merge)">
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
@ -492,9 +498,9 @@ Voice Call ใช้คอนฟิกหลัก `messages.tts` สำหร
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## สายโทรเข้า
|
||||
## สายขาเข้า
|
||||
|
||||
นโยบายขาเข้ามีค่าเริ่มต้นเป็น `disabled` หากต้องการเปิดใช้สายโทรเข้า ให้ตั้งค่า:
|
||||
นโยบายขาเข้ามีค่าเริ่มต้นเป็น `disabled` หากต้องการเปิดใช้สายขาเข้า ให้ตั้งค่า:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -505,33 +511,33 @@ Voice Call ใช้คอนฟิกหลัก `messages.tts` สำหร
|
||||
```
|
||||
|
||||
<Warning>
|
||||
`inboundPolicy: "allowlist"` เป็นหน้าจอกรอง caller-ID ที่มีความเชื่อมั่นต่ำ
|
||||
Plugin จะทำให้ค่า `From` ที่ผู้ให้บริการส่งมาเป็นรูปแบบปกติและเปรียบเทียบกับ
|
||||
`allowFrom` การตรวจสอบ Webhook ยืนยันความถูกต้องของการส่งจากผู้ให้บริการและ
|
||||
`inboundPolicy: "allowlist"` เป็นการคัดกรองหมายเลขผู้โทรที่มีความน่าเชื่อต่ำ
|
||||
Plugin จะทำให้ค่า `From` ที่ผู้ให้บริการส่งมาอยู่ในรูปแบบปกติและเปรียบเทียบกับ
|
||||
`allowFrom` การตรวจสอบ Webhook ยืนยันการส่งจากผู้ให้บริการและ
|
||||
ความสมบูรณ์ของเพย์โหลด แต่ไม่ได้ **พิสูจน์** ความเป็นเจ้าของหมายเลขผู้โทร
|
||||
PSTN/VoIP ให้ถือว่า `allowFrom` เป็นการกรอง caller-ID ไม่ใช่อัตลักษณ์ผู้โทร
|
||||
PSTN/VoIP ให้ถือว่า `allowFrom` เป็นการกรองหมายเลขผู้โทร ไม่ใช่ตัวตนผู้โทร
|
||||
ที่แข็งแรง
|
||||
</Warning>
|
||||
|
||||
การตอบกลับอัตโนมัติใช้ระบบเอเจนต์ ปรับแต่งด้วย `responseModel`,
|
||||
`responseSystemPrompt` และ `responseTimeoutMs`
|
||||
|
||||
### การกำหนดเส้นทางแยกตามหมายเลข
|
||||
### การกำหนดเส้นทางรายหมายเลข
|
||||
|
||||
ใช้ `numbers` เมื่อ Plugin Voice Call หนึ่งรายการรับสายสำหรับหมายเลขโทรศัพท์หลาย
|
||||
หมายเลข และแต่ละหมายเลขควรทำงานเหมือนสายคนละสาย ตัวอย่างเช่น หมายเลขหนึ่ง
|
||||
อาจใช้ผู้ช่วยส่วนตัวโทนเป็นกันเอง ขณะที่อีกหมายเลขหนึ่งใช้บุคลิกทางธุรกิจ
|
||||
ใช้ `numbers` เมื่อ Plugin Voice Call หนึ่งรายการรับสายสำหรับหมายเลขโทรศัพท์หลายหมายเลข
|
||||
และแต่ละหมายเลขควรทำงานเหมือนคนละสาย ตัวอย่างเช่น หมายเลขหนึ่ง
|
||||
สามารถใช้ผู้ช่วยส่วนตัวแบบเป็นกันเอง ขณะที่อีกหมายเลขใช้บุคลิกธุรกิจ
|
||||
เอเจนต์ตอบกลับคนละตัว และเสียง TTS คนละเสียง
|
||||
|
||||
เส้นทางถูกเลือกจากหมายเลข `To` ที่ผู้ให้บริการส่งมา คีย์ต้องเป็นหมายเลข
|
||||
E.164 เมื่อมีสายเข้า Voice Call จะระบุเส้นทางที่ตรงกันหนึ่งครั้ง
|
||||
เก็บเส้นทางที่ตรงกันไว้ในระเบียนการโทร และนำคอนฟิกที่มีผลนั้นกลับมาใช้ซ้ำ
|
||||
สำหรับคำทักทาย เส้นทางตอบกลับอัตโนมัติแบบคลาสสิก เส้นทางปรึกษาแบบเรียลไทม์
|
||||
และการเล่นเสียง TTS หากไม่มีเส้นทางใดตรงกัน จะใช้คอนฟิก Voice Call ส่วนกลาง
|
||||
สายโทรออกไม่ใช้ `numbers`; ให้ส่งเป้าหมายขาออก ข้อความ และ
|
||||
เซสชันอย่างชัดเจนเมื่อเริ่มการโทร
|
||||
เส้นทางจะถูกเลือกจากหมายเลข `To` ที่ผู้ให้บริการส่งมา คีย์ต้องเป็น
|
||||
หมายเลข E.164 เมื่อสายเข้ามา Voice Call จะระบุเส้นทางที่ตรงกันหนึ่งครั้ง
|
||||
จัดเก็บเส้นทางที่ตรงกันไว้ในบันทึกสาย และนำการกำหนดค่าที่มีผลนั้นกลับมาใช้
|
||||
สำหรับคำทักทาย เส้นทางตอบกลับอัตโนมัติแบบคลาสสิก เส้นทางปรึกษาแบบเรียลไทม์ และการเล่นเสียง
|
||||
TTS หากไม่มีเส้นทางใดตรงกัน จะใช้การกำหนดค่า Voice Call แบบส่วนกลาง
|
||||
สายขาออกจะไม่ใช้ `numbers`; ให้ส่งเป้าหมายขาออก ข้อความ และ
|
||||
เซสชันอย่างชัดเจนเมื่อเริ่มสาย
|
||||
|
||||
การเขียนทับเส้นทางรองรับรายการต่อไปนี้ในปัจจุบัน:
|
||||
การแทนที่เส้นทางปัจจุบันรองรับ:
|
||||
|
||||
- `inboundGreeting`
|
||||
- `tts`
|
||||
@ -540,8 +546,8 @@ E.164 เมื่อมีสายเข้า Voice Call จะระบุ
|
||||
- `responseSystemPrompt`
|
||||
- `responseTimeoutMs`
|
||||
|
||||
ค่าเส้นทาง `tts` จะ deep-merge ทับคอนฟิก `tts` ส่วนกลางของ Voice Call ดังนั้น
|
||||
โดยปกติคุณสามารถเขียนทับเฉพาะเสียงของผู้ให้บริการได้:
|
||||
ค่าเส้นทาง `tts` จะผสานเชิงลึกทับการกำหนดค่า `tts` ของ Voice Call ส่วนกลาง ดังนั้น
|
||||
โดยปกติคุณสามารถแทนที่เฉพาะเสียงของผู้ให้บริการได้:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -567,53 +573,53 @@ E.164 เมื่อมีสายเข้า Voice Call จะระบุ
|
||||
}
|
||||
```
|
||||
|
||||
### สัญญาเอาต์พุตคำพูด
|
||||
### สัญญาเอาต์พุตเสียงพูด
|
||||
|
||||
สำหรับการตอบกลับอัตโนมัติ Voice Call จะต่อท้ายสัญญาเอาต์พุตคำพูดแบบเข้มงวดเข้ากับ
|
||||
พรอมป์ระบบ:
|
||||
สำหรับการตอบกลับอัตโนมัติ Voice Call จะต่อท้ายสัญญาเอาต์พุตเสียงพูดแบบเข้มงวด
|
||||
เข้ากับพรอมป์ต์ระบบ:
|
||||
|
||||
```text
|
||||
{"spoken":"..."}
|
||||
```
|
||||
|
||||
Voice Call แยกข้อความคำพูดอย่างระมัดระวัง:
|
||||
Voice Call ดึงข้อความคำพูดอย่างระมัดระวัง:
|
||||
|
||||
- ละเว้นเพย์โหลดที่ทำเครื่องหมายเป็นเนื้อหา reasoning/error
|
||||
- แยกวิเคราะห์ JSON ตรง, JSON ใน fence หรือคีย์ `"spoken"` แบบอินไลน์
|
||||
- ถอยกลับไปใช้ข้อความธรรมดาและลบย่อหน้าเกริ่นนำที่น่าจะเป็นการวางแผน/เมตา
|
||||
- ละเว้นเพย์โหลดที่ทำเครื่องหมายเป็นเนื้อหาการให้เหตุผล/ข้อผิดพลาด
|
||||
- แยกวิเคราะห์ JSON โดยตรง, JSON ใน fenced block หรือคีย์ `"spoken"` แบบอินไลน์
|
||||
- ย้อนกลับไปใช้ข้อความธรรมดาและลบย่อหน้านำที่น่าจะเป็นการวางแผน/เมตา
|
||||
|
||||
สิ่งนี้ช่วยให้การเล่นเสียงคำพูดมุ่งเน้นที่ข้อความสำหรับผู้โทรและหลีกเลี่ยง
|
||||
การรั่วไหลของข้อความวางแผนเข้าไปในเสียง
|
||||
สิ่งนี้ช่วยให้การเล่นเสียงพูดเน้นข้อความสำหรับผู้โทรและหลีกเลี่ยง
|
||||
การรั่วไหลข้อความวางแผนไปยังเสียง
|
||||
|
||||
### ลักษณะการทำงานเมื่อเริ่มการสนทนา
|
||||
### พฤติกรรมการเริ่มต้นการสนทนา
|
||||
|
||||
สำหรับสาย `conversation` ขาออก การจัดการข้อความแรกผูกกับสถานะ
|
||||
การเล่นเสียงสด:
|
||||
|
||||
- การล้างคิว barge-in และการตอบกลับอัตโนมัติจะถูกระงับเฉพาะขณะที่คำทักทายแรกกำลังพูดอยู่เท่านั้น
|
||||
- หากการเล่นเสียงแรกเริ่มล้มเหลว การโทรจะกลับไปเป็น `listening` และข้อความแรกยังคงอยู่ในคิวเพื่อรอลองใหม่
|
||||
- การเล่นเสียงแรกเริ่มสำหรับการสตรีม Twilio จะเริ่มเมื่อสตรีมเชื่อมต่อโดยไม่มีดีเลย์เพิ่มเติม
|
||||
- barge-in จะยกเลิกการเล่นเสียงที่กำลังทำงานและล้างรายการ TTS ของ Twilio ที่เข้าคิวแล้วแต่ยังไม่ได้เริ่มเล่น รายการที่ถูกล้างจะ resolve เป็น skipped เพื่อให้ลอจิกการตอบกลับถัดไปดำเนินต่อได้โดยไม่ต้องรอเสียงที่จะไม่มีวันเล่น
|
||||
- การสนทนาเสียงแบบเรียลไทม์ใช้เทิร์นเปิดของสตรีมเรียลไทม์เอง Voice Call **จะไม่** โพสต์อัปเดต TwiML `<Say>` แบบเดิมสำหรับข้อความแรกเริ่มนั้น ดังนั้นเซสชัน `<Connect><Stream>` ขาออกจะยังคงแนบอยู่
|
||||
- การล้างคิวจาก barge-in และการตอบกลับอัตโนมัติจะถูกระงับเฉพาะขณะที่คำทักทายแรกกำลังพูดอยู่
|
||||
- หากการเล่นเสียงแรกเริ่มล้มเหลว สายจะกลับไปเป็น `listening` และข้อความแรกจะยังคงอยู่ในคิวเพื่อรอลองใหม่
|
||||
- การเล่นเสียงแรกเริ่มสำหรับการสตรีม Twilio จะเริ่มเมื่อสตรีมเชื่อมต่อโดยไม่มีความล่าช้าเพิ่มเติม
|
||||
- Barge-in ยกเลิกการเล่นเสียงที่ทำงานอยู่และล้างรายการ Twilio TTS ที่เข้าคิวไว้แต่ยังไม่ได้เล่น รายการที่ถูกล้างจะ resolve เป็นถูกข้าม เพื่อให้ตรรกะการตอบกลับต่อเนื่องดำเนินต่อได้โดยไม่ต้องรอเสียงที่ไม่มีวันเล่น
|
||||
- การสนทนาเสียงแบบเรียลไทม์ใช้เทิร์นเปิดของสตรีมเรียลไทม์เอง Voice Call จะ **ไม่** โพสต์อัปเดต TwiML `<Say>` แบบเดิมสำหรับข้อความแรกเริ่มนั้น ดังนั้นเซสชัน `<Connect><Stream>` ขาออกจึงยังคงเชื่อมต่ออยู่
|
||||
|
||||
### ระยะผ่อนผันเมื่อสตรีม Twilio ตัดการเชื่อมต่อ
|
||||
### ช่วงผ่อนผันเมื่อสตรีม Twilio ตัดการเชื่อมต่อ
|
||||
|
||||
เมื่อสตรีมสื่อของ Twilio ตัดการเชื่อมต่อ Voice Call จะรอ **2000 ms** ก่อน
|
||||
จบการโทรโดยอัตโนมัติ:
|
||||
เมื่อสตรีมสื่อ Twilio ตัดการเชื่อมต่อ Voice Call จะรอ **2000 ms** ก่อน
|
||||
สิ้นสุดสายโดยอัตโนมัติ:
|
||||
|
||||
- หากสตรีมเชื่อมต่อใหม่ในช่วงเวลานั้น การจบอัตโนมัติจะถูกยกเลิก
|
||||
- หากไม่มีสตรีมลงทะเบียนใหม่หลังระยะผ่อนผัน การโทรจะถูกจบเพื่อป้องกันสายที่ค้างอยู่ในสถานะแอคทีฟ
|
||||
- หากสตรีมเชื่อมต่อกลับในช่วงเวลานั้น การสิ้นสุดอัตโนมัติจะถูกยกเลิก
|
||||
- หากไม่มีสตรีมลงทะเบียนใหม่หลังช่วงผ่อนผัน สายจะถูกสิ้นสุดเพื่อป้องกันสายที่ยัง active ค้างอยู่
|
||||
|
||||
## ตัวเก็บกวาดสายค้าง
|
||||
|
||||
ใช้ `staleCallReaperSeconds` เพื่อจบสายที่ไม่เคยได้รับ Webhook ปลายทาง
|
||||
(ตัวอย่างเช่น สายโหมดแจ้งเตือนที่ไม่เคยเสร็จสมบูรณ์) ค่าเริ่มต้น
|
||||
ใช้ `staleCallReaperSeconds` เพื่อสิ้นสุดสายที่ไม่เคยได้รับ Webhook
|
||||
ปลายทาง (ตัวอย่างเช่น สายโหมดแจ้งเตือนที่ไม่เคยเสร็จสมบูรณ์) ค่าเริ่มต้น
|
||||
คือ `0` (ปิดใช้งาน)
|
||||
|
||||
ช่วงที่แนะนำ:
|
||||
ช่วงค่าที่แนะนำ:
|
||||
|
||||
- **โปรดักชัน:** `120`–`300` วินาทีสำหรับโฟลว์แบบแจ้งเตือน
|
||||
- ตั้งค่านี้ให้ **สูงกว่า `maxDurationSeconds`** เพื่อให้สายปกติสามารถเสร็จสิ้นได้ จุดเริ่มต้นที่ดีคือ `maxDurationSeconds + 30–60` วินาที
|
||||
- ให้ค่านี้ **สูงกว่า `maxDurationSeconds`** เพื่อให้สายปกติจบได้ จุดเริ่มต้นที่ดีคือ `maxDurationSeconds + 30–60` วินาที
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -632,26 +638,26 @@ Voice Call แยกข้อความคำพูดอย่างระม
|
||||
|
||||
## ความปลอดภัยของ Webhook
|
||||
|
||||
เมื่อมีพร็อกซีหรือทันเนลอยู่หน้า Gateway Plugin จะ
|
||||
สร้าง URL สาธารณะขึ้นใหม่เพื่อการตรวจสอบลายเซ็น ตัวเลือกเหล่านี้
|
||||
ควบคุมว่าจะเชื่อถือส่วนหัวที่ส่งต่อใด:
|
||||
เมื่อพร็อกซีหรือทันเนลอยู่หน้า Gateway Plugin จะ
|
||||
สร้าง URL สาธารณะใหม่สำหรับการตรวจสอบลายเซ็น ตัวเลือกเหล่านี้
|
||||
ควบคุมว่าเฮดเดอร์ที่ส่งต่อใดเชื่อถือได้:
|
||||
|
||||
<ParamField path="webhookSecurity.allowedHosts" type="string[]">
|
||||
โฮสต์ allowlist จากส่วนหัวการส่งต่อ
|
||||
อนุญาตโฮสต์จากเฮดเดอร์การส่งต่อ
|
||||
</ParamField>
|
||||
<ParamField path="webhookSecurity.trustForwardingHeaders" type="boolean">
|
||||
เชื่อถือส่วนหัวที่ส่งต่อโดยไม่มี allowlist
|
||||
เชื่อถือเฮดเดอร์ที่ส่งต่อโดยไม่ต้องมี allowlist
|
||||
</ParamField>
|
||||
<ParamField path="webhookSecurity.trustedProxyIPs" type="string[]">
|
||||
เชื่อถือส่วนหัวที่ส่งต่อเฉพาะเมื่อ IP ระยะไกลของคำขอตรงกับรายการ
|
||||
เชื่อถือเฮดเดอร์ที่ส่งต่อเฉพาะเมื่อ IP ระยะไกลของคำขอตรงกับรายการ
|
||||
</ParamField>
|
||||
|
||||
การป้องกันเพิ่มเติม:
|
||||
|
||||
- เปิดใช้ **การป้องกันการเล่นซ้ำ** ของ Webhook สำหรับ Twilio และ Plivo คำขอ Webhook ที่ถูกต้องแต่เล่นซ้ำจะได้รับการตอบรับแต่ถูกข้ามสำหรับผลข้างเคียง
|
||||
- เทิร์นการสนทนาของ Twilio มีโทเค็นต่อเทิร์นในคอลแบ็ก `<Gather>` ดังนั้นคอลแบ็กคำพูดที่ค้าง/เล่นซ้ำจึงไม่สามารถตอบสนองเทิร์นถอดเสียงที่รออยู่ใหม่กว่าได้
|
||||
- คำขอ Webhook ที่ไม่ได้ยืนยันตัวตนจะถูกปฏิเสธก่อนอ่านบอดี้เมื่อส่วนหัวลายเซ็นที่ผู้ให้บริการกำหนดขาดหายไป
|
||||
- Webhook ของ voice-call ใช้โปรไฟล์บอดี้ก่อนยืนยันตัวตนร่วมกัน (64 KB / 5 วินาที) พร้อมขีดจำกัด in-flight ต่อ IP ก่อนตรวจสอบลายเซ็น
|
||||
- เปิดใช้ **การป้องกันการเล่นซ้ำ** ของ Webhook สำหรับ Twilio และ Plivo คำขอ Webhook ที่ถูกต้องซึ่งถูกเล่นซ้ำจะได้รับการยืนยัน แต่จะข้ามผลข้างเคียง
|
||||
- เทิร์นการสนทนา Twilio มีโทเค็นต่อเทิร์นในคอลแบ็ก `<Gather>` ดังนั้นคอลแบ็กคำพูดที่เก่า/ถูกเล่นซ้ำจึงไม่สามารถทำให้เทิร์นทรานสคริปต์ที่รอดำเนินการใหม่กว่าสำเร็จได้
|
||||
- คำขอ Webhook ที่ไม่ได้ยืนยันตัวตนจะถูกปฏิเสธก่อนอ่าน body เมื่อเฮดเดอร์ลายเซ็นที่ผู้ให้บริการต้องการขาดหายไป
|
||||
- Webhook ของ voice-call ใช้โปรไฟล์ body ก่อนยืนยันตัวตนร่วมกัน (64 KB / 5 วินาที) รวมกับขีดจำกัด in-flight ต่อ IP ก่อนการตรวจสอบลายเซ็น
|
||||
|
||||
ตัวอย่างพร้อมโฮสต์สาธารณะที่เสถียร:
|
||||
|
||||
@ -687,21 +693,21 @@ openclaw voicecall latency # summarize turn latency from lo
|
||||
openclaw voicecall expose --mode funnel
|
||||
```
|
||||
|
||||
เมื่อ Gateway กำลังทำงานอยู่แล้ว คำสั่ง `voicecall` เชิงปฏิบัติการจะมอบหมาย
|
||||
ไปยัง runtime ของ voice-call ที่ Gateway เป็นเจ้าของ เพื่อให้ CLI ไม่ bind
|
||||
เซิร์ฟเวอร์ Webhook ตัวที่สอง หากติดต่อ Gateway ไม่ได้ คำสั่งจะถอยกลับไปใช้
|
||||
runtime ของ CLI แบบสแตนด์อโลน
|
||||
เมื่อ Gateway ทำงานอยู่แล้ว คำสั่ง `voicecall` เชิงปฏิบัติการจะมอบหมายงาน
|
||||
ให้รันไทม์การโทรเสียงที่ Gateway เป็นเจ้าของ เพื่อให้ CLI ไม่ผูกกับเซิร์ฟเวอร์
|
||||
webhook ตัวที่สอง หากติดต่อ Gateway ไม่ได้ คำสั่งจะถอยกลับไปใช้รันไทม์
|
||||
CLI แบบสแตนด์อโลน
|
||||
|
||||
`latency` อ่าน `calls.jsonl` จากพาธพื้นที่จัดเก็บ voice-call เริ่มต้น
|
||||
ใช้ `--file <path>` เพื่อชี้ไปยังล็อกอื่น และ `--last <n>` เพื่อจำกัด
|
||||
การวิเคราะห์ไว้ที่ระเบียน N รายการล่าสุด (ค่าเริ่มต้น 200) เอาต์พุตมี p50/p90/p99
|
||||
สำหรับเวลาแฝงของเทิร์นและเวลารอฟัง
|
||||
`latency` อ่าน `calls.jsonl` จากพาธจัดเก็บการโทรเสียงเริ่มต้น
|
||||
ใช้ `--file <path>` เพื่อชี้ไปยังบันทึกอื่น และ `--last <n>` เพื่อจำกัด
|
||||
การวิเคราะห์ไว้ที่ N ระเบียนล่าสุด (ค่าเริ่มต้น 200) เอาต์พุตมี p50/p90/p99
|
||||
สำหรับเวลาแฝงของรอบสนทนาและเวลารอฟัง
|
||||
|
||||
## เครื่องมือเอเจนต์
|
||||
## เครื่องมือ Agent
|
||||
|
||||
ชื่อเครื่องมือ: `voice_call`.
|
||||
|
||||
| การกระทำ | อาร์กิวเมนต์ |
|
||||
| การกระทำ | อาร์กิวเมนต์ |
|
||||
| --------------- | ------------------------------------------ |
|
||||
| `initiate_call` | `message`, `to?`, `mode?`, `dtmfSequence?` |
|
||||
| `continue_call` | `callId`, `message` |
|
||||
@ -710,11 +716,11 @@ runtime ของ CLI แบบสแตนด์อโลน
|
||||
| `end_call` | `callId` |
|
||||
| `get_status` | `callId` |
|
||||
|
||||
รีโพนี้มาพร้อมเอกสารทักษะที่ตรงกันที่ `skills/voice-call/SKILL.md`.
|
||||
repo นี้มาพร้อมเอกสาร skill ที่ตรงกันที่ `skills/voice-call/SKILL.md`.
|
||||
|
||||
## RPC ของ Gateway
|
||||
## Gateway RPC
|
||||
|
||||
| เมธอด | อาร์กิวเมนต์ |
|
||||
| เมธอด | อาร์กิวเมนต์ |
|
||||
| -------------------- | ------------------------------------------ |
|
||||
| `voicecall.initiate` | `to?`, `message`, `mode?`, `dtmfSequence?` |
|
||||
| `voicecall.continue` | `callId`, `message` |
|
||||
@ -723,32 +729,32 @@ runtime ของ CLI แบบสแตนด์อโลน
|
||||
| `voicecall.end` | `callId` |
|
||||
| `voicecall.status` | `callId` |
|
||||
|
||||
`dtmfSequence` ใช้ได้เฉพาะกับ `mode: "conversation"` เท่านั้น การโทรในโหมดแจ้งเตือน
|
||||
ควรใช้ `voicecall.dtmf` หลังจากมีสายแล้ว หากต้องใช้ตัวเลขหลังเชื่อมต่อ
|
||||
`dtmfSequence` ใช้ได้เฉพาะกับ `mode: "conversation"` เท่านั้น การโทรในโหมด
|
||||
notify ควรใช้ `voicecall.dtmf` หลังจากมีการโทรแล้ว หากต้องใช้ตัวเลขหลังเชื่อมต่อ
|
||||
|
||||
## การแก้ไขปัญหา
|
||||
|
||||
### การตั้งค่าล้มเหลวจากการเปิดเผย Webhook
|
||||
### การตั้งค่าล้มเหลวที่การเปิดเผย webhook
|
||||
|
||||
เรียกใช้การตั้งค่าจากสภาพแวดล้อมเดียวกับที่รัน Gateway:
|
||||
เรียกใช้การตั้งค่าจากสภาพแวดล้อมเดียวกับที่เรียกใช้ Gateway:
|
||||
|
||||
```bash
|
||||
openclaw voicecall setup
|
||||
openclaw voicecall setup --json
|
||||
```
|
||||
|
||||
สำหรับ `twilio`, `telnyx` และ `plivo`, `webhook-exposure` ต้องเป็นสีเขียว
|
||||
`publicUrl` ที่กำหนดค่าไว้ยังล้มเหลวได้เมื่อชี้ไปยังพื้นที่เครือข่ายภายในเครื่องหรือส่วนตัว
|
||||
เพราะผู้ให้บริการโทรศัพท์ไม่สามารถเรียกกลับมายังที่อยู่เหล่านั้นได้ อย่าใช้
|
||||
`localhost`, `127.0.0.1`, `0.0.0.0`, `10.x`, `172.16.x`-`172.31.x`,
|
||||
สำหรับ `twilio`, `telnyx` และ `plivo` นั้น `webhook-exposure` ต้องเป็นสีเขียว
|
||||
`publicUrl` ที่กำหนดค่าไว้ยังคงล้มเหลวได้เมื่อชี้ไปยังพื้นที่เครือข่าย local
|
||||
หรือ private เพราะผู้ให้บริการเครือข่ายโทรศัพท์ไม่สามารถเรียกกลับไปยังที่อยู่เหล่านั้นได้
|
||||
อย่าใช้ `localhost`, `127.0.0.1`, `0.0.0.0`, `10.x`, `172.16.x`-`172.31.x`,
|
||||
`192.168.x`, `169.254.x`, `fc00::/7` หรือ `fd00::/8` เป็น `publicUrl`.
|
||||
|
||||
สายออกในโหมดแจ้งเตือนของ Twilio ส่ง TwiML `<Say>` เริ่มต้นโดยตรงใน
|
||||
คำขอสร้างสาย ดังนั้นข้อความพูดแรกจึงไม่ขึ้นกับการที่ Twilio ดึง TwiML จาก Webhook
|
||||
ยังคงต้องมี Webhook สาธารณะสำหรับคอลแบ็กสถานะ, การโทรแบบสนทนา, DTMF ก่อนเชื่อมต่อ,
|
||||
สตรีมเรียลไทม์ และการควบคุมสายหลังเชื่อมต่อ
|
||||
การโทรออกของ Twilio ในโหมด notify จะส่ง TwiML `<Say>` เริ่มต้นโดยตรงใน
|
||||
คำขอ create-call ดังนั้นข้อความพูดแรกจึงไม่ขึ้นกับการที่ Twilio ดึง webhook TwiML
|
||||
ยังคงต้องใช้ webhook สาธารณะสำหรับ status callbacks, การโทรแบบสนทนา,
|
||||
DTMF ก่อนเชื่อมต่อ, สตรีมแบบ realtime และการควบคุมสายหลังเชื่อมต่อ
|
||||
|
||||
ใช้พาธเปิดเผยสาธารณะหนึ่งรายการ:
|
||||
ใช้พาธเปิดเผยสาธารณะหนึ่งแบบ:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -768,18 +774,18 @@ openclaw voicecall setup --json
|
||||
}
|
||||
```
|
||||
|
||||
หลังเปลี่ยนการกำหนดค่า ให้รีสตาร์ตหรือโหลด Gateway ใหม่ แล้วเรียกใช้:
|
||||
หลังจากเปลี่ยน config แล้ว ให้รีสตาร์ตหรือโหลด Gateway ใหม่ จากนั้นเรียกใช้:
|
||||
|
||||
```bash
|
||||
openclaw voicecall setup
|
||||
openclaw voicecall smoke
|
||||
```
|
||||
|
||||
`voicecall smoke` เป็นการทดสอบแบบไม่ส่งผลจริง เว้นแต่คุณจะส่ง `--yes`.
|
||||
`voicecall smoke` เป็นการรันแบบ dry run เว้นแต่คุณจะส่ง `--yes`.
|
||||
|
||||
### ข้อมูลรับรองของผู้ให้บริการล้มเหลว
|
||||
### ข้อมูลรับรองผู้ให้บริการล้มเหลว
|
||||
|
||||
ตรวจสอบผู้ให้บริการที่เลือกและฟิลด์ข้อมูลรับรองที่ต้องใช้:
|
||||
ตรวจสอบผู้ให้บริการที่เลือกและฟิลด์ข้อมูลรับรองที่จำเป็น:
|
||||
|
||||
- Twilio: `twilio.accountSid`, `twilio.authToken` และ `fromNumber` หรือ
|
||||
`TWILIO_ACCOUNT_SID`, `TWILIO_AUTH_TOKEN` และ `TWILIO_FROM_NUMBER`.
|
||||
@ -787,13 +793,12 @@ openclaw voicecall smoke
|
||||
`fromNumber`.
|
||||
- Plivo: `plivo.authId`, `plivo.authToken` และ `fromNumber`.
|
||||
|
||||
ข้อมูลรับรองต้องมีอยู่บนโฮสต์ Gateway การแก้ไขโปรไฟล์เชลล์ภายในเครื่อง
|
||||
จะไม่มีผลกับ Gateway ที่กำลังรันอยู่จนกว่าจะรีสตาร์ตหรือโหลด
|
||||
สภาพแวดล้อมใหม่
|
||||
ข้อมูลรับรองต้องมีอยู่บนโฮสต์ Gateway การแก้ไขโปรไฟล์ shell ในเครื่อง
|
||||
จะไม่ส่งผลต่อ Gateway ที่กำลังทำงานอยู่จนกว่าจะรีสตาร์ตหรือโหลดสภาพแวดล้อมใหม่
|
||||
|
||||
### สายเริ่มต้นได้แต่ Webhook ของผู้ให้บริการไม่มาถึง
|
||||
### การโทรเริ่มต้นได้ แต่ webhook ของผู้ให้บริการไม่มาถึง
|
||||
|
||||
ยืนยันว่าคอนโซลของผู้ให้บริการชี้ไปยัง URL Webhook สาธารณะที่ถูกต้องทุกอักขระ:
|
||||
ยืนยันว่าคอนโซลของผู้ให้บริการชี้ไปยัง URL webhook สาธารณะที่ถูกต้องพอดี:
|
||||
|
||||
```text
|
||||
https://voice.example.com/voice/webhook
|
||||
@ -807,84 +812,84 @@ openclaw voicecall tail
|
||||
openclaw logs --follow
|
||||
```
|
||||
|
||||
สาเหตุทั่วไป:
|
||||
สาเหตุที่พบบ่อย:
|
||||
|
||||
- `publicUrl` ชี้ไปยังพาธที่ต่างจาก `serve.path`.
|
||||
- URL ทันเนลเปลี่ยนหลังจาก Gateway เริ่มทำงานแล้ว
|
||||
- พร็อกซีส่งต่อคำขอแต่ตัดหรือเขียนส่วนหัว host/proto ใหม่
|
||||
- ไฟร์วอลล์หรือ DNS ส่งชื่อโฮสต์สาธารณะไปยังที่อื่นที่ไม่ใช่ Gateway
|
||||
- Gateway ถูกรีสตาร์ตโดยไม่ได้เปิดใช้งาน Plugin Voice Call
|
||||
- URL tunnel เปลี่ยนหลังจาก Gateway เริ่มทำงาน
|
||||
- proxy ส่งต่อคำขอ แต่ตัดหรือเขียน host/proto headers ใหม่
|
||||
- firewall หรือ DNS นำชื่อโฮสต์สาธารณะไปยังตำแหน่งอื่นที่ไม่ใช่ Gateway
|
||||
- Gateway ถูกรีสตาร์ตโดยไม่ได้เปิดใช้งาน Voice Call Plugin
|
||||
|
||||
เมื่อมี reverse proxy หรือทันเนลอยู่หน้า Gateway ให้ตั้งค่า
|
||||
เมื่อมี reverse proxy หรือ tunnel อยู่หน้า Gateway ให้ตั้งค่า
|
||||
`webhookSecurity.allowedHosts` เป็นชื่อโฮสต์สาธารณะ หรือใช้
|
||||
`webhookSecurity.trustedProxyIPs` สำหรับที่อยู่พร็อกซีที่รู้จัก ใช้
|
||||
`webhookSecurity.trustForwardingHeaders` เฉพาะเมื่อขอบเขตพร็อกซีอยู่ภายใต้
|
||||
`webhookSecurity.trustedProxyIPs` สำหรับที่อยู่ proxy ที่ทราบแน่ชัด ใช้
|
||||
`webhookSecurity.trustForwardingHeaders` เฉพาะเมื่อขอบเขต proxy อยู่ภายใต้
|
||||
การควบคุมของคุณ
|
||||
|
||||
### การยืนยันลายเซ็นล้มเหลว
|
||||
### การตรวจสอบลายเซ็นล้มเหลว
|
||||
|
||||
ลายเซ็นของผู้ให้บริการจะถูกตรวจสอบกับ URL สาธารณะที่ OpenClaw สร้างขึ้นใหม่
|
||||
ลายเซ็นของผู้ให้บริการจะถูกตรวจสอบเทียบกับ URL สาธารณะที่ OpenClaw สร้างใหม่
|
||||
จากคำขอขาเข้า หากลายเซ็นล้มเหลว:
|
||||
|
||||
- ยืนยันว่า URL Webhook ของผู้ให้บริการตรงกับ `publicUrl` ทุกอักขระ รวมถึง
|
||||
- ยืนยันว่า URL webhook ของผู้ให้บริการตรงกับ `publicUrl` ทุกประการ รวมถึง
|
||||
scheme, host และ path.
|
||||
- สำหรับ URL ระดับฟรีของ ngrok ให้อัปเดต `publicUrl` เมื่อชื่อโฮสต์ของทันเนลเปลี่ยน
|
||||
- ตรวจสอบว่าพร็อกซีคงส่วนหัว host และ proto เดิมไว้ หรือกำหนดค่า
|
||||
- สำหรับ URL ของ ngrok free-tier ให้อัปเดต `publicUrl` เมื่อชื่อโฮสต์ tunnel เปลี่ยน
|
||||
- ตรวจสอบให้แน่ใจว่า proxy รักษา host และ proto headers เดิมไว้ หรือกำหนดค่า
|
||||
`webhookSecurity.allowedHosts`.
|
||||
- อย่าเปิดใช้ `skipSignatureVerification` นอกการทดสอบภายในเครื่อง
|
||||
- อย่าเปิดใช้ `skipSignatureVerification` นอกการทดสอบ local
|
||||
|
||||
### การเข้าร่วม Google Meet ผ่าน Twilio ล้มเหลว
|
||||
### การเข้าร่วม Google Meet ด้วย Twilio ล้มเหลว
|
||||
|
||||
Google Meet ใช้ Plugin นี้สำหรับการเข้าร่วมแบบโทรเข้า Twilio ก่อนอื่นให้ตรวจสอบ Voice Call:
|
||||
Google Meet ใช้ Plugin นี้สำหรับการเข้าร่วมแบบ dial-in ผ่าน Twilio ก่อนอื่นให้ตรวจสอบ Voice Call:
|
||||
|
||||
```bash
|
||||
openclaw voicecall setup
|
||||
openclaw voicecall smoke --to "+15555550123"
|
||||
```
|
||||
|
||||
จากนั้นตรวจสอบทรานสปอร์ต Google Meet โดยตรง:
|
||||
จากนั้นตรวจสอบการขนส่งของ Google Meet อย่างชัดเจน:
|
||||
|
||||
```bash
|
||||
openclaw googlemeet setup --transport twilio
|
||||
```
|
||||
|
||||
หาก Voice Call เป็นสีเขียวแต่ผู้เข้าร่วม Meet ไม่เคยเข้าร่วม ให้ตรวจสอบ
|
||||
หมายเลขโทรเข้า Meet, PIN และ `--dtmf-sequence` สายโทรศัพท์อาจปกติดีในขณะที่
|
||||
การประชุมปฏิเสธหรือไม่สนใจลำดับ DTMF ที่ไม่ถูกต้อง
|
||||
หาก Voice Call เป็นสีเขียวแต่ผู้เข้าร่วม Meet ไม่เคยเข้าร่วม ให้ตรวจสอบหมายเลข
|
||||
dial-in ของ Meet, PIN และ `--dtmf-sequence` สายโทรศัพท์อาจปกติดีแม้การประชุม
|
||||
จะปฏิเสธหรือเพิกเฉยต่อลำดับ DTMF ที่ไม่ถูกต้อง
|
||||
|
||||
Google Meet ส่งลำดับ DTMF ของ Meet และข้อความแนะนำไปยัง `voicecall.start`.
|
||||
สำหรับสาย Twilio, Voice Call จะให้บริการ TwiML ของ DTMF ก่อน เปลี่ยนเส้นทางกลับไปยัง
|
||||
Webhook แล้วเปิดสตรีมสื่อเรียลไทม์เพื่อให้สร้างข้อความแนะนำที่บันทึกไว้
|
||||
สำหรับการโทร Twilio นั้น Voice Call จะให้บริการ DTMF TwiML ก่อน เปลี่ยนเส้นทางกลับไปยัง
|
||||
webhook แล้วจึงเปิดสตรีมสื่อแบบ realtime เพื่อให้ข้อความแนะนำที่บันทึกไว้ถูกสร้าง
|
||||
หลังจากผู้เข้าร่วมทางโทรศัพท์เข้าร่วมการประชุมแล้ว
|
||||
|
||||
ใช้ `openclaw logs --follow` สำหรับร่องรอยระยะสด การเข้าร่วม Twilio Meet
|
||||
ที่ปกติจะบันทึกลำดับนี้:
|
||||
ใช้ `openclaw logs --follow` สำหรับ trace ช่วง live การเข้าร่วม Twilio Meet
|
||||
ที่ทำงานปกติจะบันทึกลำดับนี้:
|
||||
|
||||
- Google Meet มอบหมายการเข้าร่วม Twilio ให้ Voice Call
|
||||
- Voice Call จัดเก็บ TwiML ของ DTMF ก่อนเชื่อมต่อ
|
||||
- TwiML เริ่มต้นของ Twilio ถูกใช้งานและให้บริการก่อนการจัดการเรียลไทม์
|
||||
- Voice Call ให้บริการ TwiML เรียลไทม์สำหรับสาย Twilio
|
||||
- บริดจ์เรียลไทม์เริ่มต้นพร้อมคำทักทายเริ่มต้นที่ถูกเข้าคิวไว้
|
||||
- Voice Call จัดเก็บ DTMF TwiML ก่อนเชื่อมต่อ
|
||||
- Twilio initial TwiML ถูกใช้และให้บริการก่อนการจัดการแบบ realtime
|
||||
- Voice Call ให้บริการ realtime TwiML สำหรับการโทร Twilio
|
||||
- realtime bridge เริ่มต้นพร้อมคำทักทายเริ่มต้นที่เข้าคิวไว้
|
||||
|
||||
`openclaw voicecall tail` ยังคงแสดงระเบียนสายที่คงอยู่ ซึ่งมีประโยชน์สำหรับ
|
||||
สถานะสายและทรานสคริปต์ แต่ไม่ใช่ทุกการเปลี่ยนผ่านของ Webhook/เรียลไทม์จะปรากฏ
|
||||
ที่นั่น
|
||||
`openclaw voicecall tail` ยังคงแสดงระเบียนการโทรที่บันทึกถาวร มีประโยชน์สำหรับ
|
||||
สถานะการโทรและทรานสคริปต์ แต่ไม่ใช่ทุกการเปลี่ยนผ่านของ webhook/realtime
|
||||
ที่จะปรากฏที่นั่น
|
||||
|
||||
### สายเรียลไทม์ไม่มีเสียงพูด
|
||||
### การโทรแบบ realtime ไม่มีเสียงพูด
|
||||
|
||||
ยืนยันว่าเปิดใช้โหมดเสียงเพียงโหมดเดียว `realtime.enabled` และ
|
||||
ยืนยันว่าเปิดใช้งานโหมดเสียงเพียงโหมดเดียว `realtime.enabled` และ
|
||||
`streaming.enabled` ไม่สามารถเป็น true พร้อมกันได้
|
||||
|
||||
สำหรับสาย Twilio แบบเรียลไทม์ ให้ตรวจสอบเพิ่มเติมว่า:
|
||||
สำหรับการโทร Twilio แบบ realtime ให้ตรวจสอบเพิ่มเติมว่า:
|
||||
|
||||
- มีการโหลดและลงทะเบียน Plugin ผู้ให้บริการเรียลไทม์แล้ว
|
||||
- Plugin ผู้ให้บริการ realtime ถูกโหลดและลงทะเบียนแล้ว
|
||||
- `realtime.provider` ไม่ได้ตั้งค่าไว้ หรือระบุชื่อผู้ให้บริการที่ลงทะเบียนแล้ว
|
||||
- คีย์ API ของผู้ให้บริการพร้อมใช้งานสำหรับกระบวนการ Gateway
|
||||
- `openclaw logs --follow` แสดงว่าให้บริการ TwiML เรียลไทม์แล้ว บริดจ์เรียลไทม์
|
||||
เริ่มต้นแล้ว และคำทักทายเริ่มต้นถูกเข้าคิวแล้ว
|
||||
- API key ของผู้ให้บริการพร้อมใช้งานสำหรับ process ของ Gateway
|
||||
- `openclaw logs --follow` แสดงว่า realtime TwiML ถูกให้บริการ, realtime bridge
|
||||
เริ่มต้นแล้ว และคำทักทายเริ่มต้นถูกเข้าคิวไว้
|
||||
|
||||
## ที่เกี่ยวข้อง
|
||||
|
||||
- [โหมดพูดคุย](/th/nodes/talk)
|
||||
- [ข้อความเป็นเสียงพูด](/th/tools/tts)
|
||||
- [การปลุกด้วยเสียง](/th/nodes/voicewake)
|
||||
- [ปลุกด้วยเสียง](/th/nodes/voicewake)
|
||||
|
||||
@ -1,32 +1,32 @@
|
||||
---
|
||||
read_when:
|
||||
- คุณต้องการใช้ระบบแปลงข้อความเป็นเสียงของ ElevenLabs ใน OpenClaw
|
||||
- คุณต้องการใช้ระบบแปลงเสียงเป็นข้อความ ElevenLabs Scribe สำหรับไฟล์แนบเสียง
|
||||
- คุณต้องการใช้การถอดเสียงแบบเรียลไทม์ของ ElevenLabs สำหรับ Voice Call
|
||||
summary: ใช้เสียงพูด ElevenLabs, Scribe STT และการถอดเสียงแบบเรียลไทม์กับ OpenClaw
|
||||
- คุณต้องการใช้การแปลงข้อความเป็นเสียงของ ElevenLabs ใน OpenClaw
|
||||
- คุณต้องการใช้ ElevenLabs Scribe สำหรับการถอดเสียงพูดเป็นข้อความจากไฟล์แนบเสียง
|
||||
- คุณต้องการการถอดเสียงแบบเรียลไทม์ด้วย ElevenLabs สำหรับการโทรด้วยเสียงหรือ Google Meet
|
||||
summary: ใช้เสียงพูดของ ElevenLabs, Scribe STT และการถอดเสียงแบบเรียลไทม์กับ OpenClaw
|
||||
title: ElevenLabs
|
||||
x-i18n:
|
||||
generated_at: "2026-04-25T13:57:04Z"
|
||||
model: gpt-5.4
|
||||
generated_at: "2026-05-04T07:06:18Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 1f858a344228c6355cd5fdc3775cddac39e0075f2e9fcf7683271f11be03a31a
|
||||
source_hash: 4c880bf9dcab01ef70779c74576c70ea5d0203b96b5f739291842fafcb4bdb4b
|
||||
source_path: providers/elevenlabs.md
|
||||
workflow: 15
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
OpenClaw ใช้ ElevenLabs สำหรับการแปลงข้อความเป็นเสียง, การแปลงเสียงเป็นข้อความแบบแบตช์ด้วย Scribe
|
||||
v2 และ STT แบบสตรีมมิงสำหรับ Voice Call ด้วย Scribe v2 Realtime
|
||||
v2 และ STT แบบสตรีมด้วย Scribe v2 Realtime.
|
||||
|
||||
| ความสามารถ | พื้นที่ใช้งานใน OpenClaw | ค่าเริ่มต้น |
|
||||
| ----------------------- | ----------------------------------------------- | ------------------------- |
|
||||
| การแปลงข้อความเป็นเสียง | `messages.tts` / `talk` | `eleven_multilingual_v2` |
|
||||
| การแปลงเสียงเป็นข้อความแบบแบตช์ | `tools.media.audio` | `scribe_v2` |
|
||||
| การแปลงเสียงเป็นข้อความแบบสตรีมมิง | Voice Call `streaming.provider: "elevenlabs"` | `scribe_v2_realtime` |
|
||||
| ความสามารถ | พื้นผิวของ OpenClaw | ค่าเริ่มต้น |
|
||||
| ------------------------ | -------------------------------------------------------------------- | ------------------------ |
|
||||
| การแปลงข้อความเป็นเสียง | `messages.tts` / `talk` | `eleven_multilingual_v2` |
|
||||
| การแปลงเสียงเป็นข้อความแบบแบตช์ | `tools.media.audio` | `scribe_v2` |
|
||||
| การแปลงเสียงเป็นข้อความแบบสตรีม | การสตรีม Voice Call หรือ Google Meet `realtime.transcriptionProvider` | `scribe_v2_realtime` |
|
||||
|
||||
## การยืนยันตัวตน
|
||||
|
||||
ตั้งค่า `ELEVENLABS_API_KEY` ใน environment โดย `XI_API_KEY` ก็รองรับเช่นกัน
|
||||
เพื่อความเข้ากันได้กับเครื่องมือ ElevenLabs ที่มีอยู่เดิม
|
||||
ตั้งค่า `ELEVENLABS_API_KEY` ในสภาพแวดล้อม ระบบยังยอมรับ `XI_API_KEY` เพื่อ
|
||||
ความเข้ากันได้กับเครื่องมือ ElevenLabs ที่มีอยู่.
|
||||
|
||||
```bash
|
||||
export ELEVENLABS_API_KEY="..."
|
||||
@ -50,12 +50,12 @@ export ELEVENLABS_API_KEY="..."
|
||||
}
|
||||
```
|
||||
|
||||
ตั้งค่า `modelId` เป็น `eleven_v3` เพื่อใช้ ElevenLabs v3 TTS โดย OpenClaw ยังคงใช้
|
||||
`eleven_multilingual_v2` เป็นค่าเริ่มต้นสำหรับการติดตั้งเดิม
|
||||
ตั้งค่า `modelId` เป็น `eleven_v3` เพื่อใช้ ElevenLabs v3 TTS. OpenClaw ยังคงใช้
|
||||
`eleven_multilingual_v2` เป็นค่าเริ่มต้นสำหรับการติดตั้งที่มีอยู่.
|
||||
|
||||
## การแปลงเสียงเป็นข้อความ
|
||||
|
||||
ใช้ Scribe v2 สำหรับไฟล์แนบเสียงขาเข้าและเสียงพูดที่บันทึกไว้ช่วงสั้น ๆ:
|
||||
ใช้ Scribe v2 สำหรับไฟล์แนบเสียงขาเข้าและช่วงเสียงพูดที่บันทึกไว้แบบสั้น:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -71,20 +71,21 @@ export ELEVENLABS_API_KEY="..."
|
||||
```
|
||||
|
||||
OpenClaw ส่งเสียงแบบ multipart ไปยัง ElevenLabs `/v1/speech-to-text` พร้อม
|
||||
`model_id: "scribe_v2"` โดยคำใบ้ภาษาจะถูกแมปไปยัง `language_code` เมื่อมีการระบุ
|
||||
`model_id: "scribe_v2"`. คำใบ้ภาษาจะแมปไปยัง `language_code` เมื่อมีอยู่.
|
||||
|
||||
## STT แบบสตรีมมิงสำหรับ Voice Call
|
||||
## STT แบบสตรีม
|
||||
|
||||
Plugin `elevenlabs` ที่มีมาในตัวจะลงทะเบียน Scribe v2 Realtime สำหรับการถอดเสียงแบบสตรีมมิงของ Voice Call
|
||||
Plugin `elevenlabs` ที่รวมมาให้จะลงทะเบียน Scribe v2 Realtime สำหรับ Voice Call และ
|
||||
การถอดความแบบสตรีมในโหมดเอเจนต์ของ Google Meet.
|
||||
|
||||
| การตั้งค่า | เส้นทาง config | ค่าเริ่มต้น |
|
||||
| ---------------- | ------------------------------------------------------------------------- | -------------------------------------------------- |
|
||||
| API key | `plugins.entries.voice-call.config.streaming.providers.elevenlabs.apiKey` | ใช้ `ELEVENLABS_API_KEY` / `XI_API_KEY` เป็นค่า fallback |
|
||||
| โมเดล | `...elevenlabs.modelId` | `scribe_v2_realtime` |
|
||||
| รูปแบบเสียง | `...elevenlabs.audioFormat` | `ulaw_8000` |
|
||||
| อัตราการสุ่มตัวอย่าง | `...elevenlabs.sampleRate` | `8000` |
|
||||
| กลยุทธ์การ commit | `...elevenlabs.commitStrategy` | `vad` |
|
||||
| ภาษา | `...elevenlabs.languageCode` | (ไม่ตั้งค่า) |
|
||||
| การตั้งค่า | เส้นทางการกำหนดค่า | ค่าเริ่มต้น |
|
||||
| --------------- | ------------------------------------------------------------------------- | ------------------------------------------------- |
|
||||
| คีย์ API | `plugins.entries.voice-call.config.streaming.providers.elevenlabs.apiKey` | ย้อนกลับไปใช้ `ELEVENLABS_API_KEY` / `XI_API_KEY` |
|
||||
| โมเดล | `...elevenlabs.modelId` | `scribe_v2_realtime` |
|
||||
| รูปแบบเสียง | `...elevenlabs.audioFormat` | `ulaw_8000` |
|
||||
| อัตราสุ่มตัวอย่าง | `...elevenlabs.sampleRate` | `8000` |
|
||||
| กลยุทธ์ commit | `...elevenlabs.commitStrategy` | `vad` |
|
||||
| ภาษา | `...elevenlabs.languageCode` | (ไม่ได้ตั้งค่า) |
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -112,12 +113,18 @@ Plugin `elevenlabs` ที่มีมาในตัวจะลงทะเบ
|
||||
```
|
||||
|
||||
<Note>
|
||||
Voice Call รับสื่อจาก Twilio เป็น G.711 u-law ที่ 8 kHz โดย provider แบบเรียลไทม์ของ ElevenLabs
|
||||
ใช้ค่าเริ่มต้นเป็น `ulaw_8000` ดังนั้นเฟรมโทรศัพท์จึงสามารถส่งต่อได้โดยไม่ต้อง
|
||||
transcode
|
||||
Voice Call รับสื่อ Twilio เป็น G.711 u-law ที่ 8 kHz. Provider แบบ realtime ของ ElevenLabs
|
||||
มีค่าเริ่มต้นเป็น `ulaw_8000` ดังนั้นเฟรมโทรศัพท์จึงสามารถส่งต่อได้โดยไม่ต้อง
|
||||
แปลงรหัส.
|
||||
</Note>
|
||||
|
||||
สำหรับโหมดเอเจนต์ของ Google Meet ให้ตั้งค่า
|
||||
`plugins.entries.google-meet.config.realtime.transcriptionProvider` เป็น
|
||||
`"elevenlabs"` และกำหนดค่าบล็อก Provider เดียวกันภายใต้
|
||||
`plugins.entries.google-meet.config.realtime.providers.elevenlabs`.
|
||||
|
||||
## ที่เกี่ยวข้อง
|
||||
|
||||
- [การแปลงข้อความเป็นเสียง](/th/tools/tts)
|
||||
- [Google Meet](/th/plugins/google-meet)
|
||||
- [การเลือกโมเดล](/th/concepts/model-providers)
|
||||
|
||||
@ -1,38 +1,38 @@
|
||||
---
|
||||
read_when:
|
||||
- คุณต้องการใช้โมเดล Google Gemini กับ OpenClaw
|
||||
- คุณต้องใช้คีย์ API หรือโฟลว์การตรวจสอบสิทธิ์ OAuth
|
||||
summary: การตั้งค่า Google Gemini (คีย์ API + OAuth, การสร้างภาพ, การทำความเข้าใจสื่อ, TTS, การค้นหาเว็บ)
|
||||
- คุณต้องใช้คีย์ API หรือขั้นตอนการยืนยันตัวตนแบบ OAuth
|
||||
summary: การตั้งค่า Google Gemini (คีย์ API + OAuth, การสร้างรูปภาพ, การทำความเข้าใจสื่อ, TTS, การค้นหาเว็บ)
|
||||
title: Google (Gemini)
|
||||
x-i18n:
|
||||
generated_at: "2026-05-02T10:26:17Z"
|
||||
generated_at: "2026-05-04T07:06:25Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 14605b88f0d1d7e01796d429113a73b2b52a48fde6443565dcb3db47653be5e7
|
||||
source_hash: 3e45627f5d5cd57e858c7590a90435b7fc0e9381509f3312a16fc9e9a4cbd908
|
||||
source_path: providers/google.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
Plugin ของ Google ให้การเข้าถึงโมเดล Gemini ผ่าน Google AI Studio รวมถึง
|
||||
การสร้างรูปภาพ การทำความเข้าใจสื่อ (รูปภาพ/เสียง/วิดีโอ), การแปลงข้อความเป็นเสียง และการค้นหาเว็บผ่าน
|
||||
การสร้างภาพ การทำความเข้าใจสื่อ (ภาพ/เสียง/วิดีโอ) การแปลงข้อความเป็นเสียง และการค้นหาเว็บผ่าน
|
||||
Gemini Grounding
|
||||
|
||||
- ผู้ให้บริการ: `google`
|
||||
- การยืนยันตัวตน: `GEMINI_API_KEY` หรือ `GOOGLE_API_KEY`
|
||||
- API: Google Gemini API
|
||||
- ตัวเลือก Runtime: `agents.defaults.agentRuntime.id: "google-gemini-cli"`
|
||||
ใช้ Gemini CLI OAuth ซ้ำ โดยยังคงให้ refs ของโมเดลเป็นรูปแบบ canonical เช่น `google/*`
|
||||
- ตัวเลือกรันไทม์: `agents.defaults.agentRuntime.id: "google-gemini-cli"`
|
||||
ใช้ Gemini CLI OAuth ซ้ำ พร้อมคงการอ้างอิงโมเดลให้เป็นรูปแบบมาตรฐานเป็น `google/*`
|
||||
|
||||
## เริ่มต้นใช้งาน
|
||||
|
||||
เลือกวิธีการยืนยันตัวตนที่ต้องการ แล้วทำตามขั้นตอนการตั้งค่า
|
||||
เลือกวิธีการยืนยันตัวตนที่ต้องการและทำตามขั้นตอนการตั้งค่า
|
||||
|
||||
<Tabs>
|
||||
<Tab title="API key">
|
||||
**เหมาะที่สุดสำหรับ:** การเข้าถึง Gemini API มาตรฐานผ่าน Google AI Studio
|
||||
**เหมาะสำหรับ:** การเข้าถึง Gemini API มาตรฐานผ่าน Google AI Studio
|
||||
|
||||
<Steps>
|
||||
<Step title="รัน onboarding">
|
||||
<Step title="Run onboarding">
|
||||
```bash
|
||||
openclaw onboard --auth-choice gemini-api-key
|
||||
```
|
||||
@ -46,7 +46,7 @@ Gemini Grounding
|
||||
--gemini-api-key "$GEMINI_API_KEY"
|
||||
```
|
||||
</Step>
|
||||
<Step title="ตั้งค่าโมเดลเริ่มต้น">
|
||||
<Step title="Set a default model">
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
@ -57,7 +57,7 @@ Gemini Grounding
|
||||
}
|
||||
```
|
||||
</Step>
|
||||
<Step title="ตรวจสอบว่าโมเดลพร้อมใช้งาน">
|
||||
<Step title="Verify the model is available">
|
||||
```bash
|
||||
openclaw models list --provider google
|
||||
```
|
||||
@ -65,22 +65,22 @@ Gemini Grounding
|
||||
</Steps>
|
||||
|
||||
<Tip>
|
||||
ตัวแปรสภาพแวดล้อม `GEMINI_API_KEY` และ `GOOGLE_API_KEY` ใช้ได้ทั้งคู่ ใช้ตัวที่คุณตั้งค่าไว้อยู่แล้ว
|
||||
ตัวแปรสภาพแวดล้อม `GEMINI_API_KEY` และ `GOOGLE_API_KEY` ใช้ได้ทั้งคู่ ใช้ตัวที่คุณกำหนดค่าไว้อยู่แล้ว
|
||||
</Tip>
|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab title="Gemini CLI (OAuth)">
|
||||
**เหมาะที่สุดสำหรับ:** การใช้การเข้าสู่ระบบ Gemini CLI ที่มีอยู่ผ่าน PKCE OAuth ซ้ำ แทนการใช้ API key แยกต่างหาก
|
||||
**เหมาะสำหรับ:** การใช้การเข้าสู่ระบบ Gemini CLI ที่มีอยู่แล้วซ้ำผ่าน PKCE OAuth แทน API key แยกต่างหาก
|
||||
|
||||
<Warning>
|
||||
ผู้ให้บริการ `google-gemini-cli` เป็นการผสานรวมที่ไม่เป็นทางการ ผู้ใช้บางราย
|
||||
รายงานข้อจำกัดของบัญชีเมื่อใช้ OAuth ด้วยวิธีนี้ ใช้โดยยอมรับความเสี่ยงเอง
|
||||
ผู้ให้บริการ `google-gemini-cli` เป็นการเชื่อมต่อแบบไม่เป็นทางการ ผู้ใช้บางราย
|
||||
รายงานว่ามีข้อจำกัดบัญชีเมื่อใช้ OAuth ด้วยวิธีนี้ ใช้โดยยอมรับความเสี่ยงเอง
|
||||
</Warning>
|
||||
|
||||
<Steps>
|
||||
<Step title="ติดตั้ง Gemini CLI">
|
||||
คำสั่ง `gemini` ในเครื่องต้องพร้อมใช้งานบน `PATH`
|
||||
<Step title="Install the Gemini CLI">
|
||||
คำสั่ง `gemini` ภายในเครื่องต้องพร้อมใช้งานบน `PATH`
|
||||
|
||||
```bash
|
||||
# Homebrew
|
||||
@ -90,15 +90,15 @@ Gemini Grounding
|
||||
npm install -g @google/gemini-cli
|
||||
```
|
||||
|
||||
OpenClaw รองรับทั้งการติดตั้งผ่าน Homebrew และการติดตั้ง npm แบบ global รวมถึง
|
||||
เลย์เอาต์ Windows/npm ที่พบบ่อย
|
||||
OpenClaw รองรับทั้งการติดตั้งผ่าน Homebrew และการติดตั้ง npm แบบโกลบอล รวมถึง
|
||||
โครงสร้าง Windows/npm ทั่วไป
|
||||
</Step>
|
||||
<Step title="เข้าสู่ระบบผ่าน OAuth">
|
||||
<Step title="Log in via OAuth">
|
||||
```bash
|
||||
openclaw models auth login --provider google-gemini-cli --set-default
|
||||
```
|
||||
</Step>
|
||||
<Step title="ตรวจสอบว่าโมเดลพร้อมใช้งาน">
|
||||
<Step title="Verify the model is available">
|
||||
```bash
|
||||
openclaw models list --provider google
|
||||
```
|
||||
@ -106,10 +106,10 @@ Gemini Grounding
|
||||
</Steps>
|
||||
|
||||
- โมเดลเริ่มต้น: `google/gemini-3.1-pro-preview`
|
||||
- Runtime: `google-gemini-cli`
|
||||
- รันไทม์: `google-gemini-cli`
|
||||
- นามแฝง: `gemini-cli`
|
||||
|
||||
รหัสโมเดล Gemini API ของ Gemini 3.1 Pro คือ `gemini-3.1-pro-preview` OpenClaw รับค่า `google/gemini-3.1-pro` แบบสั้นกว่าเป็นนามแฝงเพื่อความสะดวก และทำให้เป็นรูปแบบปกติก่อนเรียกผู้ให้บริการ
|
||||
รหัสโมเดล Gemini API ของ Gemini 3.1 Pro คือ `gemini-3.1-pro-preview` OpenClaw รับ `google/gemini-3.1-pro` ที่สั้นกว่าเป็นนามแฝงเพื่อความสะดวก และปรับให้อยู่ในรูปแบบมาตรฐานก่อนเรียกผู้ให้บริการ
|
||||
|
||||
**ตัวแปรสภาพแวดล้อม:**
|
||||
|
||||
@ -119,42 +119,42 @@ Gemini Grounding
|
||||
(หรือรูปแบบ `GEMINI_CLI_*`)
|
||||
|
||||
<Note>
|
||||
หากคำขอ Gemini CLI OAuth ล้มเหลวหลังเข้าสู่ระบบ ให้ตั้งค่า `GOOGLE_CLOUD_PROJECT` หรือ
|
||||
หากคำขอ Gemini CLI OAuth ล้มเหลวหลังจากเข้าสู่ระบบ ให้ตั้งค่า `GOOGLE_CLOUD_PROJECT` หรือ
|
||||
`GOOGLE_CLOUD_PROJECT_ID` บนโฮสต์ Gateway แล้วลองอีกครั้ง
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
หากการเข้าสู่ระบบล้มเหลวก่อนเริ่มขั้นตอนในเบราว์เซอร์ ให้ตรวจสอบว่ามีการติดตั้งคำสั่ง `gemini`
|
||||
ในเครื่องและอยู่บน `PATH`
|
||||
หากการเข้าสู่ระบบล้มเหลวก่อนเริ่มโฟลว์เบราว์เซอร์ ตรวจสอบให้แน่ใจว่าคำสั่ง `gemini`
|
||||
ภายในเครื่องถูกติดตั้งและอยู่บน `PATH`
|
||||
</Note>
|
||||
|
||||
refs โมเดล `google-gemini-cli/*` เป็นนามแฝงเพื่อความเข้ากันได้แบบเดิม การกำหนดค่าใหม่
|
||||
ควรใช้ refs โมเดล `google/*` ร่วมกับ Runtime `google-gemini-cli`
|
||||
เมื่อต้องการให้ Gemini CLI ทำงานในเครื่อง
|
||||
การอ้างอิงโมเดล `google-gemini-cli/*` เป็นนามแฝงความเข้ากันได้แบบเดิม การกำหนดค่าใหม่
|
||||
ควรใช้การอ้างอิงโมเดล `google/*` พร้อมกับรันไทม์ `google-gemini-cli`
|
||||
เมื่อต้องการให้ Gemini CLI ทำงานภายในเครื่อง
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## ความสามารถ
|
||||
|
||||
| ความสามารถ | รองรับ |
|
||||
| ความสามารถ | รองรับ |
|
||||
| ---------------------- | ----------------------------- |
|
||||
| การเติมเต็มแชต | ใช่ |
|
||||
| การสร้างรูปภาพ | ใช่ |
|
||||
| การสร้างเพลง | ใช่ |
|
||||
| การแปลงข้อความเป็นเสียง | ใช่ |
|
||||
| เสียงแบบเรียลไทม์ | ใช่ (Google Live API) |
|
||||
| การทำความเข้าใจรูปภาพ | ใช่ |
|
||||
| การถอดเสียงจากเสียง | ใช่ |
|
||||
| การทำความเข้าใจวิดีโอ | ใช่ |
|
||||
| การค้นหาเว็บ (Grounding) | ใช่ |
|
||||
| การคิด/การให้เหตุผล | ใช่ (Gemini 2.5+ / Gemini 3+) |
|
||||
| โมเดล Gemma 4 | ใช่ |
|
||||
| การเติมเต็มแชต | ใช่ |
|
||||
| การสร้างภาพ | ใช่ |
|
||||
| การสร้างเพลง | ใช่ |
|
||||
| การแปลงข้อความเป็นเสียง | ใช่ |
|
||||
| เสียงเรียลไทม์ | ใช่ (Google Live API) |
|
||||
| การทำความเข้าใจภาพ | ใช่ |
|
||||
| การถอดเสียง | ใช่ |
|
||||
| การทำความเข้าใจวิดีโอ | ใช่ |
|
||||
| การค้นหาเว็บ (Grounding) | ใช่ |
|
||||
| การคิด/การใช้เหตุผล | ใช่ (Gemini 2.5+ / Gemini 3+) |
|
||||
| โมเดล Gemma 4 | ใช่ |
|
||||
|
||||
## การค้นหาเว็บ
|
||||
|
||||
ผู้ให้บริการค้นหาเว็บ `gemini` ที่มาพร้อมชุดใช้งานใช้ Gemini Google Search grounding
|
||||
กำหนดค่าคีย์ค้นหาเฉพาะภายใต้ `plugins.entries.google.config.webSearch`
|
||||
ผู้ให้บริการค้นหาเว็บ `gemini` ที่รวมมาให้ใช้ Gemini Google Search grounding
|
||||
กำหนดค่าคีย์ค้นหาเฉพาะใต้ `plugins.entries.google.config.webSearch`
|
||||
หรือให้ใช้ `models.providers.google.apiKey` ซ้ำหลังจาก `GEMINI_API_KEY`:
|
||||
|
||||
```json5
|
||||
@ -175,40 +175,40 @@ Gemini Grounding
|
||||
}
|
||||
```
|
||||
|
||||
ลำดับความสำคัญของข้อมูลประจำตัวคือ `webSearch.apiKey` เฉพาะก่อน จากนั้น `GEMINI_API_KEY`
|
||||
แล้วจึงเป็น `models.providers.google.apiKey` `webSearch.baseUrl` เป็นค่าไม่บังคับและ
|
||||
มีไว้สำหรับพร็อกซีของผู้ปฏิบัติงานหรือปลายทาง Gemini API ที่เข้ากันได้ เมื่อไม่ได้ระบุ
|
||||
การค้นหาเว็บของ Gemini จะใช้ `models.providers.google.baseUrl` ซ้ำ ดู
|
||||
[การค้นหา Gemini](/th/tools/gemini-search) สำหรับพฤติกรรมเครื่องมือเฉพาะของผู้ให้บริการ
|
||||
ลำดับความสำคัญของข้อมูลรับรองคือ `webSearch.apiKey` เฉพาะ จากนั้น `GEMINI_API_KEY`
|
||||
จากนั้น `models.providers.google.apiKey` `webSearch.baseUrl` เป็นตัวเลือกและ
|
||||
มีไว้สำหรับพร็อกซีของผู้ดำเนินการหรือปลายทาง Gemini API ที่เข้ากันได้ เมื่อไม่ระบุ
|
||||
การค้นหาเว็บ Gemini จะใช้ `models.providers.google.baseUrl` ซ้ำ ดู
|
||||
[การค้นหา Gemini](/th/tools/gemini-search) สำหรับพฤติกรรมเครื่องมือเฉพาะผู้ให้บริการ
|
||||
|
||||
<Tip>
|
||||
โมเดล Gemini 3 ใช้ `thinkingLevel` แทน `thinkingBudget` OpenClaw แมป
|
||||
ตัวควบคุมการให้เหตุผลของนามแฝง Gemini 3, Gemini 3.1 และ `gemini-*-latest` ไปยัง
|
||||
`thinkingLevel` เพื่อให้การรันเริ่มต้น/ความหน่วงต่ำไม่ส่งค่า
|
||||
`thinkingBudget` ที่ถูกปิดใช้งาน
|
||||
การควบคุมเหตุผลของนามแฝง Gemini 3, Gemini 3.1 และ `gemini-*-latest` ไปยัง
|
||||
`thinkingLevel` เพื่อให้การรันแบบค่าเริ่มต้น/หน่วงเวลาต่ำไม่ส่งค่า
|
||||
`thinkingBudget` ที่ปิดใช้งานแล้ว
|
||||
|
||||
`/think adaptive` คง semantics การคิดแบบไดนามิกของ Google ไว้แทนการเลือก
|
||||
ระดับ OpenClaw แบบตายตัว Gemini 3 และ Gemini 3.1 จะละเว้น `thinkingLevel` แบบตายตัวเพื่อให้
|
||||
`/think adaptive` คงความหมายการคิดแบบไดนามิกของ Google แทนการเลือก
|
||||
ระดับ OpenClaw แบบคงที่ Gemini 3 และ Gemini 3.1 จะละ `thinkingLevel` แบบคงที่เพื่อให้
|
||||
Google เลือกระดับได้ ส่วน Gemini 2.5 จะส่ง sentinel แบบไดนามิกของ Google
|
||||
`thinkingBudget: -1`
|
||||
|
||||
โมเดล Gemma 4 (เช่น `gemma-4-26b-a4b-it`) รองรับโหมดการคิด OpenClaw
|
||||
เขียน `thinkingBudget` ใหม่เป็น `thinkingLevel` ของ Google ที่รองรับสำหรับ Gemma 4
|
||||
การตั้งค่าการคิดเป็น `off` จะคงการปิดใช้งานการคิดไว้ แทนที่จะแมปเป็น
|
||||
การตั้งค่าการคิดเป็น `off` จะคงการปิดใช้งานการคิดไว้แทนการแมปเป็น
|
||||
`MINIMAL`
|
||||
</Tip>
|
||||
|
||||
## การสร้างรูปภาพ
|
||||
## การสร้างภาพ
|
||||
|
||||
ผู้ให้บริการสร้างรูปภาพ `google` ที่มาพร้อมชุดใช้งานมีค่าเริ่มต้นเป็น
|
||||
ผู้ให้บริการสร้างภาพ `google` ที่รวมมาให้ตั้งค่าเริ่มต้นเป็น
|
||||
`google/gemini-3.1-flash-image-preview`
|
||||
|
||||
- รองรับ `google/gemini-3-pro-image-preview` ด้วย
|
||||
- สร้าง: ได้สูงสุด 4 รูปภาพต่อคำขอ
|
||||
- โหมดแก้ไข: เปิดใช้งาน รองรับรูปภาพอินพุตสูงสุด 5 รูป
|
||||
- ตัวควบคุมเรขาคณิต: `size`, `aspectRatio` และ `resolution`
|
||||
- สร้าง: สูงสุด 4 ภาพต่อคำขอ
|
||||
- โหมดแก้ไข: เปิดใช้งาน สูงสุด 5 ภาพอินพุต
|
||||
- การควบคุมเรขาคณิต: `size`, `aspectRatio` และ `resolution`
|
||||
|
||||
หากต้องการใช้ Google เป็นผู้ให้บริการรูปภาพเริ่มต้น:
|
||||
หากต้องการใช้ Google เป็นผู้ให้บริการภาพเริ่มต้น:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -223,18 +223,18 @@ Google เลือกระดับได้ ส่วน Gemini 2.5 จะส
|
||||
```
|
||||
|
||||
<Note>
|
||||
ดู [การสร้างรูปภาพ](/th/tools/image-generation) สำหรับพารามิเตอร์เครื่องมือที่ใช้ร่วมกัน การเลือกผู้ให้บริการ และพฤติกรรม failover
|
||||
ดู [การสร้างภาพ](/th/tools/image-generation) สำหรับพารามิเตอร์เครื่องมือร่วม การเลือกผู้ให้บริการ และพฤติกรรม failover
|
||||
</Note>
|
||||
|
||||
## การสร้างวิดีโอ
|
||||
|
||||
Plugin `google` ที่มาพร้อมชุดใช้งานยังลงทะเบียนการสร้างวิดีโอผ่านเครื่องมือที่ใช้ร่วมกัน
|
||||
`video_generate`
|
||||
Plugin `google` ที่รวมมาให้ยังลงทะเบียนการสร้างวิดีโอผ่านเครื่องมือร่วม
|
||||
`video_generate` ด้วย
|
||||
|
||||
- โมเดลวิดีโอเริ่มต้น: `google/veo-3.1-fast-generate-preview`
|
||||
- โหมด: โฟลว์ข้อความเป็นวิดีโอ รูปภาพเป็นวิดีโอ และการอ้างอิงวิดีโอเดียว
|
||||
- โหมด: โฟลว์ข้อความเป็นวิดีโอ ภาพเป็นวิดีโอ และอ้างอิงวิดีโอเดียว
|
||||
- รองรับ `aspectRatio`, `resolution` และ `audio`
|
||||
- ขีดจำกัดระยะเวลาปัจจุบัน: **4 ถึง 8 วินาที**
|
||||
- การจำกัดระยะเวลาปัจจุบัน: **4 ถึง 8 วินาที**
|
||||
|
||||
หากต้องการใช้ Google เป็นผู้ให้บริการวิดีโอเริ่มต้น:
|
||||
|
||||
@ -251,20 +251,20 @@ Plugin `google` ที่มาพร้อมชุดใช้งานยั
|
||||
```
|
||||
|
||||
<Note>
|
||||
ดู [การสร้างวิดีโอ](/th/tools/video-generation) สำหรับพารามิเตอร์เครื่องมือที่ใช้ร่วมกัน การเลือกผู้ให้บริการ และพฤติกรรม failover
|
||||
ดู [การสร้างวิดีโอ](/th/tools/video-generation) สำหรับพารามิเตอร์เครื่องมือร่วม การเลือกผู้ให้บริการ และพฤติกรรม failover
|
||||
</Note>
|
||||
|
||||
## การสร้างเพลง
|
||||
|
||||
Plugin `google` ที่มาพร้อมชุดใช้งานยังลงทะเบียนการสร้างเพลงผ่านเครื่องมือที่ใช้ร่วมกัน
|
||||
`music_generate`
|
||||
Plugin `google` ที่รวมมาให้ยังลงทะเบียนการสร้างเพลงผ่านเครื่องมือร่วม
|
||||
`music_generate` ด้วย
|
||||
|
||||
- โมเดลเพลงเริ่มต้น: `google/lyria-3-clip-preview`
|
||||
- รองรับ `google/lyria-3-pro-preview` ด้วย
|
||||
- ตัวควบคุมพรอมป์: `lyrics` และ `instrumental`
|
||||
- รูปแบบเอาต์พุต: `mp3` เป็นค่าเริ่มต้น และมี `wav` เพิ่มเติมบน `google/lyria-3-pro-preview`
|
||||
- อินพุตอ้างอิง: รูปภาพสูงสุด 10 รูป
|
||||
- การรันที่มีเซสชันรองรับจะแยกการทำงานผ่านโฟลว์งาน/สถานะที่ใช้ร่วมกัน รวมถึง `action: "status"`
|
||||
- การควบคุมพรอมป์: `lyrics` และ `instrumental`
|
||||
- รูปแบบเอาต์พุต: ค่าเริ่มต้นคือ `mp3` รวมถึง `wav` บน `google/lyria-3-pro-preview`
|
||||
- อินพุตอ้างอิง: สูงสุด 10 ภาพ
|
||||
- การรันที่มีเซสชันรองรับจะ detach ผ่านโฟลว์งาน/สถานะร่วม รวมถึง `action: "status"`
|
||||
|
||||
หากต้องการใช้ Google เป็นผู้ให้บริการเพลงเริ่มต้น:
|
||||
|
||||
@ -281,18 +281,18 @@ Plugin `google` ที่มาพร้อมชุดใช้งานยั
|
||||
```
|
||||
|
||||
<Note>
|
||||
ดู [การสร้างเพลง](/th/tools/music-generation) สำหรับพารามิเตอร์เครื่องมือที่ใช้ร่วมกัน การเลือกผู้ให้บริการ และพฤติกรรม failover
|
||||
ดู [การสร้างเพลง](/th/tools/music-generation) สำหรับพารามิเตอร์เครื่องมือร่วม การเลือกผู้ให้บริการ และพฤติกรรม failover
|
||||
</Note>
|
||||
|
||||
## การแปลงข้อความเป็นเสียง
|
||||
|
||||
ผู้ให้บริการเสียง `google` ที่มาพร้อมชุดใช้งานใช้เส้นทาง TTS ของ Gemini API ด้วย
|
||||
ผู้ให้บริการเสียงพูด `google` ที่รวมมาให้ใช้เส้นทาง TTS ของ Gemini API ด้วย
|
||||
`gemini-3.1-flash-tts-preview`
|
||||
|
||||
- เสียงเริ่มต้น: `Kore`
|
||||
- การยืนยันตัวตน: `messages.tts.providers.google.apiKey`, `models.providers.google.apiKey`, `GEMINI_API_KEY` หรือ `GOOGLE_API_KEY`
|
||||
- เอาต์พุต: WAV สำหรับไฟล์แนบ TTS ปกติ, Opus สำหรับเป้าหมาย voice-note, PCM สำหรับ Talk/โทรศัพท์
|
||||
- เอาต์พุต voice-note: Google PCM จะถูกห่อเป็น WAV และแปลงรหัสเป็น Opus 48 kHz ด้วย `ffmpeg`
|
||||
- เอาต์พุต voice-note: Google PCM ถูกห่อเป็น WAV และทรานส์โค้ดเป็น Opus 48 kHz ด้วย `ffmpeg`
|
||||
|
||||
หากต้องการใช้ Google เป็นผู้ให้บริการ TTS เริ่มต้น:
|
||||
|
||||
@ -314,13 +314,13 @@ Plugin `google` ที่มาพร้อมชุดใช้งานยั
|
||||
}
|
||||
```
|
||||
|
||||
Gemini API TTS ใช้การพรอมป์ด้วยภาษาธรรมชาติเพื่อควบคุมสไตล์ ตั้งค่า
|
||||
`audioProfile` เพื่อเติมพรอมป์สไตล์ที่นำกลับมาใช้ซ้ำได้ไว้หน้าข้อความที่จะพูด ตั้งค่า
|
||||
Gemini API TTS ใช้การพรอมป์ด้วยภาษาธรรมชาติสำหรับควบคุมสไตล์ ตั้งค่า
|
||||
`audioProfile` เพื่อเติมพรอมป์สไตล์ที่ใช้ซ้ำได้ไว้ก่อนข้อความที่จะพูด ตั้งค่า
|
||||
`speakerName` เมื่อข้อความพรอมป์ของคุณอ้างถึงผู้พูดที่มีชื่อ
|
||||
|
||||
Gemini API TTS ยังรับแท็กเสียงในวงเล็บเหลี่ยมแบบแสดงอารมณ์ในข้อความ
|
||||
เช่น `[whispers]` หรือ `[laughs]` หากต้องการกันแท็กออกจากข้อความตอบกลับแชตที่มองเห็น
|
||||
แต่ยังส่งไปยัง TTS ให้วางไว้ภายในบล็อก `[[tts:text]]...[[/tts:text]]`:
|
||||
Gemini API TTS ยังรับแท็กเสียงแบบวงเล็บเหลี่ยมที่สื่ออารมณ์ในข้อความ
|
||||
เช่น `[whispers]` หรือ `[laughs]` หากต้องการกันแท็กออกจากคำตอบแชตที่มองเห็นได้
|
||||
ในขณะที่ส่งแท็กเหล่านั้นไปยัง TTS ให้ใส่แท็กไว้ในบล็อก `[[tts:text]]...[[/tts:text]]`:
|
||||
|
||||
```text
|
||||
Here is the clean reply text.
|
||||
@ -329,29 +329,31 @@ Here is the clean reply text.
|
||||
```
|
||||
|
||||
<Note>
|
||||
API key ของ Google Cloud Console ที่จำกัดไว้สำหรับ Gemini API ใช้ได้กับ
|
||||
API key ของ Google Cloud Console ที่จำกัดไว้กับ Gemini API ใช้ได้กับ
|
||||
ผู้ให้บริการนี้ นี่ไม่ใช่เส้นทาง Cloud Text-to-Speech API แยกต่างหาก
|
||||
</Note>
|
||||
|
||||
## เสียงแบบเรียลไทม์
|
||||
## เสียงเรียลไทม์
|
||||
|
||||
Plugin `google` ที่มาพร้อมชุดใช้งานลงทะเบียนผู้ให้บริการเสียงแบบเรียลไทม์ที่ใช้
|
||||
Gemini Live API สำหรับบริดจ์เสียงฝั่งแบ็กเอนด์ เช่น Voice Call และ Google Meet
|
||||
Plugin `google` ที่รวมมาให้ลงทะเบียนผู้ให้บริการเสียงเรียลไทม์ที่ขับเคลื่อนโดย
|
||||
Gemini Live API สำหรับบริดจ์เสียงแบ็กเอนด์ เช่น Voice Call และ Google Meet
|
||||
|
||||
| การตั้งค่า | พาธการกำหนดค่า | ค่าเริ่มต้น |
|
||||
| --------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
|
||||
| Model | `plugins.entries.voice-call.config.realtime.providers.google.model` | `gemini-2.5-flash-native-audio-preview-12-2025` |
|
||||
| Voice | `...google.voice` | `Kore` |
|
||||
| Temperature | `...google.temperature` | (ไม่ได้ตั้งค่า) |
|
||||
| ความไวเริ่มต้นของ VAD | `...google.startSensitivity` | (ไม่ได้ตั้งค่า) |
|
||||
| ความไวสิ้นสุดของ VAD | `...google.endSensitivity` | (ไม่ได้ตั้งค่า) |
|
||||
| ระยะเวลาความเงียบ | `...google.silenceDurationMs` | (ไม่ได้ตั้งค่า) |
|
||||
| โมเดล | `plugins.entries.voice-call.config.realtime.providers.google.model` | `gemini-2.5-flash-native-audio-preview-12-2025` |
|
||||
| เสียง | `...google.voice` | `Kore` |
|
||||
| อุณหภูมิ | `...google.temperature` | (ไม่ได้ตั้งค่า) |
|
||||
| ความไวในการเริ่ม VAD | `...google.startSensitivity` | (ไม่ได้ตั้งค่า) |
|
||||
| ความไวในการจบ VAD | `...google.endSensitivity` | (ไม่ได้ตั้งค่า) |
|
||||
| ระยะเวลาเงียบ | `...google.silenceDurationMs` | (ไม่ได้ตั้งค่า) |
|
||||
| การจัดการกิจกรรม | `...google.activityHandling` | ค่าเริ่มต้นของ Google, `start-of-activity-interrupts` |
|
||||
| ความครอบคลุมของเทิร์น | `...google.turnCoverage` | ค่าเริ่มต้นของ Google, `only-activity` |
|
||||
| ปิดใช้งาน VAD อัตโนมัติ | `...google.automaticActivityDetectionDisabled` | `false` |
|
||||
| คีย์ API | `...google.apiKey` | สำรองไปใช้ `models.providers.google.apiKey`, `GEMINI_API_KEY`, หรือ `GOOGLE_API_KEY` |
|
||||
| การกลับมาใช้เซสชันต่อ | `...google.sessionResumption` | `true` |
|
||||
| การบีบอัดบริบท | `...google.contextWindowCompression` | `true` |
|
||||
| คีย์ API | `...google.apiKey` | ถอยกลับไปใช้ `models.providers.google.apiKey`, `GEMINI_API_KEY`, หรือ `GOOGLE_API_KEY` |
|
||||
|
||||
ตัวอย่างการกำหนดค่าเรียลไทม์ของการโทรด้วยเสียง:
|
||||
ตัวอย่างการกำหนดค่าเรียลไทม์ของ Voice Call:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -381,24 +383,24 @@ Gemini Live API สำหรับบริดจ์เสียงฝั่ง
|
||||
|
||||
<Note>
|
||||
Google Live API ใช้เสียงสองทิศทางและการเรียกฟังก์ชันผ่าน WebSocket
|
||||
OpenClaw ปรับเสียงจากบริดจ์โทรศัพท์/Meet ให้เข้ากับสตรีม PCM Live API ของ Gemini และ
|
||||
คงการเรียกใช้เครื่องมือไว้บนสัญญาเสียงเรียลไทม์ที่ใช้ร่วมกัน ปล่อย `temperature`
|
||||
ให้ไม่ได้ตั้งค่าไว้ เว้นแต่คุณต้องการเปลี่ยนการสุ่มตัวอย่าง OpenClaw จะละค่าที่ไม่เป็นบวก
|
||||
เพราะ Google Live อาจส่งคืนทรานสคริปต์โดยไม่มีเสียงสำหรับ `temperature: 0`
|
||||
OpenClaw ปรับเสียงจากสะพานเชื่อมโทรศัพท์/Meet ให้เข้ากับสตรีม PCM Live API ของ Gemini และ
|
||||
คงการเรียกเครื่องมือไว้บนสัญญาเสียงเรียลไทม์ที่ใช้ร่วมกัน ปล่อย `temperature`
|
||||
ไว้โดยไม่ต้องตั้งค่า เว้นแต่คุณต้องเปลี่ยนการสุ่มตัวอย่าง OpenClaw จะละเว้นค่าที่ไม่เป็นบวก
|
||||
เพราะ Google Live อาจส่งทรานสคริปต์กลับมาโดยไม่มีเสียงสำหรับ `temperature: 0`
|
||||
การถอดเสียงของ Gemini API เปิดใช้งานโดยไม่มี `languageCodes`; Google
|
||||
SDK ปัจจุบันปฏิเสธคำแนะนำรหัสภาษาบนพาธ API นี้
|
||||
SDK ปัจจุบันปฏิเสธคำใบ้รหัสภาษาบนพาธ API นี้
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
Control UI Talk รองรับเซสชัน Google Live บนเบราว์เซอร์ด้วยโทเค็นแบบใช้ครั้งเดียวที่มีข้อจำกัด
|
||||
ผู้ให้บริการเสียงเรียลไทม์เฉพาะแบ็กเอนด์ยังสามารถทำงานผ่านทรานสปอร์ตรีเลย์ทั่วไปของ
|
||||
Gateway ซึ่งเก็บข้อมูลรับรองของผู้ให้บริการไว้บน Gateway
|
||||
Control UI Talk รองรับเซสชัน Google Live ในเบราว์เซอร์ด้วยโทเค็นใช้ครั้งเดียวแบบจำกัด
|
||||
ผู้ให้บริการเสียงเรียลไทม์แบบแบ็กเอนด์เท่านั้นยังสามารถทำงานผ่านการขนส่งรีเลย์ทั่วไปของ
|
||||
Gateway ได้ด้วย ซึ่งจะเก็บข้อมูลประจำตัวของผู้ให้บริการไว้บน Gateway
|
||||
</Note>
|
||||
|
||||
สำหรับการตรวจสอบสดของผู้ดูแล ให้รัน
|
||||
`OPENAI_API_KEY=... GEMINI_API_KEY=... node --import tsx scripts/dev/realtime-talk-live-smoke.ts`.
|
||||
ส่วนของ Google จะสร้างโทเค็น Live API ที่มีข้อจำกัดในรูปแบบเดียวกับที่ Control
|
||||
UI Talk ใช้ เปิดปลายทาง WebSocket ของเบราว์เซอร์ ส่งเพย์โหลดการตั้งค่าเริ่มต้น
|
||||
`OPENAI_API_KEY=... GEMINI_API_KEY=... node --import tsx scripts/dev/realtime-talk-live-smoke.ts`
|
||||
ฝั่ง Google จะออกโทเค็น Live API แบบจำกัดรูปแบบเดียวกับที่ Control
|
||||
UI Talk ใช้ เปิดปลายทาง WebSocket ของเบราว์เซอร์ ส่งเพย์โหลดตั้งค่าเริ่มต้น
|
||||
และรอ `setupComplete`
|
||||
|
||||
## การกำหนดค่าขั้นสูง
|
||||
@ -406,13 +408,13 @@ UI Talk ใช้ เปิดปลายทาง WebSocket ของเบร
|
||||
<AccordionGroup>
|
||||
<Accordion title="Direct Gemini cache reuse">
|
||||
สำหรับการรัน Gemini API โดยตรง (`api: "google-generative-ai"`), OpenClaw
|
||||
ส่งแฮนเดิล `cachedContent` ที่กำหนดค่าไว้ต่อไปยังคำขอ Gemini
|
||||
จะส่งต่อแฮนเดิล `cachedContent` ที่กำหนดค่าไว้ไปยังคำขอ Gemini
|
||||
|
||||
- กำหนดค่าพารามิเตอร์ต่อโมเดลหรือส่วนกลางด้วย
|
||||
`cachedContent` หรือ `cached_content` แบบเดิม
|
||||
- หากมีทั้งสองค่า `cachedContent` จะชนะ
|
||||
- หากมีทั้งสองค่า `cachedContent` จะมีผลก่อน
|
||||
- ค่าตัวอย่าง: `cachedContents/prebuilt-context`
|
||||
- การใช้งาน cache-hit ของ Gemini จะถูกปรับให้อยู่ในรูป OpenClaw `cacheRead` จาก
|
||||
- การใช้งาน cache-hit ของ Gemini ถูกทำให้เป็นรูปแบบมาตรฐานเป็น `cacheRead` ของ OpenClaw จาก
|
||||
`cachedContentTokenCount` ต้นทาง
|
||||
|
||||
```json5
|
||||
@ -434,20 +436,20 @@ UI Talk ใช้ เปิดปลายทาง WebSocket ของเบร
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Gemini CLI JSON usage notes">
|
||||
เมื่อใช้ผู้ให้บริการ OAuth `google-gemini-cli`, OpenClaw จะปรับ
|
||||
เอาต์พุต CLI JSON ให้เป็นดังนี้:
|
||||
เมื่อใช้ผู้ให้บริการ OAuth `google-gemini-cli`, OpenClaw จะทำให้
|
||||
เอาต์พุต JSON ของ CLI เป็นรูปแบบมาตรฐานดังนี้:
|
||||
|
||||
- ข้อความตอบกลับมาจากฟิลด์ CLI JSON `response`
|
||||
- การใช้งานสำรองไปใช้ `stats` เมื่อ CLI ปล่อย `usage` ว่างไว้
|
||||
- `stats.cached` จะถูกปรับให้อยู่ในรูป OpenClaw `cacheRead`
|
||||
- ข้อความตอบกลับมาจากฟิลด์ `response` ใน JSON ของ CLI
|
||||
- การใช้งานจะถอยกลับไปใช้ `stats` เมื่อ CLI ปล่อย `usage` ว่างไว้
|
||||
- `stats.cached` ถูกทำให้เป็นรูปแบบมาตรฐานเป็น `cacheRead` ของ OpenClaw
|
||||
- หากไม่มี `stats.input`, OpenClaw จะคำนวณโทเค็นอินพุตจาก
|
||||
`stats.input_tokens - stats.cached`
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Environment and daemon setup">
|
||||
หาก Gateway ทำงานเป็น daemon (launchd/systemd) ตรวจสอบให้แน่ใจว่า `GEMINI_API_KEY`
|
||||
พร้อมใช้งานสำหรับโปรเซสนั้น (เช่น ใน `~/.openclaw/.env` หรือผ่าน
|
||||
หาก Gateway ทำงานเป็น daemon (launchd/systemd), ตรวจสอบให้แน่ใจว่า `GEMINI_API_KEY`
|
||||
พร้อมใช้งานสำหรับกระบวนการนั้น (เช่น ใน `~/.openclaw/.env` หรือผ่าน
|
||||
`env.shellEnv`)
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
@ -456,7 +458,7 @@ UI Talk ใช้ เปิดปลายทาง WebSocket ของเบร
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Model selection" href="/th/concepts/model-providers" icon="layers">
|
||||
การเลือกผู้ให้บริการ, การอ้างอิงโมเดล, และพฤติกรรม failover
|
||||
การเลือกผู้ให้บริการ การอ้างอิงโมเดล และพฤติกรรมการสลับสำรอง
|
||||
</Card>
|
||||
<Card title="Image generation" href="/th/tools/image-generation" icon="image">
|
||||
พารามิเตอร์เครื่องมือรูปภาพที่ใช้ร่วมกันและการเลือกผู้ให้บริการ
|
||||
|
||||
@ -2,172 +2,273 @@
|
||||
read_when:
|
||||
- กำลังค้นหานิยามช่องทางการเผยแพร่สาธารณะ
|
||||
- การเรียกใช้การตรวจสอบความถูกต้องของรีลีสหรือการยอมรับแพ็กเกจ
|
||||
- กำลังมองหารูปแบบการตั้งชื่อเวอร์ชันและจังหวะการออกเวอร์ชัน
|
||||
summary: เลนการเผยแพร่, รายการตรวจสอบสำหรับผู้ปฏิบัติงาน, กล่องตรวจสอบความถูกต้อง, การตั้งชื่อเวอร์ชัน และรอบการเผยแพร่
|
||||
title: นโยบายการเผยแพร่รุ่น
|
||||
- กำลังค้นหารูปแบบการตั้งชื่อเวอร์ชันและรอบการออกรุ่น
|
||||
summary: เลนการเผยแพร่, รายการตรวจสอบสำหรับผู้ปฏิบัติการ, กล่องตรวจสอบความถูกต้อง, การตั้งชื่อเวอร์ชัน และรอบการเผยแพร่
|
||||
title: นโยบายการเผยแพร่
|
||||
x-i18n:
|
||||
generated_at: "2026-05-03T21:36:10Z"
|
||||
generated_at: "2026-05-04T07:06:35Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 566088d826e1e2bac21b11443b82b62cb73ed1fd9c508c3fb865149cf8a428ba
|
||||
source_hash: ef50d3ef5d1e23b4e2c2b097fc4ca9f6d46bf8acb9aea0c9bca6d14e213b88b6
|
||||
source_path: reference/RELEASING.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
OpenClaw มีเลนรีลีสสาธารณะสามเลน:
|
||||
OpenClaw มีเลนการเผยแพร่สาธารณะสามเลน:
|
||||
|
||||
- stable: รีลีสที่ติดแท็กซึ่งเผยแพร่ไปยัง npm `beta` ตามค่าเริ่มต้น หรือไปยัง npm `latest` เมื่อร้องขออย่างชัดเจน
|
||||
- beta: แท็ก prerelease ที่เผยแพร่ไปยัง npm `beta`
|
||||
- dev: หัวที่เคลื่อนไหวของ `main`
|
||||
- stable: รุ่นเผยแพร่ที่ติดแท็ก ซึ่งเผยแพร่ไปยัง npm `beta` ตามค่าเริ่มต้น หรือไปยัง npm `latest` เมื่อมีการร้องขออย่างชัดเจน
|
||||
- beta: แท็กก่อนเผยแพร่ที่เผยแพร่ไปยัง npm `beta`
|
||||
- dev: หัวปัจจุบันที่เปลี่ยนแปลงอยู่ของ `main`
|
||||
|
||||
## การตั้งชื่อเวอร์ชัน
|
||||
|
||||
- เวอร์ชันรีลีส stable: `YYYY.M.D`
|
||||
- เวอร์ชันรุ่นเผยแพร่เสถียร: `YYYY.M.D`
|
||||
- แท็ก Git: `vYYYY.M.D`
|
||||
- เวอร์ชันรีลีสแก้ไข stable: `YYYY.M.D-N`
|
||||
- เวอร์ชันรุ่นเผยแพร่แก้ไขของรุ่นเสถียร: `YYYY.M.D-N`
|
||||
- แท็ก Git: `vYYYY.M.D-N`
|
||||
- เวอร์ชัน prerelease beta: `YYYY.M.D-beta.N`
|
||||
- เวอร์ชันก่อนเผยแพร่ Beta: `YYYY.M.D-beta.N`
|
||||
- แท็ก Git: `vYYYY.M.D-beta.N`
|
||||
- อย่าเติมศูนย์นำหน้าเดือนหรือวัน
|
||||
- `latest` หมายถึงรีลีส npm stable ที่โปรโมตอยู่ในปัจจุบัน
|
||||
- `latest` หมายถึงรุ่นเผยแพร่ npm เสถียรที่ได้รับการโปรโมตในปัจจุบัน
|
||||
- `beta` หมายถึงเป้าหมายการติดตั้ง beta ปัจจุบัน
|
||||
- รีลีส stable และรีลีสแก้ไข stable จะเผยแพร่ไปยัง npm `beta` ตามค่าเริ่มต้น; ผู้ปฏิบัติการรีลีสสามารถระบุเป้าหมายเป็น `latest` อย่างชัดเจน หรือโปรโมตบิลด์ beta ที่ผ่านการตรวจสอบภายหลังได้
|
||||
- รีลีส OpenClaw stable ทุกครั้งจะส่งแพ็กเกจ npm และแอป macOS พร้อมกัน;
|
||||
รีลีส beta โดยปกติจะตรวจสอบความถูกต้องและเผยแพร่เส้นทาง npm/package ก่อน โดย
|
||||
สงวนการ build/sign/notarize แอป mac ไว้สำหรับ stable เว้นแต่จะร้องขออย่างชัดเจน
|
||||
- รุ่นเผยแพร่เสถียรและรุ่นเผยแพร่แก้ไขของรุ่นเสถียรจะเผยแพร่ไปยัง npm `beta` ตามค่าเริ่มต้น; ผู้ดำเนินการเผยแพร่สามารถกำหนดเป้าหมาย `latest` อย่างชัดเจน หรือโปรโมตบิลด์ beta ที่ตรวจสอบแล้วในภายหลังได้
|
||||
- OpenClaw รุ่นเผยแพร่เสถียรทุกเวอร์ชันจะส่งแพ็กเกจ npm และแอป macOS พร้อมกัน;
|
||||
รุ่น beta โดยปกติจะตรวจสอบและเผยแพร่เส้นทาง npm/แพ็กเกจก่อน โดยสงวนการ build/sign/notarize แอป Mac ไว้สำหรับรุ่นเสถียร เว้นแต่จะมีการร้องขออย่างชัดเจน
|
||||
|
||||
## รอบการออกรีลีส
|
||||
## จังหวะการเผยแพร่
|
||||
|
||||
- รีลีสจะเดินหน้าแบบ beta ก่อน
|
||||
- stable จะตามมาหลังจาก beta ล่าสุดผ่านการตรวจสอบแล้วเท่านั้น
|
||||
- โดยปกติ maintainer จะตัดรีลีสจากสาขา `release/YYYY.M.D` ที่สร้างจาก
|
||||
`main` ปัจจุบัน เพื่อให้การตรวจสอบรีลีสและการแก้ไขไม่บล็อกการพัฒนาใหม่
|
||||
บน `main`
|
||||
- หากมีการ push หรือเผยแพร่แท็ก beta แล้วและต้องแก้ไข maintainer จะตัด
|
||||
แท็ก `-beta.N` ถัดไปแทนการลบหรือสร้างแท็ก beta เดิมใหม่
|
||||
- ขั้นตอนรีลีสโดยละเอียด การอนุมัติ ข้อมูลรับรอง และบันทึกการกู้คืนเป็น
|
||||
เฉพาะ maintainer เท่านั้น
|
||||
- การเผยแพร่จะเดินหน้าแบบ beta-first
|
||||
- รุ่นเสถียรจะตามมาหลังจาก beta ล่าสุดได้รับการตรวจสอบแล้วเท่านั้น
|
||||
- โดยปกติผู้ดูแลจะตัดรุ่นจากสาขา `release/YYYY.M.D` ที่สร้างจาก `main` ปัจจุบัน เพื่อให้การตรวจสอบรุ่นเผยแพร่และการแก้ไขไม่บล็อกการพัฒนาใหม่บน `main`
|
||||
- หากแท็ก beta ถูก push หรือเผยแพร่แล้วและต้องการการแก้ไข ผู้ดูแลจะตัดแท็ก `-beta.N` ถัดไปแทนการลบหรือสร้างแท็ก beta เก่าใหม่
|
||||
- ขั้นตอนการเผยแพร่โดยละเอียด การอนุมัติ ข้อมูลประจำตัว และบันทึกการกู้คืนมีไว้สำหรับผู้ดูแลเท่านั้น
|
||||
|
||||
## เช็กลิสต์ผู้ปฏิบัติการรีลีส
|
||||
## เช็กลิสต์ผู้ดำเนินการเผยแพร่
|
||||
|
||||
เช็กลิสต์นี้คือรูปแบบสาธารณะของโฟลว์รีลีส ข้อมูลรับรองส่วนตัว,
|
||||
การลงนาม, การ notarization, การกู้คืน dist-tag และรายละเอียดการ rollback ฉุกเฉินจะอยู่ใน
|
||||
runbook รีลีสเฉพาะ maintainer เท่านั้น
|
||||
เช็กลิสต์นี้คือโครงร่างสาธารณะของโฟลว์การเผยแพร่ ข้อมูลประจำตัวส่วนตัว,
|
||||
การลงนาม, notarization, การกู้คืน dist-tag และรายละเอียดการ rollback ฉุกเฉินยังอยู่ใน
|
||||
runbook การเผยแพร่สำหรับผู้ดูแลเท่านั้น
|
||||
|
||||
1. เริ่มจาก `main` ปัจจุบัน: pull ล่าสุด ยืนยันว่า commit เป้าหมายถูก push แล้ว
|
||||
และยืนยันว่า CI ของ `main` ปัจจุบันเขียวพอที่จะสร้างสาขาจากมันได้
|
||||
และยืนยันว่า CI ของ `main` ปัจจุบันเขียวพอที่จะสร้างสาขาจากมัน
|
||||
2. เขียนส่วนบนสุดของ `CHANGELOG.md` ใหม่จากประวัติ commit จริงด้วย
|
||||
`/changelog` รักษารายการให้เป็นเนื้อหาสำหรับผู้ใช้ commit แล้ว push จากนั้น rebase/pull
|
||||
`/changelog` เก็บรายการให้เป็นเนื้อหาสำหรับผู้ใช้ commit แล้ว push และ rebase/pull
|
||||
อีกครั้งก่อนสร้างสาขา
|
||||
3. ตรวจทานบันทึกความเข้ากันได้ของรีลีสใน
|
||||
3. ตรวจทานบันทึกความเข้ากันได้ของรุ่นเผยแพร่ใน
|
||||
`src/plugins/compat/registry.ts` และ
|
||||
`src/commands/doctor/shared/deprecation-compat.ts` ลบความเข้ากันได้ที่หมดอายุ
|
||||
เฉพาะเมื่อเส้นทางการอัปเกรดยังถูกครอบคลุม หรือบันทึกเหตุผลว่าทำไมจึง
|
||||
ตั้งใจคงไว้
|
||||
4. สร้าง `release/YYYY.M.D` จาก `main` ปัจจุบัน; อย่าทำงานรีลีสปกติ
|
||||
เฉพาะเมื่อเส้นทางอัปเกรดยังคงครอบคลุมอยู่ หรือบันทึกเหตุผลว่าทำไมจึงตั้งใจคงไว้
|
||||
4. สร้าง `release/YYYY.M.D` จาก `main` ปัจจุบัน; อย่าทำงานเผยแพร่ปกติ
|
||||
โดยตรงบน `main`
|
||||
5. เพิ่มเวอร์ชันทุกตำแหน่งที่จำเป็นสำหรับแท็กที่ตั้งใจไว้ รัน
|
||||
`pnpm plugins:sync` เพื่อให้แพ็กเกจ Plugin ที่เผยแพร่ได้ใช้เวอร์ชันรีลีส
|
||||
และเมตาดาต้าความเข้ากันได้ร่วมกัน จากนั้นรัน preflight แบบกำหนดผลลัพธ์ได้ในเครื่อง:
|
||||
5. เพิ่มเวอร์ชันในทุกตำแหน่งที่จำเป็นสำหรับแท็กที่ตั้งใจไว้ รัน
|
||||
`pnpm plugins:sync` เพื่อให้แพ็กเกจ Plugin ที่เผยแพร่ได้ใช้เวอร์ชันรุ่นเผยแพร่
|
||||
และ metadata ความเข้ากันได้ร่วมกัน จากนั้นรัน preflight แบบกำหนดแน่นอนในเครื่อง:
|
||||
`pnpm check:test-types`, `pnpm check:architecture`,
|
||||
`pnpm build && pnpm ui:build`, `pnpm plugins:sync:check` และ
|
||||
`pnpm release:check`
|
||||
6. รัน `OpenClaw NPM Release` พร้อม `preflight_only=true` ก่อนมีแท็ก
|
||||
SHA ของสาขารีลีสแบบเต็ม 40 อักขระอนุญาตให้ใช้สำหรับ preflight
|
||||
เพื่อการตรวจสอบเท่านั้น บันทึก `preflight_run_id` ที่สำเร็จไว้
|
||||
7. เริ่มการทดสอบก่อนรีลีสทั้งหมดด้วย `Full Release Validation` สำหรับ
|
||||
สาขารีลีส แท็ก หรือ SHA commit แบบเต็ม นี่คือ entrypoint แบบแมนนวลหนึ่งเดียว
|
||||
สำหรับกล่องทดสอบรีลีสขนาดใหญ่ทั้งสี่: Vitest, Docker, QA Lab และ Package
|
||||
8. หากการตรวจสอบล้มเหลว ให้แก้บนสาขารีลีสและรันซ้ำเฉพาะไฟล์ เลน งาน workflow,
|
||||
โปรไฟล์แพ็กเกจ provider หรือ allowlist ของโมเดลที่ล้มเหลวที่เล็กที่สุดซึ่ง
|
||||
พิสูจน์การแก้ไขได้ รัน umbrella เต็มซ้ำเฉพาะเมื่อพื้นผิวที่เปลี่ยนแปลงทำให้
|
||||
หลักฐานก่อนหน้าล้าสมัย
|
||||
9. สำหรับ beta ให้แท็ก `vYYYY.M.D-beta.N` จากนั้นรัน `OpenClaw Release Publish` จาก
|
||||
สาขา `release/YYYY.M.D` ที่ตรงกัน โดยจะตรวจสอบ `pnpm plugins:sync:check`,
|
||||
เผยแพร่แพ็กเกจ Plugin ที่เผยแพร่ได้ทั้งหมดไปยัง npm ก่อน เผยแพร่ชุดเดียวกัน
|
||||
ไปยัง ClawHub เป็นลำดับที่สองในรูปแบบ ClawPack npm-pack tarball แล้วจึงโปรโมต
|
||||
artifact preflight ของ OpenClaw npm ที่เตรียมไว้พร้อม dist-tag ที่ตรงกัน หลังจาก
|
||||
เผยแพร่แล้ว ให้รัน package
|
||||
acceptance หลังเผยแพร่กับแพ็กเกจ `openclaw@YYYY.M.D-beta.N` หรือ
|
||||
`openclaw@beta` ที่เผยแพร่แล้ว หาก prerelease ที่ถูก push หรือเผยแพร่แล้วต้องแก้ไข
|
||||
ให้ตัดหมายเลข prerelease ถัดไปที่ตรงกัน; อย่าลบหรือเขียน prerelease เดิมใหม่
|
||||
10. สำหรับ stable ให้ดำเนินต่อเฉพาะหลังจาก beta หรือ release candidate ที่ผ่านการตรวจสอบแล้วมี
|
||||
หลักฐานการตรวจสอบที่จำเป็น การเผยแพร่ npm stable ก็ผ่าน
|
||||
`OpenClaw Release Publish` เช่นกัน โดยใช้ artifact preflight ที่สำเร็จซ้ำผ่าน
|
||||
`preflight_run_id`; ความพร้อมของรีลีส macOS stable ยังต้องมี
|
||||
6. รัน `OpenClaw NPM Release` ด้วย `preflight_only=true` ก่อนมีแท็ก
|
||||
อนุญาตให้ใช้ SHA ของสาขารุ่นเผยแพร่แบบเต็ม 40 อักขระสำหรับ preflight
|
||||
เพื่อการตรวจสอบเท่านั้น บันทึก `preflight_run_id` ที่สำเร็จ
|
||||
7. เริ่มการทดสอบก่อนเผยแพร่ทั้งหมดด้วย `Full Release Validation` สำหรับ
|
||||
สาขารุ่นเผยแพร่ แท็ก หรือ SHA commit แบบเต็ม นี่คือ entrypoint แบบ manual เดียว
|
||||
สำหรับกล่องทดสอบรุ่นเผยแพร่ขนาดใหญ่สี่ชุด: Vitest, Docker, QA Lab และ Package
|
||||
8. หากการตรวจสอบล้มเหลว ให้แก้บนสาขารุ่นเผยแพร่และรันไฟล์ เลน งาน workflow
|
||||
โปรไฟล์แพ็กเกจ provider หรือรายการ allowlist ของโมเดลที่ล้มเหลวที่เล็กที่สุด
|
||||
ซึ่งพิสูจน์การแก้ไขได้ รัน umbrella แบบเต็มอีกครั้งเฉพาะเมื่อพื้นผิวที่เปลี่ยนทำให้
|
||||
หลักฐานก่อนหน้าเก่าเกินใช้
|
||||
9. สำหรับ beta ให้ติดแท็ก `vYYYY.M.D-beta.N` จากนั้นรัน `OpenClaw Release Publish` จาก
|
||||
สาขา `release/YYYY.M.D` ที่ตรงกัน ระบบจะตรวจสอบ `pnpm plugins:sync:check`,
|
||||
เผยแพร่แพ็กเกจ Plugin ที่เผยแพร่ได้ทั้งหมดไปยัง npm ก่อน, เผยแพร่ชุดเดียวกัน
|
||||
ไปยัง ClawHub เป็นลำดับที่สองในรูปแบบ tarball ClawPack npm-pack แล้วจึงโปรโมต
|
||||
artifact preflight ของ OpenClaw npm ที่เตรียมไว้ด้วย dist-tag ที่ตรงกัน หลังเผยแพร่
|
||||
ให้รันการยอมรับแพ็กเกจหลังเผยแพร่กับแพ็กเกจ `openclaw@YYYY.M.D-beta.N` หรือ
|
||||
`openclaw@beta` ที่เผยแพร่แล้ว หาก prerelease ที่ถูก push หรือเผยแพร่แล้วต้องการการแก้ไข
|
||||
ให้ตัดหมายเลข prerelease ถัดไปที่ตรงกัน; อย่าลบหรือเขียน prerelease เก่าใหม่
|
||||
10. สำหรับรุ่นเสถียร ให้ดำเนินการต่อเฉพาะหลังจาก beta หรือ release candidate
|
||||
ที่ตรวจสอบแล้วมีหลักฐานการตรวจสอบที่จำเป็น การเผยแพร่ npm รุ่นเสถียรก็ผ่าน
|
||||
`OpenClaw Release Publish` เช่นกัน โดยนำ artifact preflight ที่สำเร็จกลับมาใช้ผ่าน
|
||||
`preflight_run_id`; ความพร้อมของรุ่นเผยแพร่ macOS เสถียรยังต้องมี
|
||||
`.zip`, `.dmg`, `.dSYM.zip` ที่แพ็กแล้ว และ `appcast.xml` ที่อัปเดตบน `main`
|
||||
11. หลังเผยแพร่ ให้รันตัวตรวจสอบ npm หลังเผยแพร่, Telegram E2E แบบ standalone
|
||||
published-npm ที่เป็นทางเลือกเมื่อคุณต้องการหลักฐานช่องทางหลังเผยแพร่,
|
||||
การโปรโมต dist-tag เมื่อจำเป็น, โน้ตรีลีส/prerelease ของ GitHub จาก
|
||||
ส่วน `CHANGELOG.md` ที่ตรงกันครบถ้วน และขั้นตอนการประกาศรีลีส
|
||||
11. หลังเผยแพร่ ให้รันตัวตรวจสอบหลังเผยแพร่ของ npm, E2E ของ Telegram จาก published-npm
|
||||
แบบ standalone ที่เป็นทางเลือกเมื่อคุณต้องการหลักฐานช่องทางหลังเผยแพร่,
|
||||
การโปรโมต dist-tag เมื่อจำเป็น, บันทึก release/prerelease ของ GitHub จากส่วน
|
||||
`CHANGELOG.md` ที่ตรงกันครบถ้วน และขั้นตอนประกาศรุ่นเผยแพร่
|
||||
|
||||
## การตรวจสอบก่อนออกรีลีส
|
||||
## Release preflight
|
||||
|
||||
- เรียกใช้ `pnpm check:test-types` ก่อนการตรวจสอบก่อนเผยแพร่ เพื่อให้ TypeScript ของการทดสอบยังได้รับการครอบคลุมนอกเหนือจาก gate `pnpm check` ในเครื่องที่เร็วกว่า
|
||||
- เรียกใช้ `pnpm check:architecture` ก่อนการตรวจสอบก่อนเผยแพร่ เพื่อให้การตรวจสอบ import cycle และขอบเขตสถาปัตยกรรมที่กว้างขึ้นผ่านเป็นสีเขียวนอกเหนือจาก gate ในเครื่องที่เร็วกว่า
|
||||
- เรียกใช้ `pnpm build && pnpm ui:build` ก่อน `pnpm release:check` เพื่อให้มีอาร์ติแฟกต์เผยแพร่ `dist/*` และบันเดิล Control UI ที่คาดไว้สำหรับขั้นตอนตรวจสอบ pack
|
||||
- เรียกใช้ `pnpm plugins:sync` หลังการปรับเวอร์ชันที่ root และก่อนติดแท็ก คำสั่งนี้อัปเดตเวอร์ชันแพ็กเกจ Plugin ที่เผยแพร่ได้, metadata ความเข้ากันได้ของ peer/API ของ OpenClaw, metadata การ build และ stub changelog ของ Plugin ให้ตรงกับเวอร์ชันเผยแพร่ของ core `pnpm plugins:sync:check` คือ guard การเผยแพร่แบบไม่แก้ไขข้อมูล; workflow เผยแพร่จะล้มเหลวก่อนมีการแก้ไข registry ใด ๆ หากลืมขั้นตอนนี้
|
||||
- เรียกใช้ workflow แบบ manual `Full Release Validation` ก่อนอนุมัติการเผยแพร่ เพื่อเริ่มกล่องทดสอบก่อนเผยแพร่ทั้งหมดจาก entrypoint เดียว Workflow นี้รับ branch, tag หรือ SHA ของ commit แบบเต็ม, dispatch `CI` แบบ manual และ dispatch `OpenClaw Release Checks` สำหรับ install smoke, package acceptance, ชุดทดสอบ Docker release-path, live/E2E, OpenWebUI, QA Lab parity, Matrix และ lane ของ Telegram เมื่อใช้ `release_profile=full` และ `rerun_group=all` จะเรียกใช้ package Telegram E2E กับอาร์ติแฟกต์ `release-package-under-test` จาก release checks ด้วย ระบุ `npm_telegram_package_spec` หลังเผยแพร่เมื่อ Telegram E2E เดียวกันควรพิสูจน์แพ็กเกจ npm ที่เผยแพร่แล้วด้วย ระบุ `package_acceptance_package_spec` หลังเผยแพร่เมื่อ Package Acceptance ควรเรียกใช้เมทริกซ์ package/update กับแพ็กเกจ npm ที่ส่งมอบแล้ว แทนอาร์ติแฟกต์ที่ build จาก SHA ระบุ `evidence_package_spec` เมื่อรายงานหลักฐานส่วนตัวควรพิสูจน์ว่าการตรวจสอบตรงกับแพ็กเกจ npm ที่เผยแพร่แล้วโดยไม่บังคับใช้ Telegram E2E ตัวอย่าง: `gh workflow run full-release-validation.yml --ref main -f ref=release/YYYY.M.D`
|
||||
- เรียกใช้ workflow แบบ manual `Package Acceptance` เมื่อคุณต้องการหลักฐาน side-channel สำหรับ candidate ของแพ็กเกจขณะที่งานเผยแพร่ยังดำเนินต่อ ใช้ `source=npm` สำหรับ `openclaw@beta`, `openclaw@latest` หรือเวอร์ชันเผยแพร่แบบระบุชัดเจน; `source=ref` เพื่อ pack branch/tag/SHA ของ `package_ref` ที่เชื่อถือได้ด้วย harness `workflow_ref` ปัจจุบัน; `source=url` สำหรับ tarball HTTPS พร้อม SHA-256 ที่บังคับ; หรือ `source=artifact` สำหรับ tarball ที่อัปโหลดโดย GitHub Actions run อื่น Workflow จะแปลง candidate เป็น `package-under-test`, นำ release scheduler ของ Docker E2E มาใช้ซ้ำกับ tarball นั้น และสามารถเรียกใช้ Telegram QA กับ tarball เดียวกันด้วย `telegram_mode=mock-openai` หรือ `telegram_mode=live-frontier` เมื่อ Docker lane ที่เลือกมี `published-upgrade-survivor` อาร์ติแฟกต์แพ็กเกจคือ candidate และ `published_upgrade_survivor_baseline` จะเลือก baseline ที่เผยแพร่แล้ว
|
||||
- เรียกใช้ `pnpm check:test-types` ก่อนการ preflight รีลีส เพื่อให้ TypeScript ของการทดสอบยังคง
|
||||
ครอบคลุมอยู่นอก gate `pnpm check` แบบ local ที่เร็วกว่า
|
||||
- เรียกใช้ `pnpm check:architecture` ก่อนการ preflight รีลีส เพื่อให้การตรวจสอบ import
|
||||
cycle และขอบเขตสถาปัตยกรรมที่กว้างขึ้นเป็นสีเขียวอยู่นอก gate แบบ local ที่เร็วกว่า
|
||||
- เรียกใช้ `pnpm build && pnpm ui:build` ก่อน `pnpm release:check` เพื่อให้อาร์ติแฟกต์รีลีส
|
||||
`dist/*` ที่คาดไว้และบันเดิล Control UI มีอยู่สำหรับขั้นตอนตรวจสอบความถูกต้องของแพ็ก
|
||||
- เรียกใช้ `pnpm plugins:sync` หลังจากเพิ่มเวอร์ชันที่รากและก่อนติดแท็ก โดยจะ
|
||||
อัปเดตเวอร์ชันแพ็กเกจ Plugin ที่เผยแพร่ได้, เมตาดาต้าความเข้ากันได้ของ peer/API ของ OpenClaw,
|
||||
เมตาดาต้า build และสตับ changelog ของ Plugin ให้ตรงกับเวอร์ชันรีลีสหลัก
|
||||
`pnpm plugins:sync:check` คือ guard รีลีสแบบไม่แก้ไขข้อมูล;
|
||||
workflow เผยแพร่จะล้มเหลวก่อนมีการแก้ไข registry ใดๆ หากลืมขั้นตอนนี้
|
||||
- เรียกใช้ workflow แบบ manual `Full Release Validation` ก่อนอนุมัติรีลีสเพื่อ
|
||||
เริ่ม test boxes ก่อนรีลีสทั้งหมดจาก entrypoint เดียว รับ branch,
|
||||
tag หรือ full commit SHA, dispatch `CI` แบบ manual และ dispatch
|
||||
`OpenClaw Release Checks` สำหรับ install smoke, package acceptance, ชุดทดสอบ
|
||||
release-path ของ Docker, live/E2E, OpenWebUI, QA Lab parity, Matrix และ Telegram
|
||||
lanes เมื่อใช้ `release_profile=full` และ `rerun_group=all` จะเรียกใช้ package
|
||||
Telegram E2E กับอาร์ติแฟกต์ `release-package-under-test` จาก release
|
||||
checks ด้วย ระบุ `npm_telegram_package_spec` หลังเผยแพร่เมื่อควรให้ Telegram E2E
|
||||
เดียวกันพิสูจน์แพ็กเกจ npm ที่เผยแพร่แล้วด้วย ระบุ
|
||||
`package_acceptance_package_spec` หลังเผยแพร่เมื่อ Package Acceptance
|
||||
ควรเรียกใช้เมทริกซ์ package/update กับแพ็กเกจ npm ที่ส่งมอบแล้วแทนอาร์ติแฟกต์ที่ build จาก SHA ระบุ
|
||||
`evidence_package_spec` เมื่อรายงานหลักฐานแบบ private ควรพิสูจน์ว่าการตรวจสอบความถูกต้อง
|
||||
ตรงกับแพ็กเกจ npm ที่เผยแพร่แล้วโดยไม่บังคับใช้ Telegram E2E
|
||||
ตัวอย่าง:
|
||||
`gh workflow run full-release-validation.yml --ref main -f ref=release/YYYY.M.D`
|
||||
- เรียกใช้ workflow แบบ manual `Package Acceptance` เมื่อคุณต้องการหลักฐาน side-channel
|
||||
สำหรับตัวเลือกแพ็กเกจระหว่างที่งานรีลีสดำเนินต่อไป ใช้ `source=npm` สำหรับ
|
||||
`openclaw@beta`, `openclaw@latest` หรือเวอร์ชันรีลีสที่ระบุแน่นอน; `source=ref`
|
||||
เพื่อแพ็ก branch/tag/SHA `package_ref` ที่เชื่อถือได้ด้วย harness
|
||||
`workflow_ref` ปัจจุบัน; `source=url` สำหรับ tarball HTTPS พร้อม SHA-256
|
||||
ที่จำเป็น; หรือ `source=artifact` สำหรับ tarball ที่อัปโหลดโดย GitHub
|
||||
Actions run อื่น workflow จะแปลงตัวเลือกเป็น
|
||||
`package-under-test`, ใช้ Docker E2E release scheduler ซ้ำกับ tarball นั้น
|
||||
และสามารถเรียกใช้ Telegram QA กับ tarball เดียวกันด้วย
|
||||
`telegram_mode=mock-openai` หรือ `telegram_mode=live-frontier` เมื่อ Docker
|
||||
lanes ที่เลือกมี `published-upgrade-survivor` อาร์ติแฟกต์แพ็กเกจคือ
|
||||
ตัวเลือก และ `published_upgrade_survivor_baseline` เลือก baseline ที่เผยแพร่แล้ว
|
||||
ตัวอย่าง: `gh workflow run package-acceptance.yml --ref main -f workflow_ref=main -f source=npm -f package_spec=openclaw@beta -f suite_profile=product -f published_upgrade_survivor_baseline=openclaw@2026.4.26 -f telegram_mode=mock-openai`
|
||||
โปรไฟล์ทั่วไป:
|
||||
- `smoke`: lane สำหรับ install/channel/agent, gateway network และ config reload
|
||||
- `package`: lane package/update/plugin ที่อิงอาร์ติแฟกต์โดยตรง โดยไม่มี OpenWebUI หรือ ClawHub live
|
||||
- `product`: โปรไฟล์ package รวมถึงช่องทาง MCP, การล้างข้อมูล cron/subagent, OpenAI web search และ OpenWebUI
|
||||
- `full`: ชิ้นส่วน Docker release-path พร้อม OpenWebUI
|
||||
- `custom`: การเลือก `docker_lanes` แบบระบุชัดเจนสำหรับการ rerun เฉพาะจุด
|
||||
- เรียกใช้ workflow แบบ manual `CI` โดยตรงเมื่อคุณต้องการเพียง coverage ของ CI ปกติแบบเต็มสำหรับ release candidate การ dispatch CI แบบ manual จะข้าม scoping ตามการเปลี่ยนแปลงและบังคับใช้ lane ของ Linux Node shard, bundled-plugin shard, channel contract, ความเข้ากันได้กับ Node 22, `check`, `check-additional`, build smoke, docs checks, Python skills, Windows, macOS, Android และ Control UI i18n
|
||||
- `smoke`: lanes สำหรับ install/channel/agent, เครือข่าย Gateway และโหลด config ใหม่
|
||||
- `package`: lanes package/update/plugin ที่อิงอาร์ติแฟกต์โดยตรง โดยไม่มี OpenWebUI หรือ ClawHub แบบ live
|
||||
- `product`: โปรไฟล์ package รวมกับช่อง MCP, cron/subagent cleanup,
|
||||
OpenAI web search และ OpenWebUI
|
||||
- `full`: ชิ้นส่วน release-path ของ Docker พร้อม OpenWebUI
|
||||
- `custom`: การเลือก `docker_lanes` แบบเจาะจงสำหรับการ rerun ที่มุ่งเน้น
|
||||
- เรียกใช้ workflow แบบ manual `CI` โดยตรงเมื่อคุณต้องการเพียงความครอบคลุมของ CI ปกติแบบเต็ม
|
||||
สำหรับ release candidate การ dispatch CI แบบ manual จะข้ามการกำหนด scope ตามการเปลี่ยนแปลง
|
||||
และบังคับใช้ Linux Node shards, bundled-plugin shards, channel
|
||||
contracts, ความเข้ากันได้กับ Node 22, `check`, `check-additional`, build smoke,
|
||||
docs checks, Python skills, Windows, macOS, Android และ Control UI i18n
|
||||
lanes
|
||||
ตัวอย่าง: `gh workflow run ci.yml --ref release/YYYY.M.D`
|
||||
- เรียกใช้ `pnpm qa:otel:smoke` เมื่อตรวจสอบ telemetry สำหรับการเผยแพร่ คำสั่งนี้ทดสอบ QA-lab ผ่านตัวรับ OTLP/HTTP ในเครื่อง และตรวจสอบชื่อ span ของ trace ที่ส่งออก, attribute ที่ถูกจำกัดขอบเขต และการ redact เนื้อหา/identifier โดยไม่ต้องใช้ Opik, Langfuse หรือตัวรวบรวมภายนอกอื่น
|
||||
- เรียกใช้ `pnpm release:check` ก่อนทุกการเผยแพร่ที่ติดแท็ก
|
||||
- เรียกใช้ `OpenClaw Release Publish` สำหรับลำดับการเผยแพร่ที่แก้ไขข้อมูลหลัง tag มีอยู่แล้ว Dispatch จาก `release/YYYY.M.D` (หรือ `main` เมื่อเผยแพร่ tag ที่เข้าถึงได้จาก main), ส่ง release tag และ `preflight_run_id` ของ OpenClaw npm ที่สำเร็จ และคง scope เผยแพร่ Plugin เริ่มต้น `all-publishable` ไว้ เว้นแต่คุณตั้งใจเรียกใช้การซ่อมแซมแบบเฉพาะจุด Workflow จะจัดลำดับการเผยแพร่ Plugin npm, การเผยแพร่ Plugin ClawHub และการเผยแพร่ OpenClaw npm เพื่อไม่ให้แพ็กเกจ core ถูกเผยแพร่ก่อน Plugin ที่ถูกแยกออกไปภายนอก
|
||||
- ตอนนี้ release checks ทำงานใน workflow แบบ manual แยกต่างหาก:
|
||||
- เรียกใช้ `pnpm qa:otel:smoke` เมื่อตรวจสอบ telemetry ของรีลีส โดยจะทดสอบ
|
||||
QA-lab ผ่านตัวรับ OTLP/HTTP แบบ local และตรวจสอบชื่อ trace
|
||||
span ที่ส่งออก, attributes ที่มีขอบเขต และการ redaction ของ content/identifier โดยไม่ต้องใช้
|
||||
Opik, Langfuse หรือตัวรวบรวมภายนอกอื่น
|
||||
- เรียกใช้ `pnpm release:check` ก่อนรีลีสที่ติดแท็กทุกครั้ง
|
||||
- เรียกใช้ `OpenClaw Release Publish` สำหรับลำดับการเผยแพร่ที่แก้ไขข้อมูลหลังจาก
|
||||
มี tag แล้ว Dispatch จาก `release/YYYY.M.D` (หรือ `main` เมื่อเผยแพร่ tag
|
||||
ที่เข้าถึงได้จาก main), ส่ง release tag และ OpenClaw npm
|
||||
`preflight_run_id` ที่สำเร็จ และคงขอบเขตการเผยแพร่ Plugin ค่าเริ่มต้น
|
||||
`all-publishable` ไว้ เว้นแต่คุณตั้งใจรันการซ่อมเฉพาะจุด workflow
|
||||
จะจัดลำดับการเผยแพร่ npm ของ Plugin, การเผยแพร่ ClawHub ของ Plugin และการเผยแพร่ npm ของ OpenClaw
|
||||
เพื่อไม่ให้แพ็กเกจหลักถูกเผยแพร่ก่อน Plugin ที่แยกออกไปภายนอก
|
||||
- Release checks ตอนนี้รันใน workflow แบบ manual แยกต่างหาก:
|
||||
`OpenClaw Release Checks`
|
||||
- `OpenClaw Release Checks` ยังเรียกใช้ lane QA Lab mock parity รวมถึงโปรไฟล์ Matrix live แบบเร็วและ lane Telegram QA ก่อนอนุมัติการเผยแพร่ Lane live ใช้ environment `qa-live-shared`; Telegram ยังใช้ lease ของ credential Convex CI ด้วย เรียกใช้ workflow แบบ manual `QA-Lab - All Lanes` พร้อม `matrix_profile=all` และ `matrix_shards=true` เมื่อคุณต้องการ inventory ของ Matrix transport, media และ E2EE แบบเต็มพร้อมกัน
|
||||
- การตรวจสอบ runtime สำหรับการติดตั้งและอัปเกรดข้าม OS เป็นส่วนหนึ่งของ `OpenClaw Release Checks` และ `Full Release Validation` สาธารณะ ซึ่งเรียก reusable workflow `.github/workflows/openclaw-cross-os-release-checks-reusable.yml` โดยตรง
|
||||
- การแยกนี้เป็นความตั้งใจ: รักษาเส้นทางเผยแพร่ npm จริงให้สั้น กำหนดผลได้แน่นอน และเน้นอาร์ติแฟกต์ ขณะที่การตรวจสอบ live ที่ช้ากว่าอยู่ใน lane ของตัวเอง เพื่อไม่ให้ถ่วงหรือบล็อกการเผยแพร่
|
||||
- release checks ที่มี secret ควรถูก dispatch ผ่าน `Full Release Validation` หรือจาก workflow ref `main`/release เพื่อให้ logic ของ workflow และ secret ยังถูกควบคุม
|
||||
- `OpenClaw Release Checks` รับ branch, tag หรือ SHA ของ commit แบบเต็ม ตราบใดที่ commit ที่ resolve ได้สามารถเข้าถึงได้จาก branch ของ OpenClaw หรือ release tag
|
||||
- การตรวจสอบก่อนเผยแพร่แบบ validation-only ของ `OpenClaw NPM Release` ยังรับ SHA ของ commit ใน workflow branch ปัจจุบันแบบเต็ม 40 อักขระได้โดยไม่ต้องมี tag ที่ push แล้ว
|
||||
- เส้นทาง SHA นั้นใช้สำหรับการตรวจสอบเท่านั้น และไม่สามารถ promote เป็นการเผยแพร่จริงได้
|
||||
- ในโหมด SHA workflow จะสังเคราะห์ `v<package.json version>` เฉพาะสำหรับการตรวจสอบ metadata ของแพ็กเกจเท่านั้น; การเผยแพร่จริงยังต้องใช้ release tag จริง
|
||||
- ทั้งสอง workflow คงเส้นทางเผยแพร่และ promote จริงไว้บน runner ที่โฮสต์โดย GitHub ขณะที่เส้นทางตรวจสอบแบบไม่แก้ไขข้อมูลสามารถใช้ runner Blacksmith Linux ที่ใหญ่กว่าได้
|
||||
- Workflow นั้นเรียกใช้ `OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_CACHE_TEST=1 pnpm test:live:cache` โดยใช้ workflow secrets ทั้ง `OPENAI_API_KEY` และ `ANTHROPIC_API_KEY`
|
||||
- การตรวจสอบก่อนเผยแพร่ npm ไม่รอ lane release checks ที่แยกต่างหากอีกต่อไป
|
||||
- เรียกใช้ `RELEASE_TAG=vYYYY.M.D node --import tsx scripts/openclaw-npm-release-check.ts` (หรือ tag beta/correction ที่ตรงกัน) ก่อนอนุมัติ
|
||||
- หลังเผยแพร่ npm ให้เรียกใช้ `node --import tsx scripts/openclaw-npm-postpublish-verify.ts YYYY.M.D` (หรือเวอร์ชัน beta/correction ที่ตรงกัน) เพื่อตรวจสอบเส้นทางติดตั้ง registry ที่เผยแพร่แล้วใน temp prefix ใหม่
|
||||
- หลังเผยแพร่ beta ให้เรียกใช้ `OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC=openclaw@YYYY.M.D-beta.N OPENCLAW_NPM_TELEGRAM_CREDENTIAL_SOURCE=convex OPENCLAW_NPM_TELEGRAM_CREDENTIAL_ROLE=ci pnpm test:docker:npm-telegram-live` เพื่อตรวจสอบ onboarding ของแพ็กเกจที่ติดตั้งแล้ว, การตั้งค่า Telegram และ Telegram E2E จริงกับแพ็กเกจ npm ที่เผยแพร่แล้ว โดยใช้พูล credential Telegram แบบ leased ที่ใช้ร่วมกัน maintainer ที่รันครั้งเดียวในเครื่องอาจละ Convex vars และส่ง credential env ทั้งสาม `OPENCLAW_QA_TELEGRAM_*` โดยตรงได้
|
||||
- Maintainer สามารถเรียกใช้การตรวจสอบหลังเผยแพร่เดียวกันจาก GitHub Actions ผ่าน workflow แบบ manual `NPM Telegram Beta E2E` ได้ Workflow นี้ตั้งใจให้เป็น manual-only และไม่ทำงานกับทุก merge
|
||||
- ระบบอัตโนมัติการเผยแพร่ของ maintainer ตอนนี้ใช้ preflight-then-promote:
|
||||
- การเผยแพร่ npm จริงต้องผ่าน `preflight_run_id` ของ npm ที่สำเร็จ
|
||||
- การเผยแพร่ npm จริงต้องถูก dispatch จาก branch `main` หรือ `release/YYYY.M.D` เดียวกันกับ preflight run ที่สำเร็จ
|
||||
- การเผยแพร่ npm แบบ stable มีค่าเริ่มต้นเป็น `beta`
|
||||
- การเผยแพร่ npm แบบ stable สามารถ target `latest` อย่างชัดเจนผ่าน input ของ workflow
|
||||
- การแก้ไข npm dist-tag ที่ใช้ token ตอนนี้อยู่ใน `openclaw/releases-private/.github/workflows/openclaw-npm-dist-tags.yml` ด้วยเหตุผลด้านความปลอดภัย เพราะ `npm dist-tag add` ยังต้องใช้ `NPM_TOKEN` ขณะที่ repo สาธารณะคงการเผยแพร่แบบ OIDC-only
|
||||
- `macOS Release` สาธารณะเป็น validation-only; เมื่อ tag อยู่บน release branch เท่านั้นแต่ workflow ถูก dispatch จาก `main` ให้ตั้งค่า `public_release_branch=release/YYYY.M.D`
|
||||
- การเผยแพร่ mac ส่วนตัวจริงต้องผ่าน `preflight_run_id` และ `validate_run_id` ของ mac ส่วนตัวที่สำเร็จ
|
||||
- เส้นทางเผยแพร่จริง promote อาร์ติแฟกต์ที่เตรียมไว้แทนการ rebuild อีกครั้ง
|
||||
- สำหรับการเผยแพร่แก้ไข stable เช่น `YYYY.M.D-N` ตัวตรวจสอบหลังเผยแพร่ยังตรวจเส้นทางอัปเกรดใน temp-prefix เดียวกันจาก `YYYY.M.D` ไปเป็น `YYYY.M.D-N` เพื่อไม่ให้ release correction ปล่อยให้การติดตั้ง global เก่ายังคงอยู่บน payload stable พื้นฐานโดยเงียบ ๆ
|
||||
- การตรวจสอบก่อนเผยแพร่ npm จะ fail closed เว้นแต่ tarball จะมีทั้ง `dist/control-ui/index.html` และ payload `dist/control-ui/assets/` ที่ไม่ว่าง เพื่อไม่ให้เราส่งมอบ browser dashboard ว่างอีกครั้ง
|
||||
- การตรวจสอบหลังเผยแพร่ยังตรวจว่า entrypoint ของ Plugin ที่เผยแพร่แล้วและ metadata ของแพ็กเกจมีอยู่ใน layout ของ registry ที่ติดตั้งแล้ว การเผยแพร่ที่ขาด payload runtime ของ Plugin จะทำให้ตัวตรวจสอบ postpublish ล้มเหลวและไม่สามารถ promote เป็น `latest` ได้
|
||||
- `pnpm test:install:smoke` ยังบังคับใช้งบประมาณ `unpackedSize` ของ npm pack กับ tarball อัปเดต candidate ด้วย ดังนั้น installer e2e จะจับ pack bloat ที่ไม่ตั้งใจก่อนเส้นทางเผยแพร่ release
|
||||
- หากงานเผยแพร่แตะการวางแผน CI, manifest timing ของ extension หรือเมทริกซ์ทดสอบ extension ให้สร้างใหม่และทบทวนผลลัพธ์เมทริกซ์ `plugin-prerelease-extension-shard` ที่ planner เป็นเจ้าของจาก `.github/workflows/plugin-prerelease.yml` ก่อนอนุมัติ เพื่อไม่ให้ release notes อธิบาย layout CI ที่ล้าสมัย
|
||||
- ความพร้อมของการเผยแพร่ macOS แบบ stable ยังรวมถึงพื้นผิว updater:
|
||||
- GitHub release ต้องลงเอยด้วย `.zip`, `.dmg` และ `.dSYM.zip` ที่บรรจุแพ็กเกจแล้ว
|
||||
- `appcast.xml` บน `main` ต้องชี้ไปยัง zip stable ใหม่หลังเผยแพร่
|
||||
- แอปที่บรรจุแพ็กเกจแล้วต้องคง bundle id ที่ไม่ใช่ debug, URL feed ของ Sparkle ที่ไม่ว่าง และ `CFBundleVersion` ที่เท่ากับหรือสูงกว่า build floor มาตรฐานของ Sparkle สำหรับเวอร์ชันเผยแพร่นั้น
|
||||
- `OpenClaw Release Checks` ยังเรียกใช้ QA Lab mock parity lane พร้อมโปรไฟล์ Matrix
|
||||
แบบ live ที่เร็วและ Telegram QA lane ก่อนอนุมัติรีลีสด้วย live
|
||||
lanes ใช้ environment `qa-live-shared`; Telegram ยังใช้ leases ข้อมูลรับรอง Convex CI
|
||||
ด้วย เรียกใช้ workflow แบบ manual `QA-Lab - All Lanes` ด้วย
|
||||
`matrix_profile=all` และ `matrix_shards=true` เมื่อคุณต้องการ inventory ของ Matrix
|
||||
transport, media และ E2EE แบบเต็มในแบบขนาน
|
||||
- การตรวจสอบ runtime สำหรับการติดตั้งและอัปเกรดข้าม OS เป็นส่วนหนึ่งของ
|
||||
`OpenClaw Release Checks` และ `Full Release Validation` สาธารณะ ซึ่งเรียกใช้
|
||||
reusable workflow
|
||||
`.github/workflows/openclaw-cross-os-release-checks-reusable.yml` โดยตรง
|
||||
- การแยกนี้เป็นความตั้งใจ: รักษาเส้นทางรีลีส npm จริงให้สั้น
|
||||
deterministic และมุ่งเน้นอาร์ติแฟกต์ ขณะที่การตรวจแบบ live ที่ช้ากว่าอยู่ใน lane
|
||||
ของตัวเอง เพื่อไม่ให้หยุดชะงักหรือบล็อกการเผยแพร่
|
||||
- Release checks ที่มี secret ควรถูก dispatch ผ่าน `Full Release
|
||||
Validation` หรือจาก workflow ref ของ `main`/release เพื่อให้ logic ของ workflow และ
|
||||
secrets ยังอยู่ภายใต้การควบคุม
|
||||
- `OpenClaw Release Checks` รับ branch, tag หรือ full commit SHA ตราบใดที่
|
||||
commit ที่ resolve ได้เข้าถึงได้จาก branch ของ OpenClaw หรือ release tag
|
||||
- preflight แบบ validation-only ของ `OpenClaw NPM Release` ยังรับ
|
||||
full 40-character workflow-branch commit SHA ปัจจุบันโดยไม่ต้องมี pushed tag
|
||||
- เส้นทาง SHA นั้นเป็น validation-only และไม่สามารถเลื่อนระดับเป็นการเผยแพร่จริงได้
|
||||
- ในโหมด SHA workflow จะสร้าง `v<package.json version>` เฉพาะสำหรับการตรวจเมตาดาต้า
|
||||
แพ็กเกจเท่านั้น; การเผยแพร่จริงยังต้องใช้ release tag จริง
|
||||
- workflow ทั้งสองคงเส้นทางเผยแพร่และ promotion จริงไว้บน GitHub-hosted
|
||||
runners ขณะที่เส้นทาง validation แบบไม่แก้ไขข้อมูลสามารถใช้ Blacksmith Linux runners
|
||||
ที่ใหญ่กว่าได้
|
||||
- workflow นั้นเรียกใช้
|
||||
`OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_CACHE_TEST=1 pnpm test:live:cache`
|
||||
โดยใช้ workflow secrets ทั้ง `OPENAI_API_KEY` และ `ANTHROPIC_API_KEY`
|
||||
- preflight รีลีส npm จะไม่รอ release checks lane แยกอีกต่อไป
|
||||
- เรียกใช้ `RELEASE_TAG=vYYYY.M.D node --import tsx scripts/openclaw-npm-release-check.ts`
|
||||
(หรือ tag beta/correction ที่ตรงกัน) ก่อนอนุมัติ
|
||||
- หลังจากเผยแพร่ npm ให้เรียกใช้
|
||||
`node --import tsx scripts/openclaw-npm-postpublish-verify.ts YYYY.M.D`
|
||||
(หรือเวอร์ชัน beta/correction ที่ตรงกัน) เพื่อตรวจสอบเส้นทางการติดตั้ง registry
|
||||
ที่เผยแพร่แล้วใน prefix ชั่วคราวใหม่
|
||||
- หลังเผยแพร่ beta ให้เรียกใช้ `OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC=openclaw@YYYY.M.D-beta.N OPENCLAW_NPM_TELEGRAM_CREDENTIAL_SOURCE=convex OPENCLAW_NPM_TELEGRAM_CREDENTIAL_ROLE=ci pnpm test:docker:npm-telegram-live`
|
||||
เพื่อตรวจสอบ onboarding ของแพ็กเกจที่ติดตั้งแล้ว, การตั้งค่า Telegram และ Telegram E2E จริง
|
||||
กับแพ็กเกจ npm ที่เผยแพร่แล้วโดยใช้พูลข้อมูลรับรอง Telegram แบบ leased ที่ใช้ร่วมกัน
|
||||
การรันเฉพาะกิจบนเครื่อง maintainer แบบ local อาจละเว้น Convex vars และส่ง credentials env
|
||||
`OPENCLAW_QA_TELEGRAM_*` ทั้งสามโดยตรงได้
|
||||
- หากต้องการรัน post-publish beta smoke แบบเต็มจากเครื่อง maintainer ให้ใช้ `pnpm release:beta-smoke -- --beta betaN` helper จะรันการตรวจสอบ Parallels npm update/fresh-target, dispatch `NPM Telegram Beta E2E`, poll workflow run ที่ระบุแน่นอน, ดาวน์โหลดอาร์ติแฟกต์ และพิมพ์รายงาน Telegram
|
||||
- Maintainers สามารถรันการตรวจ post-publish เดียวกันจาก GitHub Actions ผ่าน
|
||||
workflow แบบ manual `NPM Telegram Beta E2E` ได้ โดยตั้งใจให้เป็น manual-only และ
|
||||
ไม่รันทุกครั้งที่ merge
|
||||
- ระบบอัตโนมัติสำหรับรีลีสของ maintainer ตอนนี้ใช้ preflight-then-promote:
|
||||
- การเผยแพร่ npm จริงต้องผ่าน npm `preflight_run_id` ที่สำเร็จ
|
||||
- การเผยแพร่ npm จริงต้องถูก dispatch จาก branch `main` หรือ
|
||||
`release/YYYY.M.D` เดียวกับ preflight run ที่สำเร็จ
|
||||
- รีลีส npm แบบ stable ค่าเริ่มต้นคือ `beta`
|
||||
- การเผยแพร่ npm แบบ stable สามารถกำหนดเป้าหมาย `latest` ได้อย่างชัดเจนผ่าน workflow input
|
||||
- การแก้ไข npm dist-tag ด้วย token ตอนนี้อยู่ใน
|
||||
`openclaw/releases-private/.github/workflows/openclaw-npm-dist-tags.yml`
|
||||
เพื่อความปลอดภัย เพราะ `npm dist-tag add` ยังต้องใช้ `NPM_TOKEN` ขณะที่
|
||||
public repo คงการเผยแพร่แบบ OIDC-only
|
||||
- `macOS Release` สาธารณะเป็น validation-only; เมื่อ tag อยู่เฉพาะบน
|
||||
release branch แต่ workflow ถูก dispatch จาก `main` ให้ตั้งค่า
|
||||
`public_release_branch=release/YYYY.M.D`
|
||||
- การเผยแพร่ mac แบบ private จริงต้องผ่าน private mac
|
||||
`preflight_run_id` และ `validate_run_id` ที่สำเร็จ
|
||||
- เส้นทางเผยแพร่จริงจะ promote อาร์ติแฟกต์ที่เตรียมไว้แทนการ rebuild
|
||||
อีกครั้ง
|
||||
- สำหรับรีลีส correction แบบ stable เช่น `YYYY.M.D-N` ตัวตรวจสอบ post-publish
|
||||
จะตรวจเส้นทางอัปเกรด temp-prefix เดียวกันจาก `YYYY.M.D` เป็น `YYYY.M.D-N`
|
||||
ด้วย เพื่อไม่ให้ release corrections ปล่อยให้การติดตั้ง global รุ่นเก่าอยู่บน payload
|
||||
stable ฐานอย่างเงียบๆ
|
||||
- preflight รีลีส npm จะ fail closed เว้นแต่ tarball จะมีทั้ง
|
||||
`dist/control-ui/index.html` และ payload `dist/control-ui/assets/` ที่ไม่ว่าง
|
||||
เพื่อไม่ให้เราส่ง dashboard เบราว์เซอร์ที่ว่างเปล่าอีก
|
||||
- การตรวจสอบ post-publish ยังตรวจว่า entrypoints ของ Plugin ที่เผยแพร่แล้วและ
|
||||
เมตาดาต้าแพ็กเกจมีอยู่ใน layout registry ที่ติดตั้งแล้ว รีลีสที่ส่ง runtime payloads ของ Plugin
|
||||
ขาดหายจะทำให้ตัวตรวจสอบ postpublish ล้มเหลว และ
|
||||
ไม่สามารถ promote เป็น `latest` ได้
|
||||
- `pnpm test:install:smoke` ยังบังคับใช้งบประมาณ `unpackedSize` ของ npm pack กับ
|
||||
candidate update tarball ดังนั้น installer e2e จะจับ pack bloat ที่ไม่ได้ตั้งใจ
|
||||
ได้ก่อนเส้นทางเผยแพร่รีลีส
|
||||
- หากงานรีลีสแตะการวางแผน CI, manifests เวลา extension หรือ
|
||||
เมทริกซ์การทดสอบ extension ให้สร้างใหม่และทบทวน outputs ของเมทริกซ์
|
||||
`plugin-prerelease-extension-shard` ที่ planner เป็นเจ้าของจาก
|
||||
`.github/workflows/plugin-prerelease.yml` ก่อนอนุมัติ เพื่อให้ release notes ไม่
|
||||
อธิบาย layout CI ที่ล้าสมัย
|
||||
- ความพร้อมของรีลีส macOS แบบ stable ยังรวมถึง surfaces ของ updater:
|
||||
- GitHub release ต้องลงเอยด้วย `.zip`, `.dmg` และ `.dSYM.zip` ที่แพ็กแล้ว
|
||||
- `appcast.xml` บน `main` ต้องชี้ไปที่ zip แบบ stable ใหม่หลังเผยแพร่
|
||||
- แอปที่แพ็กแล้วต้องคง bundle id ที่ไม่ใช่ debug, URL feed Sparkle ที่ไม่ว่าง
|
||||
และ `CFBundleVersion` ที่เท่ากับหรือสูงกว่า canonical Sparkle build floor
|
||||
สำหรับเวอร์ชันรีลีสนั้น
|
||||
|
||||
## กล่องทดสอบการเผยแพร่
|
||||
## กล่องทดสอบรีลีส
|
||||
|
||||
`Full Release Validation` คือวิธีที่ operator ใช้เริ่มการทดสอบก่อนเผยแพร่ทั้งหมดจาก entrypoint เดียว สำหรับหลักฐาน commit ที่ pin ไว้บน branch ที่เคลื่อนไหวเร็ว ให้ใช้ helper เพื่อให้ workflow ลูกทุกตัวทำงานจาก branch ชั่วคราวที่ตรึงไว้กับ SHA เป้าหมาย:
|
||||
`Full Release Validation` คือวิธีที่ operators เริ่มการทดสอบก่อนรีลีสทั้งหมดจาก
|
||||
entrypoint เดียว สำหรับหลักฐาน commit ที่ pin ไว้บน branch ที่เปลี่ยนเร็ว ให้ใช้
|
||||
helper เพื่อให้ workflow ลูกทุกตัวรันจาก branch ชั่วคราวที่ตรึงไว้กับ target
|
||||
SHA:
|
||||
|
||||
```bash
|
||||
pnpm ci:full-release --sha <full-sha>
|
||||
```
|
||||
|
||||
Helper จะ push `release-ci/<sha>-...`, dispatch `Full Release Validation` จาก branch นั้นด้วย `ref=<sha>`, ตรวจสอบว่า `headSha` ของ workflow ลูกทุกตัวตรงกับเป้าหมาย แล้วลบ branch ชั่วคราว วิธีนี้หลีกเลี่ยงการพิสูจน์ run ลูกของ `main` ที่ใหม่กว่าโดยไม่ตั้งใจ
|
||||
helper จะ push `release-ci/<sha>-...`, dispatch `Full Release Validation`
|
||||
จาก branch นั้นด้วย `ref=<sha>`, ตรวจสอบว่า `headSha` ของ workflow ลูกทุกตัว
|
||||
ตรงกับ target จากนั้นลบ branch ชั่วคราว วิธีนี้หลีกเลี่ยงการพิสูจน์ child run ของ
|
||||
`main` ที่ใหม่กว่าโดยไม่ตั้งใจ
|
||||
|
||||
สำหรับการตรวจสอบ release branch หรือ tag ให้เรียกใช้จาก workflow ref `main` ที่เชื่อถือได้และส่ง release branch หรือ tag เป็น `ref`:
|
||||
สำหรับการตรวจสอบ release branch หรือ tag ให้รันจาก workflow ref `main` ที่เชื่อถือได้
|
||||
และส่ง release branch หรือ tag เป็น `ref`:
|
||||
|
||||
```bash
|
||||
gh workflow run full-release-validation.yml \
|
||||
@ -179,48 +280,48 @@ gh workflow run full-release-validation.yml \
|
||||
-f evidence_package_spec=openclaw@YYYY.M.D-beta.N
|
||||
```
|
||||
|
||||
เวิร์กโฟลว์จะ resolve target ref, dispatch `CI` แบบ manual ด้วย
|
||||
เวิร์กโฟลว์จะ resolve ref เป้าหมาย, dispatch `CI` แบบ manual ด้วย
|
||||
`target_ref=<release-ref>`, dispatch `OpenClaw Release Checks`, เตรียม artifact
|
||||
หลัก `release-package-under-test` สำหรับการตรวจสอบที่เกี่ยวข้องกับแพ็กเกจ และ
|
||||
dispatch package Telegram E2E แบบ standalone เมื่อ `release_profile=full` พร้อม
|
||||
`rerun_group=all` หรือเมื่อมีการตั้งค่า `npm_telegram_package_spec` จากนั้น `OpenClaw Release
|
||||
Checks` จะกระจายไปยัง install smoke, cross-OS release checks, live/E2E Docker
|
||||
release-path coverage, Package Acceptance พร้อม Telegram package QA, QA Lab
|
||||
parity, live Matrix และ live Telegram การรันแบบเต็มจะยอมรับได้ก็ต่อเมื่อ
|
||||
สรุป `Full Release Validation`
|
||||
แสดงว่า `normal_ci` และ `release_checks` สำเร็จ ในโหมด full/all
|
||||
child `npm_telegram` ต้องสำเร็จด้วย; นอก full/all จะถูกข้าม
|
||||
เว้นแต่จะมีการระบุ `npm_telegram_package_spec` ที่เผยแพร่แล้ว สรุป verifier
|
||||
สุดท้ายมีตารางงานที่ช้าที่สุดสำหรับ child run แต่ละรายการ เพื่อให้ผู้จัดการ release
|
||||
เห็น critical path ปัจจุบันได้โดยไม่ต้องดาวน์โหลด logs
|
||||
ดู [การตรวจสอบ release แบบเต็ม](/th/reference/full-release-validation) สำหรับ
|
||||
stage matrix ฉบับครบถ้วน, ชื่องาน workflow ที่แน่นอน, ความแตกต่างระหว่างโปรไฟล์ stable กับ full,
|
||||
artifacts และ handle สำหรับ rerun แบบเฉพาะจุด
|
||||
Child workflows จะถูก dispatch จาก trusted ref ที่รัน `Full Release
|
||||
Validation` โดยปกติคือ `--ref main` แม้ target `ref` จะชี้ไปที่
|
||||
release branch หรือ tag ที่เก่ากว่า ไม่มี input workflow-ref แยกต่างหากสำหรับ Full Release Validation;
|
||||
ให้เลือก trusted harness โดยเลือก workflow run ref
|
||||
อย่าใช้ `--ref main -f ref=<sha>` สำหรับหลักฐาน commit แบบแน่นอนบน `main` ที่เคลื่อนที่อยู่;
|
||||
raw commit SHA ไม่สามารถเป็น workflow dispatch refs ได้ ดังนั้นให้ใช้
|
||||
`pnpm ci:full-release --sha <sha>` เพื่อสร้าง pinned temporary branch
|
||||
หลัก `release-package-under-test` สำหรับการตรวจสอบฝั่งแพ็กเกจ และ dispatch
|
||||
Telegram E2E แบบแพ็กเกจ standalone เมื่อ `release_profile=full` พร้อม
|
||||
`rerun_group=all` หรือเมื่อมีการตั้งค่า `npm_telegram_package_spec` จากนั้น
|
||||
`OpenClaw Release Checks` จะ fan out ไปยัง install smoke, การตรวจสอบรีลีสข้าม OS,
|
||||
ความครอบคลุม live/E2E Docker ตาม release path, Package Acceptance พร้อม QA
|
||||
แพ็กเกจ Telegram, QA Lab parity, live Matrix และ live Telegram การรันแบบเต็มจะ
|
||||
ยอมรับได้ก็ต่อเมื่อสรุป `Full Release Validation` แสดงว่า `normal_ci` และ
|
||||
`release_checks` สำเร็จแล้วเท่านั้น ในโหมด full/all child `npm_telegram` ต้อง
|
||||
สำเร็จด้วย นอก full/all จะถูกข้าม เว้นแต่จะมีการระบุ
|
||||
`npm_telegram_package_spec` ที่เผยแพร่แล้ว สรุป verifier สุดท้ายมีตารางงานที่
|
||||
ช้าที่สุดสำหรับแต่ละ child run เพื่อให้ผู้จัดการรีลีสเห็น critical path ปัจจุบัน
|
||||
ได้โดยไม่ต้องดาวน์โหลด log
|
||||
ดู [การตรวจสอบรีลีสแบบเต็ม](/th/reference/full-release-validation) สำหรับ stage
|
||||
matrix ฉบับสมบูรณ์, ชื่องาน workflow ที่แน่นอน, ความแตกต่างระหว่างโปรไฟล์ stable
|
||||
กับ full, artifacts และ handle สำหรับ rerun แบบเจาะจง
|
||||
Child workflows จะถูก dispatch จาก ref ที่เชื่อถือได้ซึ่งรัน `Full Release
|
||||
Validation` โดยปกติคือ `--ref main` แม้ว่า `ref` เป้าหมายจะชี้ไปที่ release
|
||||
branch หรือ tag ที่เก่ากว่าก็ตาม ไม่มี input workflow-ref แยกต่างหากสำหรับ Full
|
||||
Release Validation ให้เลือก harness ที่เชื่อถือได้โดยเลือก ref ของ workflow run
|
||||
อย่าใช้ `--ref main -f ref=<sha>` เพื่อพิสูจน์ commit แบบเจาะจงบน `main` ที่เลื่อนไป
|
||||
เรื่อย ๆ เพราะ raw commit SHA ไม่สามารถเป็น workflow dispatch ref ได้ ดังนั้นให้ใช้
|
||||
`pnpm ci:full-release --sha <sha>` เพื่อสร้าง branch ชั่วคราวที่ pin ไว้
|
||||
|
||||
ใช้ `release_profile` เพื่อเลือกขอบเขต live/provider:
|
||||
|
||||
- `minimum`: เส้นทาง OpenAI/core live และ Docker ที่สำคัญต่อ release และเร็วที่สุด
|
||||
- `stable`: minimum พร้อม coverage ของ provider/backend ที่ stable สำหรับอนุมัติ release
|
||||
- `full`: stable พร้อม coverage กว้างของ advisory provider/media
|
||||
- `minimum`: เส้นทาง live และ Docker ที่สำคัญต่อรีลีสของ OpenAI/core ที่เร็วที่สุด
|
||||
- `stable`: minimum พร้อมความครอบคลุม provider/backend แบบ stable สำหรับการอนุมัติรีลีส
|
||||
- `full`: stable พร้อมความครอบคลุม provider/media เชิง advisory ที่กว้างขึ้น
|
||||
|
||||
`OpenClaw Release Checks` ใช้ trusted workflow ref เพื่อ resolve target
|
||||
ref หนึ่งครั้งเป็น `release-package-under-test` และ reuse artifact นั้นทั้งใน
|
||||
release-path Docker checks และ Package Acceptance วิธีนี้ทำให้ทุก
|
||||
box ที่เกี่ยวข้องกับแพ็กเกจใช้ bytes ชุดเดียวกันและหลีกเลี่ยงการ build แพ็กเกจซ้ำ
|
||||
`OpenClaw Release Checks` ใช้ workflow ref ที่เชื่อถือได้เพื่อ resolve ref เป้าหมาย
|
||||
หนึ่งครั้งเป็น `release-package-under-test` และนำ artifact นั้นกลับมาใช้ทั้งในการ
|
||||
ตรวจสอบ Docker ตาม release path และ Package Acceptance สิ่งนี้ทำให้กล่องฝั่ง
|
||||
แพ็กเกจทั้งหมดอยู่บน bytes เดียวกัน และหลีกเลี่ยงการ build แพ็กเกจซ้ำ
|
||||
cross-OS OpenAI install smoke ใช้ `OPENCLAW_CROSS_OS_OPENAI_MODEL` เมื่อมีการตั้งค่า
|
||||
repo/org variable มิฉะนั้นจะใช้ `openai/gpt-5.4` เพราะ lane นี้กำลัง
|
||||
พิสูจน์ package install, onboarding, gateway startup และ live agent turn หนึ่งครั้ง
|
||||
ไม่ใช่การ benchmark default model ที่ช้าที่สุด ส่วน live provider
|
||||
matrix ที่กว้างกว่ายังคงเป็นที่สำหรับ coverage เฉพาะ model
|
||||
ตัวแปร repo/org ไม่เช่นนั้นจะใช้ `openai/gpt-5.4` เพราะ lane นี้พิสูจน์การติดตั้ง
|
||||
แพ็กเกจ, onboarding, การเริ่มต้น Gateway และ agent turn แบบ live หนึ่งครั้ง
|
||||
มากกว่าการ benchmark โมเดล default ที่ช้าที่สุด ส่วน live provider matrix ที่กว้างกว่า
|
||||
ยังคงเป็นที่สำหรับความครอบคลุมเฉพาะโมเดล
|
||||
|
||||
ใช้ variants เหล่านี้ตาม stage ของ release:
|
||||
ใช้ variant เหล่านี้ตาม stage ของรีลีส:
|
||||
|
||||
```bash
|
||||
# Validate an unpublished release candidate branch.
|
||||
@ -250,41 +351,41 @@ gh workflow run full-release-validation.yml \
|
||||
-f npm_telegram_provider_mode=mock-openai
|
||||
```
|
||||
|
||||
อย่าใช้ umbrella แบบเต็มเป็นการ rerun ครั้งแรกหลังแก้แบบเฉพาะจุด หาก box หนึ่ง
|
||||
ล้มเหลว ให้ใช้ child workflow, งาน, Docker lane, package profile, model
|
||||
provider หรือ QA lane ที่ล้มเหลวสำหรับหลักฐานถัดไป รัน umbrella แบบเต็มอีกครั้งก็ต่อเมื่อ
|
||||
การแก้เปลี่ยน release orchestration ที่ใช้ร่วมกัน หรือทำให้หลักฐาน all-box ก่อนหน้า
|
||||
ล้าสมัย verifier สุดท้ายของ umbrella จะตรวจซ้ำ workflow run
|
||||
ids ของ child ที่บันทึกไว้ ดังนั้นหลังจาก child workflow ถูก rerun สำเร็จแล้ว ให้ rerun เฉพาะงานหลัก
|
||||
อย่าใช้ umbrella แบบเต็มเป็น rerun แรกหลังจากการแก้ไขแบบเจาะจง หากกล่องหนึ่งล้มเหลว
|
||||
ให้ใช้ child workflow, job, Docker lane, package profile, model provider หรือ QA
|
||||
lane ที่ล้มเหลวสำหรับ proof ถัดไป รัน umbrella แบบเต็มอีกครั้งเฉพาะเมื่อการแก้ไข
|
||||
เปลี่ยน release orchestration ที่ใช้ร่วมกัน หรือทำให้ evidence แบบทุกกล่องก่อนหน้า
|
||||
ล้าสมัย final verifier ของ umbrella จะตรวจซ้ำ workflow run id ของ child ที่บันทึกไว้
|
||||
ดังนั้นหลังจาก rerun child workflow สำเร็จแล้ว ให้ rerun เฉพาะ parent job
|
||||
`Verify full validation` ที่ล้มเหลว
|
||||
|
||||
สำหรับการกู้คืนแบบมีขอบเขต ให้ส่ง `rerun_group` ไปยัง umbrella `all` คือการรัน
|
||||
release-candidate จริง, `ci` รันเฉพาะ child ของ CI ปกติ, `plugin-prerelease`
|
||||
รันเฉพาะ child ของ Plugin เฉพาะ release, `release-checks` รัน release
|
||||
box ทุกตัว และ release groups ที่แคบกว่าคือ `install-smoke`, `cross-os`,
|
||||
`live-e2e`, `package`, `qa`, `qa-parity`, `qa-live` และ `npm-telegram`
|
||||
การ rerun `npm-telegram` แบบเฉพาะจุดต้องมี `npm_telegram_package_spec`; การรัน full/all
|
||||
ที่มี `release_profile=full` ใช้ release-checks package artifact
|
||||
release-candidate จริง, `ci` รันเฉพาะ normal CI child, `plugin-prerelease` รันเฉพาะ
|
||||
plugin child สำหรับรีลีสเท่านั้น, `release-checks` รันทุก release box และกลุ่มรีลีส
|
||||
ที่แคบกว่าคือ `install-smoke`, `cross-os`, `live-e2e`, `package`, `qa`,
|
||||
`qa-parity`, `qa-live` และ `npm-telegram` การ rerun `npm-telegram` แบบเจาะจงต้องมี
|
||||
`npm_telegram_package_spec`; การรัน full/all ด้วย `release_profile=full` ใช้ package
|
||||
artifact ของ release-checks
|
||||
|
||||
### Vitest
|
||||
|
||||
Vitest box คือ child workflow `CI` แบบ manual Manual CI ตั้งใจ
|
||||
ข้าม changed scoping และบังคับ test graph ปกติสำหรับ release
|
||||
candidate: Linux Node shards, bundled-plugin shards, channel contracts, Node 22
|
||||
compatibility, `check`, `check-additional`, build smoke, docs checks, Python
|
||||
skills, Windows, macOS, Android และ Control UI i18n
|
||||
กล่อง Vitest คือ child workflow `CI` แบบ manual Manual CI ตั้งใจ bypass changed
|
||||
scoping และบังคับใช้กราฟทดสอบปกติสำหรับ release candidate: Linux Node shards,
|
||||
bundled-plugin shards, channel contracts, ความเข้ากันได้กับ Node 22, `check`,
|
||||
`check-additional`, build smoke, docs checks, Python skills, Windows, macOS,
|
||||
Android และ Control UI i18n
|
||||
|
||||
ใช้ box นี้เพื่อตอบว่า "source tree ผ่านชุดทดสอบปกติแบบเต็มหรือไม่?"
|
||||
นี่ไม่เหมือนกับการตรวจสอบผลิตภัณฑ์ตาม release-path หลักฐานที่ควรเก็บ:
|
||||
ใช้กล่องนี้เพื่อตอบว่า "source tree ผ่านชุดทดสอบปกติแบบเต็มหรือไม่?"
|
||||
มันไม่เหมือนกับการตรวจสอบผลิตภัณฑ์ตาม release path หลักฐานที่ควรเก็บ:
|
||||
|
||||
- สรุป `Full Release Validation` ที่แสดง URL ของ `CI` run ที่ถูก dispatch
|
||||
- `CI` run เป็นสีเขียวบน target SHA ที่แน่นอน
|
||||
- ชื่อ shard ที่ล้มเหลวหรือช้าจากงาน CI เมื่อตรวจสอบ regression
|
||||
- Vitest timing artifacts เช่น `.artifacts/vitest-shard-timings.json` เมื่อ
|
||||
- สรุป `Full Release Validation` ที่แสดง URL ของ `CI` run ที่ dispatch แล้ว
|
||||
- `CI` run เป็นสีเขียวบน SHA เป้าหมายที่แน่นอน
|
||||
- ชื่อ shard ที่ล้มเหลวหรือช้าจากงาน CI เมื่อสืบสวน regression
|
||||
- timing artifacts ของ Vitest เช่น `.artifacts/vitest-shard-timings.json` เมื่อ
|
||||
run ต้องการการวิเคราะห์ประสิทธิภาพ
|
||||
|
||||
รัน manual CI โดยตรงเฉพาะเมื่อ release ต้องการ CI ปกติที่ deterministic แต่
|
||||
ไม่ต้องใช้ Docker, QA Lab, live, cross-OS หรือ package boxes:
|
||||
รัน manual CI โดยตรงเฉพาะเมื่อรีลีสต้องการ normal CI แบบ deterministic แต่ไม่ต้องการ
|
||||
กล่อง Docker, QA Lab, live, cross-OS หรือ package:
|
||||
|
||||
```bash
|
||||
gh workflow run ci.yml --ref main -f target_ref=release/YYYY.M.D
|
||||
@ -292,111 +393,110 @@ gh workflow run ci.yml --ref main -f target_ref=release/YYYY.M.D
|
||||
|
||||
### Docker
|
||||
|
||||
Docker box อยู่ใน `OpenClaw Release Checks` ผ่าน
|
||||
กล่อง Docker อยู่ใน `OpenClaw Release Checks` ผ่าน
|
||||
`openclaw-live-and-e2e-checks-reusable.yml` รวมถึง workflow `install-smoke`
|
||||
แบบ release-mode โดยตรวจสอบ release candidate ผ่านสภาพแวดล้อม Docker
|
||||
แบบ packaged แทนที่จะใช้เฉพาะการทดสอบระดับ source
|
||||
ในโหมดรีลีส มันตรวจสอบ release candidate ผ่านสภาพแวดล้อม Docker แบบแพ็กเกจ
|
||||
แทนที่จะเป็นเฉพาะการทดสอบระดับซอร์ส
|
||||
|
||||
Release Docker coverage รวมถึง:
|
||||
ความครอบคลุม Docker ของรีลีสประกอบด้วย:
|
||||
|
||||
- install smoke แบบเต็มโดยเปิดใช้ Bun global install smoke ที่ช้า
|
||||
- การเตรียม/reuse root Dockerfile smoke image ตาม target SHA พร้อมงาน QR,
|
||||
root/gateway และ installer/Bun smoke ที่รันเป็น install-smoke shards แยกกัน
|
||||
- repository E2E lanes
|
||||
- release-path Docker chunks: `core`, `package-update-openai`,
|
||||
- full install smoke พร้อมเปิดใช้ slow Bun global install smoke
|
||||
- การเตรียม/นำ smoke image ของ root Dockerfile กลับมาใช้ตาม SHA เป้าหมาย โดยมีงาน QR,
|
||||
root/gateway และ installer/Bun smoke รันเป็น install-smoke shards แยกกัน
|
||||
- lane E2E ของ repository
|
||||
- chunk Docker ตาม release path: `core`, `package-update-openai`,
|
||||
`package-update-anthropic`, `package-update-core`, `plugins-runtime-plugins`,
|
||||
`plugins-runtime-services`,
|
||||
`plugins-runtime-install-a`, `plugins-runtime-install-b`,
|
||||
`plugins-runtime-install-c`, `plugins-runtime-install-d`,
|
||||
`plugins-runtime-install-e`, `plugins-runtime-install-f`,
|
||||
`plugins-runtime-install-g` และ `plugins-runtime-install-h`
|
||||
- OpenWebUI coverage ภายใน chunk `plugins-runtime-services` เมื่อมีการร้องขอ
|
||||
- lane ติดตั้ง/ถอนติดตั้ง bundled plugin แบบแยก
|
||||
- ความครอบคลุม OpenWebUI ภายใน chunk `plugins-runtime-services` เมื่อมีการร้องขอ
|
||||
- lane install/uninstall ของ bundled Plugin ที่ split แล้ว
|
||||
`bundled-plugin-install-uninstall-0` ถึง
|
||||
`bundled-plugin-install-uninstall-23`
|
||||
- ชุด live/E2E provider และ Docker live model coverage เมื่อ release checks
|
||||
- ชุด provider live/E2E และความครอบคลุมโมเดล Docker live เมื่อ release checks
|
||||
รวม live suites
|
||||
|
||||
ใช้ Docker artifacts ก่อน rerun release-path scheduler อัปโหลด
|
||||
`.artifacts/docker-tests/` พร้อม lane logs, `summary.json`, `failures.json`,
|
||||
phase timings, scheduler plan JSON และคำสั่ง rerun สำหรับการกู้คืนแบบเฉพาะจุด
|
||||
ให้ใช้ `docker_lanes=<lane[,lane]>` บน workflow live/E2E แบบ reusable แทน
|
||||
การ rerun release chunks ทั้งหมด คำสั่ง rerun ที่สร้างขึ้นจะรวม
|
||||
`package_artifact_run_id` ก่อนหน้าและ prepared Docker image inputs เมื่อมี เพื่อให้
|
||||
lane ที่ล้มเหลวสามารถ reuse tarball และ GHCR images ชุดเดียวกันได้
|
||||
`.artifacts/docker-tests/` พร้อม log ของ lane, `summary.json`, `failures.json`,
|
||||
phase timings, scheduler plan JSON และคำสั่ง rerun สำหรับการกู้คืนแบบเจาะจง ให้ใช้
|
||||
`docker_lanes=<lane[,lane]>` บน reusable live/E2E workflow แทนการ rerun release
|
||||
chunks ทั้งหมด คำสั่ง rerun ที่สร้างขึ้นจะรวม `package_artifact_run_id` ก่อนหน้าและ
|
||||
input ของ Docker image ที่เตรียมไว้เมื่อมี เพื่อให้ lane ที่ล้มเหลวสามารถใช้ tarball
|
||||
และ GHCR images เดิมซ้ำได้
|
||||
|
||||
### QA Lab
|
||||
|
||||
QA Lab box เป็นส่วนหนึ่งของ `OpenClaw Release Checks` เช่นกัน เป็น gate ด้าน
|
||||
พฤติกรรม agentic และระดับ channel สำหรับ release ซึ่งแยกจาก Vitest และกลไกแพ็กเกจ
|
||||
ของ Docker
|
||||
กล่อง QA Lab เป็นส่วนหนึ่งของ `OpenClaw Release Checks` เช่นกัน มันคือ release gate
|
||||
ด้านพฤติกรรม agentic และระดับ channel แยกจากกลไกแพ็กเกจของ Vitest และ Docker
|
||||
|
||||
Release QA Lab coverage รวมถึง:
|
||||
ความครอบคลุม QA Lab ของรีลีสประกอบด้วย:
|
||||
|
||||
- mock parity lane ที่เปรียบเทียบ OpenAI candidate lane กับ baseline Opus 4.6
|
||||
- mock parity lane ที่เปรียบเทียบ lane candidate ของ OpenAI กับ baseline Opus 4.6
|
||||
โดยใช้ agentic parity pack
|
||||
- fast live Matrix QA profile ที่ใช้ environment `qa-live-shared`
|
||||
- live Telegram QA lane ที่ใช้ Convex CI credential leases
|
||||
- `pnpm qa:otel:smoke` เมื่อ release telemetry ต้องการหลักฐาน local ที่ชัดเจน
|
||||
- โปรไฟล์ fast live Matrix QA ที่ใช้ environment `qa-live-shared`
|
||||
- live Telegram QA lane ที่ใช้ credential lease ของ Convex CI
|
||||
- `pnpm qa:otel:smoke` เมื่อ release telemetry ต้องการ local proof ที่ชัดเจน
|
||||
|
||||
ใช้ box นี้เพื่อตอบว่า "release ทำงานถูกต้องในสถานการณ์ QA และ
|
||||
live channel flows หรือไม่?" เก็บ artifact URLs สำหรับ parity, Matrix และ Telegram
|
||||
lanes เมื่ออนุมัติ release Full Matrix coverage ยังมีให้ใช้งานเป็น
|
||||
QA-Lab run แบบ manual sharded ไม่ใช่ lane สำคัญต่อ release ตามค่าเริ่มต้น
|
||||
ใช้กล่องนี้เพื่อตอบว่า "รีลีสทำงานถูกต้องในสถานการณ์ QA และ flow ของ live channel
|
||||
หรือไม่?" เก็บ URL artifact สำหรับ lane parity, Matrix และ Telegram เมื่ออนุมัติรีลีส
|
||||
ความครอบคลุม Matrix แบบเต็มยังมีให้เป็น QA-Lab run แบบ sharded manual แทนที่จะเป็น
|
||||
lane สำคัญต่อรีลีสตาม default
|
||||
|
||||
### แพ็กเกจ
|
||||
### Package
|
||||
|
||||
Package box คือ installable-product gate ซึ่งรองรับโดย
|
||||
กล่อง Package คือ gate สำหรับผลิตภัณฑ์ที่ติดตั้งได้ รองรับโดย
|
||||
`Package Acceptance` และ resolver
|
||||
`scripts/resolve-openclaw-package-candidate.mjs` resolver จะ normalize
|
||||
candidate ให้เป็น tarball `package-under-test` ที่ Docker E2E ใช้, ตรวจสอบ
|
||||
package inventory, บันทึก package version และ SHA-256 และแยก workflow harness ref
|
||||
ออกจาก package source ref
|
||||
`scripts/resolve-openclaw-package-candidate.mjs` resolver จะ normalize candidate
|
||||
เป็น tarball `package-under-test` ที่ Docker E2E ใช้, validate package inventory,
|
||||
บันทึก version และ SHA-256 ของแพ็กเกจ และแยก workflow harness ref ออกจาก package
|
||||
source ref
|
||||
|
||||
แหล่ง candidate ที่รองรับ:
|
||||
|
||||
- `source=npm`: `openclaw@beta`, `openclaw@latest` หรือเวอร์ชัน OpenClaw release ที่แน่นอน
|
||||
- `source=ref`: pack branch, tag หรือ full commit SHA ของ `package_ref` ที่ trusted
|
||||
- `source=npm`: `openclaw@beta`, `openclaw@latest` หรือ version รีลีส OpenClaw ที่แน่นอน
|
||||
- `source=ref`: pack branch, tag หรือ full commit SHA ของ `package_ref` ที่เชื่อถือได้
|
||||
ด้วย harness `workflow_ref` ที่เลือก
|
||||
- `source=url`: ดาวน์โหลด HTTPS `.tgz` พร้อม `package_sha256` ที่จำเป็น
|
||||
- `source=artifact`: reuse `.tgz` ที่อัปโหลดโดย GitHub Actions run อื่น
|
||||
- `source=artifact`: ใช้ `.tgz` ที่อัปโหลดโดย GitHub Actions run อื่นซ้ำ
|
||||
|
||||
`OpenClaw Release Checks` รัน Package Acceptance ด้วย `source=artifact`,
|
||||
prepared release package artifact, `suite_profile=custom`,
|
||||
`OpenClaw Release Checks` รัน Package Acceptance ด้วย `source=artifact`, package
|
||||
artifact ของรีลีสที่เตรียมไว้, `suite_profile=custom`,
|
||||
`docker_lanes=doctor-switch update-channel-switch upgrade-survivor published-upgrade-survivor plugins-offline plugin-update`,
|
||||
`published_upgrade_survivor_baselines=all-since-2026.4.23`,
|
||||
`published_upgrade_survivor_scenarios=reported-issues` และ
|
||||
`telegram_mode=mock-openai` Package Acceptance ทำให้ migration, update, การ cleanup
|
||||
stale plugin dependency, offline plugin fixtures, plugin update และ Telegram
|
||||
package QA ใช้ tarball ที่ resolve แล้วชุดเดียวกัน upgrade matrix ครอบคลุมทุก stable npm-published baseline ตั้งแต่ `2026.4.23` ถึง `latest`; ใช้
|
||||
Package Acceptance ด้วย `source=npm` สำหรับ candidate ที่ ship ไปแล้ว หรือ
|
||||
`source=ref`/`source=artifact` สำหรับ tarball npm local ที่มี SHA รองรับก่อน
|
||||
publish นี่คือสิ่งทดแทนแบบ GitHub-native
|
||||
สำหรับ package/update coverage ส่วนใหญ่ที่ก่อนหน้านี้ต้องใช้
|
||||
Parallels Cross-OS release checks ยังสำคัญสำหรับ onboarding, installer และ
|
||||
platform behavior เฉพาะ OS แต่การตรวจสอบผลิตภัณฑ์ package/update ควร
|
||||
เลือกใช้ Package Acceptance
|
||||
`telegram_mode=mock-openai` Package Acceptance เก็บ migration, update, การล้าง
|
||||
dependency ของ Plugin เก่า, fixture ของ Plugin แบบ offline, การอัปเดต Plugin และ
|
||||
Telegram package QA ไว้กับ tarball ที่ resolve แล้วเดียวกัน upgrade matrix ครอบคลุม
|
||||
baseline stable ที่เผยแพร่บน npm ทุกตัวตั้งแต่ `2026.4.23` ถึง `latest`; ใช้
|
||||
Package Acceptance ด้วย `source=npm` สำหรับ candidate ที่ ship แล้ว หรือ
|
||||
`source=ref`/`source=artifact` สำหรับ npm tarball ในเครื่องที่มี SHA รองรับก่อน publish
|
||||
มันคือสิ่งทดแทนแบบ GitHub-native สำหรับความครอบคลุม package/update ส่วนใหญ่ที่ก่อนหน้า
|
||||
ต้องใช้ Parallels การตรวจสอบรีลีสข้าม OS ยังสำคัญสำหรับ onboarding, installer และ
|
||||
พฤติกรรมเฉพาะ platform แต่การตรวจสอบผลิตภัณฑ์ด้าน package/update ควรเลือกใช้
|
||||
Package Acceptance
|
||||
|
||||
checklist มาตรฐานสำหรับการตรวจสอบ update และ Plugin คือ
|
||||
[การทดสอบ updates และ plugins](/th/help/testing-updates-plugins) ใช้เมื่อ
|
||||
ตัดสินใจว่า local, Docker, Package Acceptance หรือ release-check lane ใดพิสูจน์
|
||||
การติดตั้ง/update Plugin, doctor cleanup หรือการเปลี่ยน migration ของ published-package ได้
|
||||
การ exhaustive published update migration จากทุกแพ็กเกจ stable `2026.4.23+` เป็น
|
||||
workflow `Update Migration` แบบ manual แยกต่างหาก ไม่ได้เป็นส่วนหนึ่งของ Full Release CI
|
||||
checklist canonical สำหรับการตรวจสอบ update และ Plugin คือ
|
||||
[การทดสอบ updates และ plugins](/th/help/testing-updates-plugins) ใช้เมื่อจะตัดสินว่า
|
||||
lane แบบ local, Docker, Package Acceptance หรือ release-check ใดพิสูจน์การ
|
||||
ติดตั้ง/อัปเดต Plugin, การล้างด้วย doctor หรือการเปลี่ยนแปลง migration ของแพ็กเกจที่
|
||||
เผยแพร่แล้ว การ migration อัปเดตที่เผยแพร่แบบละเอียดจากทุกแพ็กเกจ stable
|
||||
`2026.4.23+` เป็น workflow manual `Update Migration` แยกต่างหาก ไม่ใช่ส่วนหนึ่งของ
|
||||
Full Release CI
|
||||
|
||||
ความผ่อนปรน legacy package-acceptance ถูกจำกัดเวลาด้วยเจตนา แพ็กเกจจนถึง
|
||||
`2026.4.25` อาจใช้ compatibility path สำหรับ metadata gaps ที่เผยแพร่ไปยัง
|
||||
npm แล้ว: private QA inventory entries ที่หายไปจาก tarball, ไม่มี
|
||||
`gateway install --wrapper`, ไม่มี patch files ใน git fixture ที่ได้จาก tarball,
|
||||
ไม่มี `update.channel` ที่ persisted, ตำแหน่ง install-record ของ legacy plugin,
|
||||
ไม่มี marketplace install-record persistence และ config metadata
|
||||
migration ระหว่าง `plugins update` แพ็กเกจ `2026.4.26` ที่เผยแพร่แล้วอาจ warn
|
||||
สำหรับไฟล์ local build metadata stamp ที่ ship ไปแล้ว แพ็กเกจที่ใหม่กว่า
|
||||
ต้องเป็นไปตาม package contracts สมัยใหม่; gaps เดียวกันนั้นจะทำให้ release
|
||||
validation ล้มเหลว
|
||||
ความผ่อนปรน legacy package-acceptance ถูกจำกัดเวลาโดยตั้งใจ แพ็กเกจจนถึง
|
||||
`2026.4.25` อาจใช้ compatibility path สำหรับช่องว่าง metadata ที่เผยแพร่ไปยัง npm
|
||||
แล้ว: รายการ inventory QA ส่วนตัวที่หายไปจาก tarball, `gateway install --wrapper`
|
||||
ที่หายไป, ไฟล์ patch ที่หายไปใน git fixture ที่ได้จาก tarball, `update.channel` ที่
|
||||
persist หายไป, ตำแหน่ง legacy plugin install-record, persistence ของ marketplace
|
||||
install-record ที่หายไป และการ migration config metadata ระหว่าง `plugins update`
|
||||
แพ็กเกจ `2026.4.26` ที่เผยแพร่แล้วอาจ warn สำหรับไฟล์ stamp metadata ของ local build
|
||||
ที่ ship ไปแล้ว แพ็กเกจหลังจากนั้นต้องเป็นไปตาม package contracts สมัยใหม่
|
||||
ช่องว่างเดียวกันเหล่านั้นจะทำให้ release validation ล้มเหลว
|
||||
|
||||
ใช้โปรไฟล์ Package Acceptance ที่กว้างขึ้นเมื่อคำถามของ release เกี่ยวกับ
|
||||
แพ็กเกจที่ติดตั้งได้จริง:
|
||||
ใช้โปรไฟล์ Package Acceptance ที่กว้างขึ้นเมื่อคำถามของรีลีสเกี่ยวกับแพ็กเกจที่
|
||||
ติดตั้งได้จริง:
|
||||
|
||||
```bash
|
||||
gh workflow run package-acceptance.yml \
|
||||
@ -410,32 +510,32 @@ gh workflow run package-acceptance.yml \
|
||||
|
||||
โปรไฟล์แพ็กเกจทั่วไป:
|
||||
|
||||
- `smoke`: เลนการติดตั้งแพ็กเกจ/ช่องทาง/เอเจนต์แบบเร็ว เครือข่าย Gateway และการโหลดการกำหนดค่าใหม่
|
||||
- `package`: สัญญาการติดตั้ง/อัปเดต/แพ็กเกจ Plugin โดยไม่มี ClawHub แบบไลฟ์; นี่เป็นค่าเริ่มต้นของการตรวจสอบรีลีส
|
||||
- `product`: `package` รวมกับช่องทาง MCP, การล้าง cron/subagent, การค้นหาเว็บ OpenAI และ OpenWebUI
|
||||
- `full`: ส่วนย่อยของเส้นทางรีลีส Docker พร้อม OpenWebUI
|
||||
- `smoke`: เลนติดตั้งแพ็กเกจ/ช่องทาง/เอเจนต์แบบเร็ว, เครือข่าย Gateway, และโหลดการกำหนดค่าใหม่
|
||||
- `package`: สัญญาการติดตั้ง/อัปเดต/แพ็กเกจ Plugin โดยไม่มี ClawHub แบบสด; นี่คือค่าเริ่มต้นของการตรวจสอบรีลีส
|
||||
- `product`: `package` รวมกับช่องทาง MCP, การล้าง cron/subagent, การค้นหาเว็บ OpenAI, และ OpenWebUI
|
||||
- `full`: ส่วนของเส้นทางรีลีส Docker พร้อม OpenWebUI
|
||||
- `custom`: รายการ `docker_lanes` ที่แน่นอนสำหรับการรันซ้ำแบบเจาะจง
|
||||
|
||||
สำหรับหลักฐาน Telegram ของแพ็กเกจตัวเลือก ให้เปิดใช้ `telegram_mode=mock-openai` หรือ
|
||||
`telegram_mode=live-frontier` บน Package Acceptance เวิร์กโฟลว์จะส่ง tarball
|
||||
`package-under-test` ที่แก้ค่าแล้วเข้าไปยังเลน Telegram; เวิร์กโฟลว์ Telegram
|
||||
แบบสแตนด์อโลนยังคงรับสเปก npm ที่เผยแพร่แล้วสำหรับการตรวจสอบหลังเผยแพร่
|
||||
`package-under-test` ที่แก้ค่าแล้วเข้าสู่เลน Telegram; เวิร์กโฟลว์ Telegram แบบสแตนด์อโลน
|
||||
ยังรับสเปก npm ที่เผยแพร่แล้วสำหรับการตรวจสอบหลังเผยแพร่
|
||||
|
||||
## ระบบอัตโนมัติสำหรับการเผยแพร่รีลีส
|
||||
## การเผยแพร่รีลีสอัตโนมัติ
|
||||
|
||||
`OpenClaw Release Publish` คือจุดเข้าเผยแพร่แบบแก้ไขสถานะปกติ โดยจะจัดลำดับ
|
||||
เวิร์กโฟลว์ trusted-publisher ตามที่รีลีสต้องการ:
|
||||
`OpenClaw Release Publish` คือจุดเริ่มต้นการเผยแพร่แบบเปลี่ยนแปลงสถานะตามปกติ ซึ่ง
|
||||
ประสานเวิร์กโฟลว์ trusted-publisher ตามลำดับที่รีลีสต้องใช้:
|
||||
|
||||
1. เช็กเอาต์แท็กรีลีสและแก้ค่า commit SHA ของแท็กนั้น
|
||||
2. ตรวจสอบว่าแท็กสามารถเข้าถึงได้จาก `main` หรือ `release/*`
|
||||
2. ตรวจสอบว่าแท็กเข้าถึงได้จาก `main` หรือ `release/*`
|
||||
3. รัน `pnpm plugins:sync:check`
|
||||
4. เรียกใช้ `Plugin NPM Release` ด้วย `publish_scope=all-publishable` และ
|
||||
4. Dispatch `Plugin NPM Release` ด้วย `publish_scope=all-publishable` และ
|
||||
`ref=<release-sha>`
|
||||
5. เรียกใช้ `Plugin ClawHub Release` ด้วยสโคปและ SHA เดียวกัน
|
||||
6. เรียกใช้ `OpenClaw NPM Release` ด้วยแท็กรีลีส, npm dist-tag และ
|
||||
5. Dispatch `Plugin ClawHub Release` ด้วย scope และ SHA เดียวกัน
|
||||
6. Dispatch `OpenClaw NPM Release` ด้วยแท็กรีลีส, npm dist-tag, และ
|
||||
`preflight_run_id` ที่บันทึกไว้
|
||||
|
||||
ตัวอย่างการเผยแพร่ Beta:
|
||||
ตัวอย่างการเผยแพร่เบต้า:
|
||||
|
||||
```bash
|
||||
gh workflow run openclaw-release-publish.yml \
|
||||
@ -445,7 +545,7 @@ gh workflow run openclaw-release-publish.yml \
|
||||
-f npm_dist_tag=beta
|
||||
```
|
||||
|
||||
เผยแพร่ Stable ไปยัง beta dist-tag เริ่มต้น:
|
||||
การเผยแพร่เสถียรไปยัง dist-tag เบต้าเริ่มต้น:
|
||||
|
||||
```bash
|
||||
gh workflow run openclaw-release-publish.yml \
|
||||
@ -455,7 +555,7 @@ gh workflow run openclaw-release-publish.yml \
|
||||
-f npm_dist_tag=beta
|
||||
```
|
||||
|
||||
การเลื่อน Stable ไปยัง `latest` โดยตรงต้องระบุอย่างชัดเจน:
|
||||
การโปรโมตรีลีสเสถียรตรงไปยัง `latest` ต้องระบุอย่างชัดเจน:
|
||||
|
||||
```bash
|
||||
gh workflow run openclaw-release-publish.yml \
|
||||
@ -466,88 +566,88 @@ gh workflow run openclaw-release-publish.yml \
|
||||
```
|
||||
|
||||
ใช้เวิร์กโฟลว์ระดับล่าง `Plugin NPM Release` และ `Plugin ClawHub Release`
|
||||
เฉพาะสำหรับงานซ่อมแซมหรือเผยแพร่ซ้ำแบบเจาะจงเท่านั้น สำหรับการซ่อมแซม Plugin
|
||||
ที่เลือก ให้ส่ง `plugin_publish_scope=selected` และ `plugins=@openclaw/name` ไปยัง
|
||||
`OpenClaw Release Publish` หรือเรียกใช้เวิร์กโฟลว์ลูกโดยตรงเมื่อไม่ควรเผยแพร่
|
||||
เฉพาะสำหรับงานซ่อมแซมหรือเผยแพร่ซ้ำแบบเจาะจงเท่านั้น สำหรับการซ่อมแซม Plugin ที่เลือกไว้ ให้ส่ง
|
||||
`plugin_publish_scope=selected` และ `plugins=@openclaw/name` ไปยัง
|
||||
`OpenClaw Release Publish` หรือ dispatch เวิร์กโฟลว์ลูกโดยตรงเมื่อไม่ควรเผยแพร่
|
||||
แพ็กเกจ OpenClaw
|
||||
|
||||
## อินพุตของเวิร์กโฟลว์ NPM
|
||||
## อินพุตเวิร์กโฟลว์ NPM
|
||||
|
||||
`OpenClaw NPM Release` รับอินพุตที่ควบคุมโดยผู้ปฏิบัติงานเหล่านี้:
|
||||
`OpenClaw NPM Release` รับอินพุตที่ผู้ปฏิบัติงานควบคุมได้ดังนี้:
|
||||
|
||||
- `tag`: แท็กรีลีสที่จำเป็น เช่น `v2026.4.2`, `v2026.4.2-1` หรือ
|
||||
`v2026.4.2-beta.1`; เมื่อ `preflight_only=true` ค่านี้อาจเป็น workflow-branch
|
||||
commit SHA แบบครบ 40 อักขระปัจจุบันสำหรับ preflight แบบตรวจสอบเท่านั้นได้ด้วย
|
||||
- `preflight_only`: `true` สำหรับการตรวจสอบ/บิลด์/แพ็กเกจเท่านั้น, `false` สำหรับ
|
||||
เส้นทางเผยแพร่จริง
|
||||
- `preflight_run_id`: จำเป็นบนเส้นทางเผยแพร่จริงเพื่อให้เวิร์กโฟลว์ใช้ tarball
|
||||
ที่เตรียมไว้จากการรัน preflight ที่สำเร็จซ้ำ
|
||||
- `npm_dist_tag`: แท็กเป้าหมายของ npm สำหรับเส้นทางเผยแพร่; ค่าเริ่มต้นคือ `beta`
|
||||
- `tag`: แท็กรีลีสที่จำเป็น เช่น `v2026.4.2`, `v2026.4.2-1`, หรือ
|
||||
`v2026.4.2-beta.1`; เมื่อ `preflight_only=true` ค่านี้อาจเป็น workflow-branch commit SHA
|
||||
แบบเต็ม 40 อักขระปัจจุบันสำหรับ preflight ที่ใช้ตรวจสอบเท่านั้นได้ด้วย
|
||||
- `preflight_only`: `true` สำหรับการตรวจสอบ/บิลด์/แพ็กเกจเท่านั้น, `false` สำหรับเส้นทาง
|
||||
เผยแพร่จริง
|
||||
- `preflight_run_id`: จำเป็นบนเส้นทางเผยแพร่จริงเพื่อให้เวิร์กโฟลว์ใช้ tarball ที่เตรียมไว้
|
||||
จากการรัน preflight ที่สำเร็จซ้ำ
|
||||
- `npm_dist_tag`: แท็กเป้าหมาย npm สำหรับเส้นทางเผยแพร่; ค่าเริ่มต้นคือ `beta`
|
||||
|
||||
`OpenClaw Release Publish` รับอินพุตที่ควบคุมโดยผู้ปฏิบัติงานเหล่านี้:
|
||||
`OpenClaw Release Publish` รับอินพุตที่ผู้ปฏิบัติงานควบคุมได้ดังนี้:
|
||||
|
||||
- `tag`: แท็กรีลีสที่จำเป็น; ต้องมีอยู่แล้ว
|
||||
- `preflight_run_id`: รหัสการรัน preflight ของ `OpenClaw NPM Release` ที่สำเร็จ;
|
||||
- `preflight_run_id`: id การรัน preflight ของ `OpenClaw NPM Release` ที่สำเร็จ;
|
||||
จำเป็นเมื่อ `publish_openclaw_npm=true`
|
||||
- `npm_dist_tag`: แท็กเป้าหมายของ npm สำหรับแพ็กเกจ OpenClaw
|
||||
- `npm_dist_tag`: แท็กเป้าหมาย npm สำหรับแพ็กเกจ OpenClaw
|
||||
- `plugin_publish_scope`: ค่าเริ่มต้นคือ `all-publishable`; ใช้ `selected` เฉพาะ
|
||||
สำหรับงานซ่อมแซมแบบเจาะจง
|
||||
- `plugins`: ชื่อแพ็กเกจ `@openclaw/*` คั่นด้วยจุลภาคเมื่อ
|
||||
`plugin_publish_scope=selected`
|
||||
- `publish_openclaw_npm`: ค่าเริ่มต้นคือ `true`; ตั้งเป็น `false` เฉพาะเมื่อใช้
|
||||
เวิร์กโฟลว์เป็นตัวจัดลำดับการซ่อมแซมเฉพาะ Plugin เท่านั้น
|
||||
เวิร์กโฟลว์เป็นตัวประสานงานการซ่อมแซมแบบเฉพาะ Plugin เท่านั้น
|
||||
|
||||
`OpenClaw Release Checks` รับอินพุตที่ควบคุมโดยผู้ปฏิบัติงานเหล่านี้:
|
||||
`OpenClaw Release Checks` รับอินพุตที่ผู้ปฏิบัติงานควบคุมได้ดังนี้:
|
||||
|
||||
- `ref`: branch, tag หรือ full commit SHA ที่จะตรวจสอบ การตรวจสอบที่มี secret
|
||||
ต้องให้ commit ที่แก้ค่าแล้วสามารถเข้าถึงได้จาก branch ของ OpenClaw หรือ
|
||||
release tag
|
||||
- `ref`: branch, tag, หรือ commit SHA แบบเต็มที่ต้องตรวจสอบ เช็กที่มี secret
|
||||
ต้องให้ commit ที่แก้ค่าแล้วเข้าถึงได้จาก branch หรือแท็กรีลีสของ OpenClaw
|
||||
|
||||
กฎ:
|
||||
|
||||
- แท็ก Stable และแท็กแก้ไขสามารถเผยแพร่ไปยัง `beta` หรือ `latest` ได้
|
||||
- แท็ก prerelease แบบ Beta สามารถเผยแพร่ได้เฉพาะไปยัง `beta`
|
||||
- สำหรับ `OpenClaw NPM Release` อนุญาตให้ใช้อินพุต full commit SHA เฉพาะเมื่อ
|
||||
- แท็กเสถียรและแท็กแก้ไขอาจเผยแพร่ไปยัง `beta` หรือ `latest` ก็ได้
|
||||
- แท็ก prerelease เบต้าอาจเผยแพร่ได้เฉพาะไปยัง `beta`
|
||||
- สำหรับ `OpenClaw NPM Release` อนุญาตให้อินพุต commit SHA แบบเต็มได้เฉพาะเมื่อ
|
||||
`preflight_only=true`
|
||||
- `OpenClaw Release Checks` และ `Full Release Validation` เป็นแบบตรวจสอบเท่านั้นเสมอ
|
||||
- เส้นทางเผยแพร่จริงต้องใช้ `npm_dist_tag` เดียวกับที่ใช้ระหว่าง preflight;
|
||||
เวิร์กโฟลว์จะตรวจสอบ metadata นั้นก่อนที่การเผยแพร่จะดำเนินต่อ
|
||||
เวิร์กโฟลว์จะตรวจสอบว่าเมทาดาทาดังกล่าวยังคงถูกต้องก่อนเผยแพร่ต่อไป
|
||||
|
||||
## ลำดับการรีลีส npm แบบ Stable
|
||||
## ลำดับการรีลีส npm แบบเสถียร
|
||||
|
||||
เมื่อตัดรีลีส npm แบบ Stable:
|
||||
เมื่อตัดรีลีส npm แบบเสถียร:
|
||||
|
||||
1. รัน `OpenClaw NPM Release` ด้วย `preflight_only=true`
|
||||
- ก่อนที่จะมีแท็ก คุณสามารถใช้ full workflow-branch commit SHA ปัจจุบัน
|
||||
สำหรับ dry run ของเวิร์กโฟลว์ preflight แบบตรวจสอบเท่านั้น
|
||||
2. เลือก `npm_dist_tag=beta` สำหรับโฟลว์ beta-first ปกติ หรือ `latest` เฉพาะเมื่อ
|
||||
คุณตั้งใจต้องการเผยแพร่ Stable โดยตรง
|
||||
3. รัน `Full Release Validation` บน release branch, release tag หรือ full
|
||||
commit SHA เมื่อคุณต้องการ CI ปกติรวมกับ live prompt cache, Docker, QA Lab,
|
||||
Matrix และความครอบคลุมของ Telegram จากเวิร์กโฟลว์แบบแมนนวลเดียว
|
||||
4. หากคุณตั้งใจต้องการเฉพาะกราฟทดสอบปกติแบบกำหนดได้แน่นอน ให้รันเวิร์กโฟลว์
|
||||
`CI` แบบแมนนวลบน release ref แทน
|
||||
- ก่อนมีแท็ก คุณอาจใช้ workflow-branch commit SHA แบบเต็มปัจจุบัน
|
||||
สำหรับ dry run แบบตรวจสอบเท่านั้นของเวิร์กโฟลว์ preflight
|
||||
2. เลือก `npm_dist_tag=beta` สำหรับโฟลว์ปกติแบบเบต้าก่อน หรือ `latest` เฉพาะ
|
||||
เมื่อคุณตั้งใจต้องการเผยแพร่เสถียรโดยตรง
|
||||
3. รัน `Full Release Validation` บน branch รีลีส, แท็กรีลีส, หรือ
|
||||
commit SHA แบบเต็ม เมื่อต้องการ CI ปกติรวมกับ live prompt cache, Docker, QA Lab,
|
||||
Matrix, และความครอบคลุมของ Telegram จากเวิร์กโฟลว์แบบแมนนวลเดียว
|
||||
4. หากคุณตั้งใจต้องการเฉพาะกราฟทดสอบปกติแบบกำหนดแน่นอน ให้รันเวิร์กโฟลว์
|
||||
`CI` แบบแมนนวลบน ref รีลีสแทน
|
||||
5. บันทึก `preflight_run_id` ที่สำเร็จ
|
||||
6. รัน `OpenClaw Release Publish` ด้วย `tag` เดียวกัน, `npm_dist_tag` เดียวกัน
|
||||
และ `preflight_run_id` ที่บันทึกไว้; เวิร์กโฟลว์จะเผยแพร่ Plugin ที่ถูกทำให้เป็นภายนอกไปยัง npm
|
||||
และ ClawHub ก่อนเลื่อนแพ็กเกจ OpenClaw npm
|
||||
7. หากรีลีสลงบน `beta` ให้ใช้เวิร์กโฟลว์ส่วนตัว
|
||||
6. รัน `OpenClaw Release Publish` ด้วย `tag` เดียวกัน, `npm_dist_tag` เดียวกัน,
|
||||
และ `preflight_run_id` ที่บันทึกไว้; เวิร์กโฟลว์จะเผยแพร่ Plugin ที่แยกออกภายนอกไปยัง npm
|
||||
และ ClawHub ก่อนโปรโมตแพ็กเกจ npm ของ OpenClaw
|
||||
7. หากรีลีสลงที่ `beta` ให้ใช้เวิร์กโฟลว์ส่วนตัว
|
||||
`openclaw/releases-private/.github/workflows/openclaw-npm-dist-tags.yml`
|
||||
เพื่อเลื่อนเวอร์ชัน Stable นั้นจาก `beta` ไปยัง `latest`
|
||||
8. หากรีลีสเผยแพร่โดยตรงไปยัง `latest` อย่างตั้งใจและ `beta` ควรตามบิลด์ Stable
|
||||
เดียวกันทันที ให้ใช้เวิร์กโฟลว์ส่วนตัวเดียวกันนั้นเพื่อชี้ dist-tag ทั้งสองไปยังเวอร์ชัน Stable
|
||||
หรือปล่อยให้การซิงก์ซ่อมแซมตัวเองตามกำหนดการย้าย `beta` ในภายหลัง
|
||||
เพื่อโปรโมตเวอร์ชันเสถียรนั้นจาก `beta` ไปยัง `latest`
|
||||
8. หากรีลีสตั้งใจเผยแพร่ตรงไปยัง `latest` และ `beta`
|
||||
ควรตามบิลด์เสถียรเดียวกันทันที ให้ใช้เวิร์กโฟลว์ส่วนตัวเดียวกัน
|
||||
เพื่อชี้ dist-tag ทั้งสองไปยังเวอร์ชันเสถียร หรือปล่อยให้การซิงก์แก้ไขตัวเองตามกำหนดการ
|
||||
ย้าย `beta` ภายหลัง
|
||||
|
||||
การแก้ไข dist-tag อยู่ใน repo ส่วนตัวเพื่อความปลอดภัย เพราะยังต้องใช้
|
||||
`NPM_TOKEN` ในขณะที่ repo สาธารณะใช้การเผยแพร่แบบ OIDC เท่านั้น
|
||||
การเปลี่ยนแปลง dist-tag อยู่ใน repo ส่วนตัวด้วยเหตุผลด้านความปลอดภัย เพราะยัง
|
||||
ต้องใช้ `NPM_TOKEN` ขณะที่ repo สาธารณะคงการเผยแพร่แบบ OIDC-only ไว้
|
||||
|
||||
สิ่งนี้ทำให้ทั้งเส้นทางเผยแพร่โดยตรงและเส้นทางเลื่อนแบบ beta-first
|
||||
มีเอกสารกำกับและผู้ปฏิบัติงานมองเห็นได้
|
||||
สิ่งนี้ทำให้ทั้งเส้นทางเผยแพร่โดยตรงและเส้นทางโปรโมตแบบเบต้าก่อน
|
||||
มีเอกสารครบถ้วนและผู้ปฏิบัติงานมองเห็นได้
|
||||
|
||||
หาก maintainer จำเป็นต้อง fallback ไปใช้การยืนยันตัวตน npm ในเครื่อง ให้รันคำสั่ง
|
||||
1Password CLI (`op`) ใด ๆ เฉพาะภายในเซสชัน tmux เฉพาะเท่านั้น อย่าเรียก `op`
|
||||
โดยตรงจาก shell เอเจนต์หลัก; การเก็บไว้ภายใน tmux ทำให้ prompt,
|
||||
alert และการจัดการ OTP สังเกตได้ และป้องกัน alert ของโฮสต์ที่เกิดซ้ำ
|
||||
หาก maintainer ต้อง fallback ไปใช้การยืนยันตัวตน npm แบบ local ให้รันคำสั่ง 1Password
|
||||
CLI (`op`) ใด ๆ เฉพาะในเซสชัน tmux เฉพาะเท่านั้น อย่าเรียก `op`
|
||||
โดยตรงจากเชลล์เอเจนต์หลัก; การเก็บไว้ใน tmux ทำให้ prompt,
|
||||
การแจ้งเตือน, และการจัดการ OTP สังเกตเห็นได้และป้องกันการแจ้งเตือน host ซ้ำ
|
||||
|
||||
## เอกสารอ้างอิงสาธารณะ
|
||||
|
||||
|
||||
@ -1,40 +1,40 @@
|
||||
---
|
||||
read_when:
|
||||
- คุณต้องการการป้องกันเชิงลึกจากการโจมตีแบบ SSRF และการผูก DNS ใหม่
|
||||
- การกำหนดค่าพร็อกซีส่งต่อภายนอกสำหรับทราฟฟิกระหว่างการทำงานของ OpenClaw
|
||||
summary: วิธีส่งต่อทราฟฟิก HTTP และ WebSocket ขณะรันไทม์ของ OpenClaw ผ่านพร็อกซีกรองที่ผู้ปฏิบัติงานจัดการ
|
||||
- การกำหนดค่าพร็อกซีแบบส่งต่อภายนอกสำหรับทราฟฟิกขณะรันไทม์ของ OpenClaw
|
||||
summary: วิธีกำหนดเส้นทางทราฟฟิก HTTP และ WebSocket ของรันไทม์ OpenClaw ผ่านพร็อกซีกรองที่จัดการโดยผู้ปฏิบัติการ
|
||||
title: พร็อกซีเครือข่าย
|
||||
x-i18n:
|
||||
generated_at: "2026-05-04T02:26:06Z"
|
||||
generated_at: "2026-05-04T07:07:03Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: cd5594324e8c6b7da51d903e98fda0feacb8970e0b15d980f7a249d6641461c9
|
||||
source_hash: fc7140c5ced0e7454a6f85d1ea8f3256bbd28cc0cb42eeafe8e5e6439b90e3f0
|
||||
source_path: security/network-proxy.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
# พร็อกซีเครือข่าย
|
||||
|
||||
OpenClaw สามารถกำหนดเส้นทางทราฟฟิก HTTP และ WebSocket ของรันไทม์ผ่านพร็อกซีแบบส่งต่อที่ผู้ปฏิบัติการจัดการได้ นี่เป็นการป้องกันเชิงลึกแบบไม่บังคับสำหรับการปรับใช้ที่ต้องการควบคุมทราฟฟิกขาออกจากศูนย์กลาง เพิ่มการป้องกัน SSRF ให้แข็งแรงขึ้น และตรวจสอบเครือข่ายได้ดียิ่งขึ้น
|
||||
OpenClaw สามารถกำหนดเส้นทางทราฟฟิก HTTP และ WebSocket ขณะรันไทม์ผ่านพร็อกซีส่งต่อที่ผู้ปฏิบัติงานจัดการได้ นี่เป็นการป้องกันเชิงลึกแบบเลือกใช้ สำหรับการปรับใช้ที่ต้องการควบคุมทราฟฟิกขาออกจากศูนย์กลาง เพิ่มการป้องกัน SSRF ให้แข็งแรงขึ้น และตรวจสอบเครือข่ายได้ดียิ่งขึ้น
|
||||
|
||||
OpenClaw ไม่ได้จัดส่ง ดาวน์โหลด เริ่มต้น กำหนดค่า หรือรับรองพร็อกซี คุณเป็นผู้รันเทคโนโลยีพร็อกซีที่เหมาะกับสภาพแวดล้อมของคุณ และ OpenClaw จะกำหนดเส้นทางไคลเอนต์ HTTP และ WebSocket แบบปกติภายในโปรเซสผ่านพร็อกซีนั้น
|
||||
OpenClaw ไม่ได้จัดส่ง ดาวน์โหลด เริ่มต้น กำหนดค่า หรือรับรองพร็อกซี คุณเป็นผู้รันเทคโนโลยีพร็อกซีที่เหมาะกับสภาพแวดล้อมของคุณ และ OpenClaw จะกำหนดเส้นทางไคลเอนต์ HTTP และ WebSocket ภายในโปรเซสตามปกติผ่านพร็อกซีนั้น
|
||||
|
||||
## ทำไมต้องใช้พร็อกซี?
|
||||
|
||||
พร็อกซีให้จุดควบคุมเครือข่ายจุดเดียวแก่ผู้ปฏิบัติการสำหรับทราฟฟิก HTTP และ WebSocket ขาออก ซึ่งมีประโยชน์ได้แม้นอกเหนือจากการเสริมความแข็งแรงด้าน SSRF:
|
||||
พร็อกซีให้จุดควบคุมเครือข่ายจุดเดียวแก่ผู้ปฏิบัติงานสำหรับทราฟฟิก HTTP และ WebSocket ขาออก ซึ่งมีประโยชน์ได้แม้อยู่นอกเหนือจากการเสริมความแข็งแรงเพื่อป้องกัน SSRF:
|
||||
|
||||
- นโยบายจากศูนย์กลาง: ดูแลนโยบายขาออกเพียงชุดเดียว แทนการพึ่งพาให้ทุกจุดเรียก HTTP ของแอปพลิเคชันกำหนดกฎเครือข่ายให้ถูกต้อง
|
||||
- การตรวจสอบ ณ เวลาที่เชื่อมต่อ: ประเมินปลายทางหลังจากการแก้ชื่อ DNS และทันทีก่อนที่พร็อกซีจะเปิดการเชื่อมต่อต้นทาง
|
||||
- นโยบายส่วนกลาง: ดูแลนโยบายขาออกเพียงชุดเดียว แทนที่จะพึ่งให้ทุกจุดเรียก HTTP ของแอปพลิเคชันกำหนดกฎเครือข่ายให้ถูกต้องเอง
|
||||
- การตรวจสอบ ณ เวลาเชื่อมต่อ: ประเมินปลายทางหลังการแก้ชื่อ DNS และทันทีก่อนที่พร็อกซีจะเปิดการเชื่อมต่อต้นทาง
|
||||
- การป้องกัน DNS rebinding: ลดช่องว่างระหว่างการตรวจสอบ DNS ระดับแอปพลิเคชันกับการเชื่อมต่อขาออกจริง
|
||||
- ครอบคลุม JavaScript ได้กว้างขึ้น: กำหนดเส้นทาง `fetch`, `node:http`, `node:https`, WebSocket, axios, got, node-fetch และไคลเอนต์ที่คล้ายกันผ่านเส้นทางเดียวกัน
|
||||
- ตรวจสอบย้อนหลังได้: บันทึกปลายทางที่อนุญาตและถูกปฏิเสธที่ขอบเขตขาออก
|
||||
- การควบคุมเชิงปฏิบัติการ: บังคับใช้กฎปลายทาง การแบ่งส่วนเครือข่าย ขีดจำกัดอัตรา หรือรายการอนุญาตขาออกโดยไม่ต้องสร้าง OpenClaw ใหม่
|
||||
- ครอบคลุม JavaScript กว้างขึ้น: กำหนดเส้นทางไคลเอนต์ทั่วไปอย่าง `fetch`, `node:http`, `node:https`, WebSocket, axios, got, node-fetch และไคลเอนต์ลักษณะใกล้เคียงผ่านเส้นทางเดียวกัน
|
||||
- การตรวจสอบย้อนหลัง: บันทึกปลายทางที่อนุญาตและปฏิเสธไว้ที่ขอบเขตทราฟฟิกขาออก
|
||||
- การควบคุมเชิงปฏิบัติการ: บังคับใช้กฎปลายทาง การแบ่งส่วนเครือข่าย การจำกัดอัตรา หรือ allowlist ขาออกได้โดยไม่ต้องสร้าง OpenClaw ใหม่
|
||||
|
||||
การกำหนดเส้นทางผ่านพร็อกซีเป็นแนวป้องกันระดับโปรเซสสำหรับทราฟฟิก HTTP และ WebSocket ขาออกแบบปกติ ช่วยให้ผู้ปฏิบัติการมีเส้นทางแบบล้มเหลวแล้วปิดกั้นสำหรับการกำหนดเส้นทางไคลเอนต์ HTTP ของ JavaScript ที่รองรับผ่านพร็อกซีกรองของตนเอง แต่ไม่ใช่แซนด์บ็อกซ์เครือข่ายระดับ OS และไม่ได้ทำให้ OpenClaw รับรองนโยบายปลายทางของพร็อกซี
|
||||
การกำหนดเส้นทางพร็อกซีเป็นกรอบป้องกันระดับโปรเซสสำหรับ HTTP และ WebSocket ขาออกตามปกติ ช่วยให้ผู้ปฏิบัติงานมีเส้นทางแบบ fail-closed สำหรับกำหนดเส้นทางไคลเอนต์ HTTP ของ JavaScript ที่รองรับผ่านพร็อกซีกรองข้อมูลของตนเอง แต่ไม่ใช่ sandbox เครือข่ายระดับ OS และไม่ได้ทำให้ OpenClaw รับรองนโยบายปลายทางของพร็อกซี
|
||||
|
||||
## OpenClaw กำหนดเส้นทางทราฟฟิกอย่างไร
|
||||
|
||||
เมื่อกำหนดค่า `proxy.enabled=true` และตั้งค่า URL ของพร็อกซีแล้ว โปรเซสรันไทม์ที่ได้รับการป้องกัน เช่น `openclaw gateway run`, `openclaw node run` และ `openclaw agent --local` จะกำหนดเส้นทางทราฟฟิก HTTP และ WebSocket ขาออกแบบปกติผ่านพร็อกซีที่กำหนดค่าไว้:
|
||||
เมื่อ `proxy.enabled=true` และมีการกำหนดค่า URL พร็อกซี โปรเซสรันไทม์ที่ได้รับการปกป้อง เช่น `openclaw gateway run`, `openclaw node run` และ `openclaw agent --local` จะกำหนดเส้นทาง HTTP และ WebSocket ขาออกตามปกติผ่านพร็อกซีที่กำหนดค่าไว้:
|
||||
|
||||
```text
|
||||
OpenClaw process
|
||||
@ -43,27 +43,27 @@ OpenClaw process
|
||||
WebSocket clients -> operator-managed filtering proxy -> public internet
|
||||
```
|
||||
|
||||
สัญญาสาธารณะคือพฤติกรรมการกำหนดเส้นทาง ไม่ใช่ฮุกภายในของ Node ที่ใช้ติดตั้งใช้งาน OpenClaw Gateway control-plane WebSocket clients ใช้เส้นทางตรงแบบแคบสำหรับทราฟฟิก local loopback Gateway RPC เมื่อ URL ของ Gateway ใช้ `localhost` หรือ IP ลูปแบ็กแบบลิเทอรัล เช่น `127.0.0.1` หรือ `[::1]` เส้นทาง control-plane นั้นต้องสามารถเข้าถึง Gateway แบบลูปแบ็กได้ แม้พร็อกซีของผู้ปฏิบัติการจะบล็อกปลายทางลูปแบ็กก็ตาม คำขอ HTTP และ WebSocket ของรันไทม์แบบปกติยังคงใช้พร็อกซีที่กำหนดค่าไว้
|
||||
สัญญาสาธารณะคือพฤติกรรมการกำหนดเส้นทาง ไม่ใช่ hook ภายในของ Node ที่ใช้ในการนำไปใช้งาน ไคลเอนต์ WebSocket ใน control plane ของ OpenClaw Gateway ใช้เส้นทางตรงแบบแคบสำหรับทราฟฟิก RPC ของ Gateway ผ่าน local loopback เมื่อ URL ของ Gateway ใช้ `localhost` หรือ IP loopback แบบ literal เช่น `127.0.0.1` หรือ `[::1]` เส้นทาง control plane นั้นต้องสามารถเข้าถึง Gateway บน loopback ได้แม้พร็อกซีของผู้ปฏิบัติงานจะบล็อกปลายทาง loopback ก็ตาม คำขอ HTTP และ WebSocket ของรันไทม์ตามปกติยังคงใช้พร็อกซีที่กำหนดค่าไว้
|
||||
|
||||
ภายใน OpenClaw ใช้ฮุกกำหนดเส้นทางระดับโปรเซสสองรายการสำหรับฟีเจอร์นี้:
|
||||
ภายใน OpenClaw ใช้ hook การกำหนดเส้นทางระดับโปรเซสสองแบบสำหรับฟีเจอร์นี้:
|
||||
|
||||
- การกำหนดเส้นทางด้วย Undici dispatcher ครอบคลุม `fetch`, ไคลเอนต์ที่มี undici เป็นแบ็กเอนด์ และทรานสปอร์ตที่จัดเตรียม undici dispatcher ของตนเอง
|
||||
- การกำหนดเส้นทางด้วย `global-agent` ครอบคลุมผู้เรียก Node core `node:http` และ `node:https` รวมถึงไลบรารีจำนวนมากที่ต่อยอดบน `http.request`, `https.request`, `http.get` และ `https.get` โหมดพร็อกซีที่จัดการจะบังคับใช้ global agent นั้น เพื่อไม่ให้ Node HTTP agents ที่ระบุอย่างชัดเจนเลี่ยงพร็อกซีของผู้ปฏิบัติการโดยไม่ตั้งใจ
|
||||
- การกำหนดเส้นทางด้วย dispatcher ของ Undici ครอบคลุม `fetch`, ไคลเอนต์ที่มี undici รองรับ และ transport ที่มี dispatcher ของ undici เป็นของตนเอง
|
||||
- การกำหนดเส้นทางด้วย `global-agent` ครอบคลุมผู้เรียก Node core `node:http` และ `node:https` รวมถึงไลบรารีจำนวนมากที่ต่อยอดบน `http.request`, `https.request`, `http.get` และ `https.get` โหมดพร็อกซีที่จัดการจะบังคับใช้ global agent นั้น เพื่อไม่ให้ agent ของ Node HTTP ที่ระบุไว้โดยตรงข้ามพร็อกซีของผู้ปฏิบัติงานโดยไม่ตั้งใจ
|
||||
|
||||
Plugin บางตัวเป็นเจ้าของทรานสปอร์ตแบบกำหนดเองที่ต้องต่อสายพร็อกซีอย่างชัดเจน แม้จะมีการกำหนดเส้นทางระดับโปรเซสอยู่แล้ว ตัวอย่างเช่น ทรานสปอร์ต Bot API ของ Telegram ใช้ HTTP/1 undici dispatcher ของตนเอง จึงเคารพ env พร็อกซีของโปรเซส รวมถึง fallback `OPENCLAW_PROXY_URL` ที่จัดการในเส้นทางทรานสปอร์ตเฉพาะเจ้าของนั้น
|
||||
Plugin บางตัวมี transport แบบกำหนดเองที่ต้องเดินสายพร็อกซีอย่างชัดเจน แม้จะมีการกำหนดเส้นทางระดับโปรเซสอยู่แล้วก็ตาม ตัวอย่างเช่น transport ของ Bot API ใน Telegram ใช้ HTTP/1 undici dispatcher ของตัวเอง จึงเคารพ env พร็อกซีของโปรเซส รวมถึง fallback `OPENCLAW_PROXY_URL` ที่จัดการในเส้นทาง transport เฉพาะเจ้าของนั้น
|
||||
|
||||
URL ของพร็อกซีเองต้องใช้ `http://` ปลายทาง HTTPS ยังคงรองรับผ่านพร็อกซีด้วย HTTP `CONNECT`; ความหมายมีเพียงว่า OpenClaw คาดหวัง listener ของพร็อกซีแบบส่งต่อ HTTP ธรรมดา เช่น `http://127.0.0.1:3128`
|
||||
URL ของพร็อกซีเองต้องใช้ `http://` ปลายทาง HTTPS ยังคงรองรับผ่านพร็อกซีด้วย HTTP `CONNECT`; นี่หมายความเพียงว่า OpenClaw คาดหวัง listener ของพร็อกซีส่งต่อ HTTP แบบธรรมดา เช่น `http://127.0.0.1:3128`
|
||||
|
||||
ขณะที่พร็อกซีทำงานอยู่ OpenClaw จะล้าง `no_proxy`, `NO_PROXY` และ `GLOBAL_AGENT_NO_PROXY` รายการ bypass เหล่านั้นอิงตามปลายทาง ดังนั้นหากปล่อย `localhost` หรือ `127.0.0.1` ไว้ในนั้น จะทำให้เป้าหมาย SSRF ที่มีความเสี่ยงสูงข้ามพร็อกซีกรองได้
|
||||
ขณะที่พร็อกซีทำงานอยู่ OpenClaw จะล้าง `no_proxy`, `NO_PROXY` และ `GLOBAL_AGENT_NO_PROXY` รายการข้ามเหล่านี้อิงตามปลายทาง ดังนั้นหากปล่อย `localhost` หรือ `127.0.0.1` ไว้ในนั้น จะทำให้เป้าหมาย SSRF ความเสี่ยงสูงข้ามพร็อกซีกรองข้อมูลได้
|
||||
|
||||
เมื่อปิดการทำงาน OpenClaw จะกู้คืนสภาพแวดล้อมพร็อกซีก่อนหน้าและรีเซ็ตสถานะการกำหนดเส้นทางของโปรเซสที่แคชไว้
|
||||
|
||||
## คำศัพท์ที่เกี่ยวข้องกับพร็อกซี
|
||||
## คำศัพท์เกี่ยวกับพร็อกซีที่เกี่ยวข้อง
|
||||
|
||||
- `proxy.enabled` / `proxy.proxyUrl`: การกำหนดเส้นทางขาออกผ่านพร็อกซีแบบส่งต่อสำหรับทราฟฟิกขาออกของรันไทม์ OpenClaw หน้านี้จัดทำเอกสารฟีเจอร์ดังกล่าว
|
||||
- `gateway.auth.mode: "trusted-proxy"`: การยืนยันตัวตนขาเข้าแบบ reverse-proxy ที่รับรู้ตัวตนสำหรับการเข้าถึง Gateway ดู [การยืนยันตัวตนพร็อกซีที่เชื่อถือได้](/th/gateway/trusted-proxy-auth)
|
||||
- `openclaw proxy`: พร็อกซีดีบักภายในเครื่องและตัวตรวจสอบการจับข้อมูลสำหรับการพัฒนาและการสนับสนุน ดู [openclaw proxy](/th/cli/proxy)
|
||||
- การตั้งค่าพร็อกซีเฉพาะ channel หรือ provider: การแทนที่เฉพาะเจ้าของสำหรับทรานสปอร์ตหนึ่งรายการ ควรใช้พร็อกซีเครือข่ายที่จัดการเมื่อเป้าหมายคือการควบคุมทราฟฟิกขาออกจากศูนย์กลางทั่วทั้งรันไทม์
|
||||
- `proxy.enabled` / `proxy.proxyUrl`: การกำหนดเส้นทางพร็อกซีส่งต่อขาออกสำหรับทราฟฟิกขาออกของรันไทม์ OpenClaw หน้านี้อธิบายฟีเจอร์นั้น
|
||||
- `gateway.auth.mode: "trusted-proxy"`: การยืนยันตัวตนขาเข้าผ่าน reverse proxy ที่รับรู้ตัวตนสำหรับการเข้าถึง Gateway ดู [การยืนยันตัวตนผ่านพร็อกซีที่เชื่อถือได้](/th/gateway/trusted-proxy-auth)
|
||||
- `openclaw proxy`: พร็อกซีดีบักในเครื่องและตัวตรวจสอบการจับข้อมูลสำหรับการพัฒนาและการสนับสนุน ดู [openclaw proxy](/th/cli/proxy)
|
||||
- การตั้งค่าพร็อกซีเฉพาะช่องทางหรือ provider: override เฉพาะเจ้าของสำหรับ transport รายใดรายหนึ่ง ควรใช้พร็อกซีเครือข่ายที่จัดการเมื่อเป้าหมายคือการควบคุมทราฟฟิกขาออกจากศูนย์กลางทั่วทั้งรันไทม์
|
||||
|
||||
## การกำหนดค่า
|
||||
|
||||
@ -73,7 +73,7 @@ proxy:
|
||||
proxyUrl: http://127.0.0.1:3128
|
||||
```
|
||||
|
||||
คุณยังสามารถระบุ URL ผ่านสภาพแวดล้อมได้ โดยคง `proxy.enabled=true` ไว้ในการกำหนดค่า:
|
||||
คุณยังสามารถระบุ URL ผ่านสภาพแวดล้อมได้ โดยยังคงตั้ง `proxy.enabled=true` ไว้ใน config:
|
||||
|
||||
```bash
|
||||
OPENCLAW_PROXY_URL=http://127.0.0.1:3128 openclaw gateway run
|
||||
@ -81,9 +81,9 @@ OPENCLAW_PROXY_URL=http://127.0.0.1:3128 openclaw gateway run
|
||||
|
||||
`proxy.proxyUrl` มีลำดับความสำคัญเหนือ `OPENCLAW_PROXY_URL`
|
||||
|
||||
หาก `enabled=true` แต่ไม่มี URL พร็อกซีที่ถูกต้องได้รับการกำหนดค่า คำสั่งที่ได้รับการป้องกันจะเริ่มต้นไม่สำเร็จ แทนที่จะ fallback ไปใช้การเข้าถึงเครือข่ายโดยตรง
|
||||
หาก `enabled=true` แต่ไม่มี URL พร็อกซีที่ถูกต้องกำหนดไว้ คำสั่งที่ได้รับการปกป้องจะเริ่มต้นล้มเหลวแทนที่จะ fallback ไปใช้การเข้าถึงเครือข่ายโดยตรง
|
||||
|
||||
สำหรับบริการ Gateway ที่จัดการซึ่งเริ่มด้วย `openclaw gateway start` ควรจัดเก็บ URL ไว้ในการกำหนดค่า:
|
||||
สำหรับบริการ gateway ที่จัดการซึ่งเริ่มด้วย `openclaw gateway start` ควรเก็บ URL ไว้ใน config:
|
||||
|
||||
```bash
|
||||
openclaw config set proxy.enabled true
|
||||
@ -92,9 +92,9 @@ openclaw gateway install --force
|
||||
openclaw gateway start
|
||||
```
|
||||
|
||||
fallback ผ่านสภาพแวดล้อมเหมาะที่สุดสำหรับการรันแบบ foreground หากคุณใช้กับบริการที่ติดตั้งแล้ว ให้ใส่ `OPENCLAW_PROXY_URL` ในสภาพแวดล้อมถาวรของบริการ เช่น `$OPENCLAW_STATE_DIR/.env` หรือ `~/.openclaw/.env` จากนั้นติดตั้งบริการใหม่เพื่อให้ launchd, systemd หรือ Scheduled Tasks เริ่ม Gateway พร้อมค่านั้น
|
||||
fallback ผ่านสภาพแวดล้อมเหมาะที่สุดสำหรับการรันแบบ foreground หากคุณใช้กับบริการที่ติดตั้งแล้ว ให้ใส่ `OPENCLAW_PROXY_URL` ในสภาพแวดล้อมถาวรของบริการ เช่น `$OPENCLAW_STATE_DIR/.env` หรือ `~/.openclaw/.env` แล้วติดตั้งบริการใหม่ เพื่อให้ launchd, systemd หรือ Scheduled Tasks เริ่ม gateway พร้อมค่านั้น
|
||||
|
||||
สำหรับคำสั่ง `openclaw --container ...` OpenClaw จะส่งต่อ `OPENCLAW_PROXY_URL` ไปยัง CLI ลูกที่มุ่งเป้าไปยังคอนเทนเนอร์เมื่อมีการตั้งค่า URL ต้องเข้าถึงได้จากภายในคอนเทนเนอร์; `127.0.0.1` หมายถึงตัวคอนเทนเนอร์เอง ไม่ใช่โฮสต์ OpenClaw จะปฏิเสธ URL พร็อกซีลูปแบ็กสำหรับคำสั่งที่มุ่งเป้าไปยังคอนเทนเนอร์ เว้นแต่คุณจะแทนที่การตรวจสอบความปลอดภัยนั้นอย่างชัดเจน
|
||||
สำหรับคำสั่ง `openclaw --container ...` OpenClaw จะส่งต่อ `OPENCLAW_PROXY_URL` เข้าไปยัง CLI ลูกที่มีเป้าหมายเป็นคอนเทนเนอร์เมื่อมีการตั้งค่า URL ต้องเข้าถึงได้จากภายในคอนเทนเนอร์; `127.0.0.1` หมายถึงตัวคอนเทนเนอร์เอง ไม่ใช่โฮสต์ OpenClaw จะปฏิเสธ URL พร็อกซีแบบ loopback สำหรับคำสั่งที่มีเป้าหมายเป็นคอนเทนเนอร์ เว้นแต่คุณจะ override การตรวจสอบความปลอดภัยนั้นอย่างชัดเจน
|
||||
|
||||
## ข้อกำหนดของพร็อกซี
|
||||
|
||||
@ -102,41 +102,41 @@ fallback ผ่านสภาพแวดล้อมเหมาะที่
|
||||
|
||||
กำหนดค่าพร็อกซีให้:
|
||||
|
||||
- ผูกกับลูปแบ็กหรืออินเทอร์เฟซส่วนตัวที่เชื่อถือได้เท่านั้น
|
||||
- จำกัดการเข้าถึงเพื่อให้เฉพาะโปรเซส OpenClaw, โฮสต์, คอนเทนเนอร์ หรือบัญชีบริการเท่านั้นที่ใช้งานได้
|
||||
- แก้ชื่อปลายทางเองและบล็อก IP ปลายทางหลังจากการแก้ชื่อ DNS
|
||||
- ใช้นโยบาย ณ เวลาที่เชื่อมต่อสำหรับทั้งคำขอ HTTP ธรรมดาและทันเนล HTTPS `CONNECT`
|
||||
- ปฏิเสธ bypass ที่อิงตามปลายทางสำหรับช่วงลูปแบ็ก ส่วนตัว link-local เมทาดาทา multicast สงวนไว้ หรือเอกสารประกอบ
|
||||
- หลีกเลี่ยงรายการอนุญาตตามชื่อโฮสต์ เว้นแต่คุณจะเชื่อถือเส้นทางการแก้ชื่อ DNS อย่างเต็มที่
|
||||
- บันทึกปลายทาง การตัดสินใจ สถานะ และเหตุผล โดยไม่บันทึกเนื้อหาคำขอ เฮดเดอร์ authorization คุกกี้ หรือความลับอื่น
|
||||
- เก็บนโยบายพร็อกซีไว้ภายใต้การควบคุมเวอร์ชัน และตรวจสอบการเปลี่ยนแปลงเหมือนการกำหนดค่าที่อ่อนไหวด้านความปลอดภัย
|
||||
- bind เฉพาะกับ loopback หรืออินเทอร์เฟซส่วนตัวที่เชื่อถือได้
|
||||
- จำกัดการเข้าถึงเพื่อให้มีเพียงโปรเซส OpenClaw, โฮสต์, คอนเทนเนอร์ หรือบัญชีบริการเท่านั้นที่ใช้งานได้
|
||||
- แก้ชื่อปลายทางเองและบล็อก IP ปลายทางหลังการแก้ชื่อ DNS
|
||||
- ใช้นโยบาย ณ เวลาเชื่อมต่อสำหรับทั้งคำขอ HTTP แบบธรรมดาและ tunnel HTTPS `CONNECT`
|
||||
- ปฏิเสธการข้ามตามปลายทางสำหรับช่วง loopback, private, link-local, metadata, multicast, reserved หรือ documentation
|
||||
- หลีกเลี่ยง allowlist ชื่อโฮสต์ เว้นแต่คุณจะเชื่อถือเส้นทางการแก้ชื่อ DNS อย่างเต็มที่
|
||||
- บันทึกปลายทาง การตัดสินใจ สถานะ และเหตุผล โดยไม่บันทึกเนื้อหาคำขอ header การอนุญาต cookie หรือความลับอื่นๆ
|
||||
- เก็บนโยบายพร็อกซีไว้ในระบบควบคุมเวอร์ชันและรีวิวการเปลี่ยนแปลงเหมือนการกำหนดค่าที่อ่อนไหวด้านความปลอดภัย
|
||||
|
||||
## ปลายทางที่แนะนำให้บล็อก
|
||||
|
||||
ใช้รายการ denylist นี้เป็นจุดเริ่มต้นสำหรับพร็อกซีแบบส่งต่อ ไฟร์วอลล์ หรือนโยบายขาออกใดๆ
|
||||
ใช้ denylist นี้เป็นจุดเริ่มต้นสำหรับพร็อกซีส่งต่อ ไฟร์วอลล์ หรือนโยบายทราฟฟิกขาออกใดๆ
|
||||
|
||||
ตรรกะ classifier ระดับแอปพลิเคชันของ OpenClaw อยู่ใน `src/infra/net/ssrf.ts` และ `src/shared/net/ip.ts` parity hooks ที่เกี่ยวข้องคือ `BLOCKED_HOSTNAMES`, `BLOCKED_IPV4_SPECIAL_USE_RANGES`, `BLOCKED_IPV6_SPECIAL_USE_RANGES`, `RFC2544_BENCHMARK_PREFIX` และการจัดการ sentinel ของ IPv4 แบบฝังสำหรับ NAT64, 6to4, Teredo, ISATAP และรูปแบบ IPv4-mapped ไฟล์เหล่านี้เป็นข้อมูลอ้างอิงที่มีประโยชน์เมื่อดูแลนโยบายพร็อกซีภายนอก แต่ OpenClaw ไม่ได้ส่งออกหรือบังคับใช้กฎเหล่านั้นในพร็อกซีของคุณโดยอัตโนมัติ
|
||||
ตรรกะตัวจัดประเภทระดับแอปพลิเคชันของ OpenClaw อยู่ใน `src/infra/net/ssrf.ts` และ `src/shared/net/ip.ts` hook ที่เกี่ยวข้องสำหรับ parity คือ `BLOCKED_HOSTNAMES`, `BLOCKED_IPV4_SPECIAL_USE_RANGES`, `BLOCKED_IPV6_SPECIAL_USE_RANGES`, `RFC2544_BENCHMARK_PREFIX` และการจัดการ sentinel IPv4 แบบฝังสำหรับ NAT64, 6to4, Teredo, ISATAP และรูปแบบ IPv4-mapped ไฟล์เหล่านั้นเป็นข้อมูลอ้างอิงที่มีประโยชน์เมื่อดูแลนโยบายพร็อกซีภายนอก แต่ OpenClaw ไม่ได้ส่งออกหรือบังคับใช้กฎเหล่านั้นในพร็อกซีของคุณโดยอัตโนมัติ
|
||||
|
||||
| ช่วงหรือโฮสต์ | เหตุผลที่ต้องบล็อก |
|
||||
| ช่วงหรือโฮสต์ | เหตุผลที่ควรบล็อก |
|
||||
| ------------------------------------------------------------------------------------ | ---------------------------------------------------- |
|
||||
| `127.0.0.0/8`, `localhost`, `localhost.localdomain` | ลูปแบ็ก IPv4 |
|
||||
| `::1/128` | ลูปแบ็ก IPv6 |
|
||||
| `127.0.0.0/8`, `localhost`, `localhost.localdomain` | IPv4 loopback |
|
||||
| `::1/128` | IPv6 loopback |
|
||||
| `0.0.0.0/8`, `::/128` | ที่อยู่แบบไม่ระบุและที่อยู่ this-network |
|
||||
| `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16` | เครือข่ายส่วนตัว RFC1918 |
|
||||
| `169.254.0.0/16`, `fe80::/10` | ที่อยู่ link-local และเส้นทางเมทาดาทาคลาวด์ทั่วไป |
|
||||
| `169.254.169.254`, `metadata.google.internal` | บริการเมทาดาทาคลาวด์ |
|
||||
| `100.64.0.0/10` | พื้นที่ที่อยู่ร่วมของ NAT ระดับผู้ให้บริการ |
|
||||
| `169.254.0.0/16`, `fe80::/10` | ที่อยู่ link-local และเส้นทาง metadata ของคลาวด์ที่พบบ่อย |
|
||||
| `169.254.169.254`, `metadata.google.internal` | บริการ metadata ของคลาวด์ |
|
||||
| `100.64.0.0/10` | พื้นที่ที่อยู่ร่วมกันของ carrier-grade NAT |
|
||||
| `198.18.0.0/15`, `2001:2::/48` | ช่วงสำหรับ benchmarking |
|
||||
| `192.0.0.0/24`, `192.0.2.0/24`, `198.51.100.0/24`, `203.0.113.0/24`, `2001:db8::/32` | ช่วง special-use และเอกสารประกอบ |
|
||||
| `192.0.0.0/24`, `192.0.2.0/24`, `198.51.100.0/24`, `203.0.113.0/24`, `2001:db8::/32` | ช่วง special-use และ documentation |
|
||||
| `224.0.0.0/4`, `ff00::/8` | Multicast |
|
||||
| `240.0.0.0/4` | IPv4 ที่สงวนไว้ |
|
||||
| `fc00::/7`, `fec0::/10` | ช่วง IPv6 ภายใน/ส่วนตัว |
|
||||
| `100::/64`, `2001:20::/28` | ช่วง IPv6 discard และ ORCHIDv2 |
|
||||
| `64:ff9b::/96`, `64:ff9b:1::/48` | คำนำหน้า NAT64 ที่มี IPv4 ฝังอยู่ |
|
||||
| `fc00::/7`, `fec0::/10` | ช่วง local/private ของ IPv6 |
|
||||
| `100::/64`, `2001:20::/28` | ช่วง discard และ ORCHIDv2 ของ IPv6 |
|
||||
| `64:ff9b::/96`, `64:ff9b:1::/48` | prefix NAT64 ที่มี IPv4 ฝังอยู่ |
|
||||
| `2002::/16`, `2001::/32` | 6to4 และ Teredo ที่มี IPv4 ฝังอยู่ |
|
||||
| `::/96`, `::ffff:0:0/96` | IPv6 แบบเข้ากันได้กับ IPv4 และ IPv6 แบบ IPv4-mapped |
|
||||
| `::/96`, `::ffff:0:0/96` | IPv6 แบบ IPv4-compatible และ IPv4-mapped |
|
||||
|
||||
หากผู้ให้บริการคลาวด์หรือแพลตฟอร์มเครือข่ายของคุณจัดทำเอกสารโฮสต์เมทาดาทาหรือช่วงที่สงวนไว้เพิ่มเติม ให้เพิ่มรายการเหล่านั้นด้วย
|
||||
หากผู้ให้บริการคลาวด์หรือแพลตฟอร์มเครือข่ายของคุณมีเอกสารระบุโฮสต์ metadata หรือช่วงที่สงวนไว้เพิ่มเติม ให้เพิ่มรายการเหล่านั้นด้วย
|
||||
|
||||
## การตรวจสอบความถูกต้อง
|
||||
|
||||
@ -146,9 +146,9 @@ fallback ผ่านสภาพแวดล้อมเหมาะที่
|
||||
openclaw proxy validate --proxy-url http://127.0.0.1:3128
|
||||
```
|
||||
|
||||
โดยค่าเริ่มต้น เมื่อไม่ได้ระบุปลายทางแบบกำหนดเอง คำสั่งจะตรวจสอบว่า `https://example.com/` สำเร็จ และเริ่ม canary ลูปแบ็กชั่วคราวที่พร็อกซีต้องเข้าถึงไม่ได้ การตรวจสอบการปฏิเสธเริ่มต้นจะผ่านเมื่อพร็อกซีส่งคืนการตอบกลับปฏิเสธที่ไม่ใช่ 2xx หรือบล็อก canary ด้วยความล้มเหลวของทรานสปอร์ต; จะล้มเหลวหากการตอบกลับที่สำเร็จเข้าถึง canary หากไม่มีพร็อกซีที่เปิดใช้และกำหนดค่าไว้ การตรวจสอบความถูกต้องจะรายงานปัญหาการกำหนดค่า; ใช้ `--proxy-url` สำหรับ preflight แบบครั้งเดียวก่อนเปลี่ยนการกำหนดค่า ใช้ `--allowed-url` และ `--denied-url` เพื่อทดสอบความคาดหวังเฉพาะการปรับใช้ ปลายทางที่ถูกปฏิเสธแบบกำหนดเองจะล้มเหลวแบบปิดกั้น: การตอบกลับ HTTP ใดๆ หมายถึงปลายทางเข้าถึงได้ผ่านพร็อกซี และข้อผิดพลาดของทรานสปอร์ตใดๆ จะถูกรายงานว่าไม่สามารถสรุปได้ เพราะ OpenClaw ไม่สามารถพิสูจน์ได้ว่าพร็อกซีบล็อก origin ที่เข้าถึงได้ เมื่อการตรวจสอบความถูกต้องล้มเหลว คำสั่งจะออกด้วยรหัส 1
|
||||
โดยค่าเริ่มต้น เมื่อไม่ได้ระบุปลายทางแบบกำหนดเอง คำสั่งจะตรวจสอบว่า `https://example.com/` สำเร็จ และเริ่ม canary แบบ loopback ชั่วคราวที่พร็อกซีต้องไม่เข้าถึง การตรวจสอบที่คาดว่าถูกปฏิเสธโดยค่าเริ่มต้นจะผ่านเมื่อพร็อกซีส่งคืนการปฏิเสธแบบ non-2xx หรือบล็อก canary ด้วยความล้มเหลวของ transport; จะล้มเหลวหากการตอบกลับที่สำเร็จไปถึง canary หากไม่มีพร็อกซีที่เปิดใช้และกำหนดค่าไว้ การตรวจสอบจะรายงานปัญหา config; ใช้ `--proxy-url` สำหรับ preflight แบบครั้งเดียวก่อนเปลี่ยน config ใช้ `--allowed-url` และ `--denied-url` เพื่อทดสอบความคาดหวังเฉพาะการปรับใช้ ปลายทางที่ถูกปฏิเสธแบบกำหนดเองเป็นแบบ fail-closed: การตอบกลับ HTTP ใดๆ หมายความว่าปลายทางนั้นเข้าถึงได้ผ่านพร็อกซี และข้อผิดพลาด transport ใดๆ จะถูกรายงานว่าไม่สามารถสรุปได้ เพราะ OpenClaw ไม่สามารถพิสูจน์ได้ว่าพร็อกซีบล็อก origin ที่เข้าถึงได้ เมื่อการตรวจสอบล้มเหลว คำสั่งจะออกด้วยรหัส 1
|
||||
|
||||
ใช้ `--json` สำหรับระบบอัตโนมัติ เอาต์พุต JSON ประกอบด้วยผลลัพธ์โดยรวม แหล่งที่มาของการกำหนดค่าพร็อกซีที่มีผล ข้อผิดพลาดการกำหนดค่าใดๆ และการตรวจสอบปลายทางแต่ละรายการ ข้อมูลประจำตัวของ URL พร็อกซีจะถูกปกปิดในเอาต์พุตแบบข้อความและ JSON:
|
||||
ใช้ `--json` สำหรับการทำ automation เอาต์พุต JSON มีผลลัพธ์รวม แหล่งที่มาของ config พร็อกซีที่มีผล ข้อผิดพลาด config ใดๆ และการตรวจสอบแต่ละปลายทาง credential ใน URL พร็อกซีจะถูกปิดบังทั้งในเอาต์พุตข้อความและ JSON:
|
||||
|
||||
```json
|
||||
{
|
||||
@ -170,7 +170,7 @@ openclaw proxy validate --proxy-url http://127.0.0.1:3128
|
||||
}
|
||||
```
|
||||
|
||||
คุณยังสามารถตรวจสอบด้วยตนเองด้วย `curl`:
|
||||
คุณสามารถตรวจสอบด้วยตนเองด้วย `curl` ได้เช่นกัน:
|
||||
|
||||
```bash
|
||||
curl -x http://127.0.0.1:3128 https://example.com/
|
||||
@ -178,7 +178,7 @@ curl -x http://127.0.0.1:3128 http://127.0.0.1/
|
||||
curl -x http://127.0.0.1:3128 http://169.254.169.254/
|
||||
```
|
||||
|
||||
คำขอสาธารณะควรสำเร็จ คำขอ loopback และ metadata ควรถูกบล็อกโดยพร็อกซี สำหรับ `openclaw proxy validate` ตัวตรวจสอบ loopback canary ในตัวสามารถแยกการปฏิเสธจากพร็อกซีกับ origin ที่เข้าถึงได้ การตรวจสอบ `--denied-url` แบบกำหนดเองไม่มี canary ดังกล่าว ดังนั้นให้ถือว่าทั้งการตอบกลับ HTTP และความล้มเหลวด้านการขนส่งที่กำกวมเป็นความล้มเหลวในการตรวจสอบ เว้นแต่พร็อกซีของคุณจะเปิดเผยสัญญาณการปฏิเสธเฉพาะการปรับใช้ที่คุณสามารถตรวจสอบแยกต่างหากได้
|
||||
คำขอสาธารณะควรสำเร็จ ส่วนคำขอ loopback และ metadata ควรถูกพร็อกซีบล็อก สำหรับ `openclaw proxy validate` นั้น canary loopback ในตัวสามารถแยกแยะการปฏิเสธจากพร็อกซีออกจากต้นทางที่เข้าถึงได้ การตรวจสอบ `--denied-url` แบบกำหนดเองไม่มี canary ดังกล่าว ดังนั้นให้ถือว่าทั้งการตอบกลับ HTTP และความล้มเหลวด้านการส่งข้อมูลที่กำกวมเป็นความล้มเหลวของการตรวจสอบ เว้นแต่ว่าพร็อกซีของคุณเปิดเผยสัญญาณการปฏิเสธเฉพาะการปรับใช้ที่คุณสามารถตรวจสอบแยกต่างหากได้
|
||||
|
||||
จากนั้นเปิดใช้การกำหนดเส้นทางพร็อกซีของ OpenClaw:
|
||||
|
||||
@ -198,10 +198,11 @@ proxy:
|
||||
|
||||
## ขีดจำกัด
|
||||
|
||||
- พร็อกซีช่วยเพิ่มการครอบคลุมสำหรับไคลเอนต์ HTTP และ WebSocket ของ JavaScript ที่อยู่ภายในโปรเซส แต่ไม่ใช่ sandbox เครือข่ายระดับระบบปฏิบัติการ
|
||||
- ซ็อกเก็ต `net`, `tls` และ `http2` แบบดิบ, native addons และโปรเซสลูก อาจเลี่ยงการกำหนดเส้นทางพร็อกซีระดับ Node ได้ เว้นแต่จะสืบทอดและเคารพตัวแปรสภาพแวดล้อมของพร็อกซี
|
||||
- IRC เป็นช่องทาง TCP/TLS แบบดิบที่อยู่นอกการกำหนดเส้นทาง forward proxy ที่ผู้ปฏิบัติงานจัดการ ในการปรับใช้ที่กำหนดให้ egress ทั้งหมดผ่าน forward proxy นั้น ให้ตั้งค่า `channels.irc.enabled=false` เว้นแต่ egress ของ IRC โดยตรงจะได้รับอนุมัติอย่างชัดเจน
|
||||
- WebUI ภายในเครื่องของผู้ใช้และเซิร์ฟเวอร์โมเดลภายในเครื่องควรถูกเพิ่มใน allowlist ในนโยบายพร็อกซีของผู้ปฏิบัติงานเมื่อจำเป็น OpenClaw ไม่ได้เปิดเผยการข้ามเครือข่ายภายในเครื่องแบบทั่วไปสำหรับสิ่งเหล่านี้
|
||||
- การข้ามพร็อกซีของ control-plane ของ Gateway ถูกจำกัดไว้ที่ `localhost` และ URL IP loopback แบบระบุโดยตรงโดยเจตนา ใช้ `ws://127.0.0.1:18789`, `ws://[::1]:18789` หรือ `ws://localhost:18789` สำหรับการเชื่อมต่อ control-plane ของ Gateway โดยตรงภายในเครื่อง ชื่อโฮสต์อื่นจะถูกกำหนดเส้นทางเหมือนทราฟฟิกที่อิงตามชื่อโฮสต์ทั่วไป
|
||||
- พร็อกซีช่วยเพิ่มความครอบคลุมสำหรับไคลเอ็นต์ HTTP และ WebSocket ของ JavaScript ที่อยู่ภายในกระบวนการ แต่ไม่ใช่แซนด์บ็อกซ์เครือข่ายระดับ OS
|
||||
- ซ็อกเก็ต `net`, `tls`, และ `http2` แบบดิบ, native addons, และกระบวนการลูก อาจเลี่ยงการกำหนดเส้นทางพร็อกซีระดับ Node ได้ เว้นแต่ว่าจะสืบทอดและเคารพตัวแปรสภาพแวดล้อมของพร็อกซี
|
||||
- IRC เป็นช่องทาง TCP/TLS แบบดิบที่อยู่นอกการกำหนดเส้นทางผ่านพร็อกซีส่งต่อที่ผู้ปฏิบัติการจัดการ ในการปรับใช้ที่กำหนดให้อีเกรสทั้งหมดต้องผ่านพร็อกซีส่งต่อนั้น ให้ตั้งค่า `channels.irc.enabled=false` เว้นแต่ว่าอีเกรส IRC โดยตรงจะได้รับอนุมัติอย่างชัดเจน
|
||||
- พร็อกซีดีบักภายในเครื่องเป็นเครื่องมือวินิจฉัย และการส่งต่ออัปสตรีมโดยตรงสำหรับคำขอพร็อกซีและ CONNECT tunnels จะถูกปิดใช้งานตามค่าเริ่มต้นขณะที่โหมดพร็อกซีที่จัดการอยู่ทำงานอยู่ ให้เปิดใช้การส่งต่อโดยตรงเฉพาะสำหรับการวินิจฉัยภายในเครื่องที่ได้รับอนุมัติเท่านั้น
|
||||
- WebUI ภายในเครื่องของผู้ใช้และเซิร์ฟเวอร์โมเดลภายในเครื่องควรถูกเพิ่มลงในรายการอนุญาตในนโยบายพร็อกซีของผู้ปฏิบัติการเมื่อจำเป็น OpenClaw ไม่ได้เปิดเผยการเลี่ยงเครือข่ายภายในเครื่องแบบทั่วไปสำหรับสิ่งเหล่านี้
|
||||
- การเลี่ยงพร็อกซีของ control plane ของ Gateway ถูกจำกัดไว้ที่ `localhost` และ URL ที่เป็น IP loopback ตามตัวอักษรโดยตั้งใจ ใช้ `ws://127.0.0.1:18789`, `ws://[::1]:18789`, หรือ `ws://localhost:18789` สำหรับการเชื่อมต่อ control plane ของ Gateway ภายในเครื่องโดยตรง ชื่อโฮสต์อื่นจะถูกกำหนดเส้นทางเหมือนทราฟฟิกที่อิงตามชื่อโฮสต์ทั่วไป
|
||||
- OpenClaw ไม่ตรวจสอบ ทดสอบ หรือรับรองนโยบายพร็อกซีของคุณ
|
||||
- ให้ถือว่าการเปลี่ยนแปลงนโยบายพร็อกซีเป็นการเปลี่ยนแปลงการดำเนินงานที่อ่อนไหวด้านความปลอดภัย
|
||||
- ให้ถือว่าการเปลี่ยนแปลงนโยบายพร็อกซีเป็นการเปลี่ยนแปลงการปฏิบัติงานที่มีความอ่อนไหวด้านความปลอดภัย
|
||||
|
||||
@ -1,40 +1,46 @@
|
||||
---
|
||||
read_when:
|
||||
- คุณต้องการทำงานเบื้องหลังหรือทำงานแบบขนานผ่านเอเจนต์
|
||||
- คุณกำลังเปลี่ยนแปลง sessions_spawn หรือนโยบายของเครื่องมือตัวแทนย่อย
|
||||
- คุณกำลังนำเซสชันเอเจนต์ย่อยที่ผูกกับเธรดไปใช้ หรือกำลังแก้ไขปัญหาเซสชันดังกล่าว
|
||||
- คุณต้องการงานเบื้องหลังหรืองานแบบขนานผ่านเอเจนต์
|
||||
- คุณกำลังเปลี่ยนแปลง sessions_spawn หรือนโยบายเครื่องมือของเอเจนต์ย่อย
|
||||
- คุณกำลังพัฒนาหรือแก้ไขปัญหาเซสชันเอเจนต์ย่อยที่ผูกกับเธรด
|
||||
sidebarTitle: Sub-agents
|
||||
summary: สร้างการรันเอเจนต์พื้นหลังแบบแยกอิสระ ซึ่งประกาศผลลัพธ์กลับไปยังแชตของผู้ร้องขอ
|
||||
summary: เริ่มการรันเอเจนต์เบื้องหลังแบบแยกส่วน ซึ่งประกาศผลลัพธ์กลับไปยังแชตของผู้ร้องขอ
|
||||
title: เอเจนต์ย่อย
|
||||
x-i18n:
|
||||
generated_at: "2026-05-04T02:27:42Z"
|
||||
generated_at: "2026-05-04T07:07:15Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: d0df39e06b952def3eb0b296f36c7dc8c0b0a115785d865236a970c5d453fc37
|
||||
source_hash: 65d60bf6813d667b7311aa28109d4bd6be012a16e638c64cfff130831db88cd8
|
||||
source_path: tools/subagents.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
เอเจนต์ย่อยคือการรันเอเจนต์เบื้องหลังที่ถูกสร้างจากการรันเอเจนต์ที่มีอยู่
|
||||
เอเจนต์เหล่านี้รันในเซสชันของตัวเอง (`agent:<agentId>:subagent:<uuid>`) และ
|
||||
เมื่อเสร็จสิ้น จะ**ประกาศ**ผลลัพธ์กลับไปยังช่องแชตของผู้ร้องขอ
|
||||
เอเจนต์ย่อยจะทำงานในเซสชันของตัวเอง (`agent:<agentId>:subagent:<uuid>`) และ
|
||||
เมื่อเสร็จแล้วจะ **ประกาศ** ผลลัพธ์กลับไปยังช่องแชทของผู้ร้องขอ
|
||||
การรันเอเจนต์ย่อยแต่ละครั้งจะถูกติดตามเป็น
|
||||
[งานเบื้องหลัง](/th/automation/tasks)
|
||||
|
||||
เป้าหมายหลัก:
|
||||
|
||||
- ทำให้งาน "วิจัย / งานยาว / เครื่องมือที่ช้า" รันแบบขนานได้โดยไม่บล็อกการรันหลัก
|
||||
- แยกเอเจนต์ย่อยออกจากกันตามค่าเริ่มต้น (การแยกเซสชัน + sandboxing แบบเลือกได้)
|
||||
- ทำให้พื้นผิวเครื่องมือใช้งานผิดได้ยาก: เอเจนต์ย่อยจะ**ไม่ได้**รับเครื่องมือเซสชันตามค่าเริ่มต้น
|
||||
- รองรับความลึกของการซ้อนที่กำหนดค่าได้สำหรับรูปแบบ orchestrator
|
||||
- ทำงาน "ค้นคว้า / งานยาว / เครื่องมือช้า" แบบขนานโดยไม่บล็อกการรันหลัก
|
||||
- แยกเอเจนต์ย่อยโดยค่าเริ่มต้น (แยกเซสชัน + sandboxing ที่เลือกได้)
|
||||
- ทำให้พื้นผิวเครื่องมือถูกใช้งานผิดได้ยาก: เอเจนต์ย่อยจะไม่ได้รับเครื่องมือเซสชันโดยค่าเริ่มต้น
|
||||
- รองรับความลึกการซ้อนที่กำหนดค่าได้สำหรับรูปแบบ orchestrator
|
||||
|
||||
<Note>
|
||||
**หมายเหตุด้านต้นทุน:** เอเจนต์ย่อยแต่ละตัวมีบริบทและการใช้โทเค็นของตัวเองตามค่าเริ่มต้น สำหรับงานหนักหรืองานซ้ำ ให้ตั้งโมเดลที่ถูกกว่าสำหรับเอเจนต์ย่อยและคงเอเจนต์หลักไว้บนโมเดลคุณภาพสูงกว่า กำหนดค่าผ่าน `agents.defaults.subagents.model` หรือการ override รายเอเจนต์ เมื่อลูกต้องการ transcript ปัจจุบันของผู้ร้องขอจริง ๆ เอเจนต์สามารถขอ `context: "fork"` สำหรับการ spawn ครั้งนั้นได้ เซสชัน subagent ที่ผูกกับเธรดมีค่าเริ่มต้นเป็น `context: "fork"` เพราะจะแตกกิ่งบทสนทนาปัจจุบันไปยังเธรดติดตามผล
|
||||
**หมายเหตุเรื่องต้นทุน:** โดยค่าเริ่มต้น เอเจนต์ย่อยแต่ละตัวมีบริบทและการใช้โทเค็นของตัวเอง
|
||||
สำหรับงานหนักหรืองานที่ทำซ้ำ ให้ตั้งโมเดลที่ถูกกว่าสำหรับเอเจนต์ย่อย
|
||||
และให้เอเจนต์หลักใช้โมเดลคุณภาพสูงกว่า กำหนดค่าผ่าน
|
||||
`agents.defaults.subagents.model` หรือการ override รายเอเจนต์ เมื่อเอเจนต์ลูก
|
||||
ต้องการทรานสคริปต์ปัจจุบันของผู้ร้องขอจริง ๆ เอเจนต์สามารถขอ
|
||||
`context: "fork"` สำหรับการ spawn ครั้งนั้นได้ เซสชันเอเจนต์ย่อยที่ผูกกับเธรดมีค่าเริ่มต้นเป็น
|
||||
`context: "fork"` เพราะจะแตกแขนงบทสนทนาปัจจุบันไปยังเธรดติดตามผล
|
||||
</Note>
|
||||
|
||||
## คำสั่ง slash
|
||||
## คำสั่ง Slash
|
||||
|
||||
ใช้ `/subagents` เพื่อตรวจสอบหรือควบคุมการรันเอเจนต์ย่อยสำหรับ**เซสชันปัจจุบัน**:
|
||||
ใช้ `/subagents` เพื่อตรวจสอบหรือควบคุมการรันเอเจนต์ย่อยสำหรับ **เซสชันปัจจุบัน**:
|
||||
|
||||
```text
|
||||
/subagents list
|
||||
@ -46,15 +52,17 @@ x-i18n:
|
||||
/subagents spawn <agentId> <task> [--model <model>] [--thinking <level>]
|
||||
```
|
||||
|
||||
ใช้ [`/steer <message>`](/th/tools/steer) ระดับบนสุดเพื่อ steer การรันที่ใช้งานอยู่ของเซสชันผู้ร้องขอปัจจุบัน ใช้ `/subagents steer <id|#> <message>` เมื่อเป้าหมายเป็นการรันลูก
|
||||
ใช้ [`/steer <message>`](/th/tools/steer) ระดับบนสุดเพื่อบังคับทิศทางการรันที่ใช้งานอยู่ของเซสชันผู้ร้องขอปัจจุบัน ใช้ `/subagents steer <id|#> <message>` เมื่อเป้าหมายเป็นการรันลูก
|
||||
|
||||
`/subagents info` แสดงข้อมูลเมตาของการรัน (สถานะ, timestamp, id เซสชัน,
|
||||
พาธ transcript, cleanup) ใช้ `sessions_history` สำหรับมุมมองการเรียกดูย้อนหลังที่มีขอบเขตและผ่านการกรองความปลอดภัยแล้ว; ตรวจสอบพาธ transcript บนดิสก์เมื่อคุณต้องการ transcript ฉบับเต็มแบบดิบ
|
||||
`/subagents info` แสดงเมทาดาทาของการรัน (สถานะ, เวลา, id เซสชัน,
|
||||
พาธทรานสคริปต์, การล้างข้อมูล) ใช้ `sessions_history` สำหรับมุมมองการเรียกคืนแบบจำกัดขอบเขต
|
||||
และกรองความปลอดภัยแล้ว ตรวจสอบพาธทรานสคริปต์บนดิสก์เมื่อคุณ
|
||||
ต้องการทรานสคริปต์เต็มดิบ
|
||||
|
||||
### การควบคุมการผูกเธรด
|
||||
|
||||
คำสั่งเหล่านี้ทำงานบนช่องที่รองรับการผูกเธรดแบบคงอยู่
|
||||
ดู [ช่องที่รองรับเธรด](#thread-supporting-channels) ด้านล่าง
|
||||
คำสั่งเหล่านี้ทำงานบนช่องทางที่รองรับการผูกเธรดแบบถาวร
|
||||
ดู [ช่องทางที่รองรับเธรด](#thread-supporting-channels) ด้านล่าง
|
||||
|
||||
```text
|
||||
/focus <subagent-label|session-key|session-id|session-label>
|
||||
@ -64,74 +72,79 @@ x-i18n:
|
||||
/session max-age <duration|off>
|
||||
```
|
||||
|
||||
### พฤติกรรมการ spawn
|
||||
### พฤติกรรมการ Spawn
|
||||
|
||||
`/subagents spawn` เริ่มเอเจนต์ย่อยเบื้องหลังในฐานะคำสั่งของผู้ใช้ (ไม่ใช่ relay ภายใน) และส่งการอัปเดตการเสร็จสิ้นขั้นสุดท้ายหนึ่งครั้งกลับไปยังแชตของผู้ร้องขอเมื่อการรันเสร็จสิ้น
|
||||
`/subagents spawn` เริ่มเอเจนต์ย่อยเบื้องหลังในฐานะคำสั่งของผู้ใช้ (ไม่ใช่
|
||||
relay ภายใน) และส่งอัปเดตการเสร็จสิ้นสุดท้ายหนึ่งครั้งกลับไปยัง
|
||||
แชทของผู้ร้องขอเมื่อการรันเสร็จสิ้น
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Non-blocking, push-based completion">
|
||||
- คำสั่ง spawn ไม่บล็อก; จะคืน id การรันทันที
|
||||
- เมื่อเสร็จสิ้น เอเจนต์ย่อยจะประกาศข้อความสรุป/ผลลัพธ์กลับไปยังช่องแชตของผู้ร้องขอ
|
||||
- การเสร็จสิ้นเป็นแบบ push-based หลังจาก spawn แล้ว อย่า poll `/subagents list`, `sessions_list`, หรือ `sessions_history` เป็นลูปเพียงเพื่อรอให้เสร็จ; ตรวจสอบสถานะเฉพาะเมื่อจำเป็นสำหรับการดีบักหรือการแทรกแซง
|
||||
- เมื่อเสร็จสิ้น OpenClaw จะพยายามปิดแท็บ/โปรเซสเบราว์เซอร์ที่ติดตามไว้ซึ่งเปิดโดยเซสชันเอเจนต์ย่อยนั้นก่อนที่โฟลว์ cleanup ของการประกาศจะดำเนินต่อ
|
||||
- คำสั่ง spawn เป็นแบบไม่บล็อก และจะคืน id การรันทันที
|
||||
- เมื่อเสร็จสิ้น เอเจนต์ย่อยจะประกาศข้อความสรุป/ผลลัพธ์กลับไปยังช่องแชทของผู้ร้องขอ
|
||||
- การเสร็จสิ้นเป็นแบบ push-based เมื่อ spawn แล้ว อย่า poll `/subagents list`, `sessions_list`, หรือ `sessions_history` ในลูปเพียงเพื่อรอให้เสร็จ ให้ตรวจสอบสถานะเฉพาะเมื่อจำเป็นสำหรับการดีบักหรือการแทรกแซงเท่านั้น
|
||||
- เมื่อเสร็จสิ้น OpenClaw จะพยายามปิดแท็บเบราว์เซอร์/โปรเซสที่ติดตามไว้ซึ่งเปิดโดยเซสชันเอเจนต์ย่อยนั้น ก่อนที่โฟลว์การล้างข้อมูลของการประกาศจะดำเนินต่อ
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Manual-spawn delivery resilience">
|
||||
- OpenClaw ลองส่งมอบ `agent` โดยตรงก่อนด้วย idempotency key ที่เสถียร
|
||||
- หากการส่งมอบโดยตรงล้มเหลว จะ fallback ไปใช้การ routing ผ่านคิว
|
||||
- หากการ routing ผ่านคิวยังใช้ไม่ได้ การประกาศจะถูก retry ด้วย exponential backoff สั้น ๆ ก่อนยอมแพ้ขั้นสุดท้าย
|
||||
- การส่งมอบเมื่อเสร็จสิ้นจะคง route ของผู้ร้องขอที่ resolve แล้ว: route การเสร็จสิ้นที่ผูกกับเธรดหรือผูกกับบทสนทนาจะชนะเมื่อมีให้ใช้; หากต้นทางการเสร็จสิ้นให้มาเพียง channel, OpenClaw จะเติม target/account ที่หายไปจาก route ที่ resolve แล้วของเซสชันผู้ร้องขอ (`lastChannel` / `lastTo` / `lastAccountId`) เพื่อให้การส่งมอบโดยตรงยังทำงานได้
|
||||
- OpenClaw จะลองส่งแบบ `agent` โดยตรงก่อนด้วยคีย์ idempotency ที่เสถียร
|
||||
- หากรอบการเสร็จสิ้นของเอเจนต์ผู้ร้องขอล้มเหลว ไม่มีเอาต์พุตที่มองเห็นได้ หรือคืน prefix ที่ไม่สมบูรณ์อย่างชัดเจนของผลลัพธ์ลูกที่จับไว้ OpenClaw จะ fallback ไปส่งการเสร็จสิ้นโดยตรงจากผลลัพธ์ลูกที่จับไว้
|
||||
- หากใช้การส่งโดยตรงไม่ได้ จะ fallback ไปยังการกำหนดเส้นทางผ่านคิว
|
||||
- หากการกำหนดเส้นทางผ่านคิวยังใช้ไม่ได้ การประกาศจะถูกลองซ้ำด้วย exponential backoff สั้น ๆ ก่อนยอมแพ้ขั้นสุดท้าย
|
||||
- การส่งการเสร็จสิ้นจะรักษาเส้นทางผู้ร้องขอที่ resolve แล้ว: เส้นทางการเสร็จสิ้นที่ผูกกับเธรดหรือผูกกับบทสนทนาจะชนะเมื่อพร้อมใช้งาน หากต้นทางการเสร็จสิ้นให้มาเฉพาะช่องทาง OpenClaw จะเติมเป้าหมาย/บัญชีที่ขาดจากเส้นทางที่ resolve แล้วของเซสชันผู้ร้องขอ (`lastChannel` / `lastTo` / `lastAccountId`) เพื่อให้การส่งโดยตรงยังทำงานได้
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Completion handoff metadata">
|
||||
การ handoff การเสร็จสิ้นไปยังเซสชันผู้ร้องขอเป็นบริบทภายในที่สร้างโดย runtime (ไม่ใช่ข้อความที่ผู้ใช้เขียน) และประกอบด้วย:
|
||||
การส่งมอบการเสร็จสิ้นให้เซสชันผู้ร้องขอเป็นบริบทภายในที่ runtime สร้างขึ้น
|
||||
(ไม่ใช่ข้อความที่ผู้ใช้เขียน) และประกอบด้วย:
|
||||
|
||||
- `Result` — ข้อความตอบกลับ `assistant` ที่มองเห็นล่าสุด มิฉะนั้นเป็นข้อความ tool/toolResult ล่าสุดที่ sanitize แล้ว การรันที่ล้มเหลวแบบสิ้นสุดจะไม่นำข้อความตอบกลับที่จับไว้กลับมาใช้ซ้ำ
|
||||
- `Result` — ข้อความตอบกลับ `assistant` ล่าสุดที่มองเห็นได้ มิฉะนั้นเป็นข้อความ tool/toolResult ล่าสุดที่ผ่านการทำให้ปลอดภัยแล้ว การรันที่ล้มเหลวแบบ terminal จะไม่นำข้อความตอบกลับที่จับไว้มาใช้ซ้ำ
|
||||
- `Status` — `completed successfully` / `failed` / `timed out` / `unknown`
|
||||
- สถิติ runtime/token แบบย่อ
|
||||
- คำสั่งการส่งมอบที่บอกเอเจนต์ผู้ร้องขอให้เขียนใหม่ด้วยเสียง assistant ปกติ (ไม่ส่งต่อ metadata ภายในแบบดิบ)
|
||||
- สถิติ runtime/โทเค็นแบบกระชับ
|
||||
- คำสั่งการส่งที่บอกเอเจนต์ผู้ร้องขอให้เขียนใหม่ด้วยเสียงผู้ช่วยปกติ (ไม่ส่งต่อเมทาดาทาภายในแบบดิบ)
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Modes and ACP runtime">
|
||||
- `--model` และ `--thinking` override ค่าเริ่มต้นสำหรับการรันนั้นโดยเฉพาะ
|
||||
- ใช้ `info`/`log` เพื่อตรวจสอบรายละเอียดและเอาต์พุตหลังเสร็จสิ้น
|
||||
- `/subagents spawn` เป็นโหมด one-shot (`mode: "run"`) สำหรับเซสชันแบบคงอยู่ที่ผูกกับเธรด ให้ใช้ `sessions_spawn` พร้อม `thread: true` และ `mode: "session"`
|
||||
- สำหรับเซสชัน harness ของ ACP (Claude Code, Gemini CLI, OpenCode, หรือ Codex ACP/acpx ที่ระบุชัดเจน) ให้ใช้ `sessions_spawn` พร้อม `runtime: "acp"` เมื่อเครื่องมือประกาศ runtime นั้น ดู [โมเดลการส่งมอบของ ACP](/th/tools/acp-agents#delivery-model) เมื่อดีบักการเสร็จสิ้นหรือลูป agent-to-agent เมื่อเปิดใช้งาน Plugin `codex` การควบคุมแชต/เธรดของ Codex ควรเลือกใช้ `/codex ...` แทน ACP เว้นแต่ผู้ใช้จะขอ ACP/acpx อย่างชัดเจน
|
||||
- OpenClaw ซ่อน `runtime: "acp"` จนกว่า ACP จะเปิดใช้งาน ผู้ร้องขอไม่ได้อยู่ใน sandbox และมีการโหลด Plugin backend เช่น `acpx` แล้ว `runtime: "acp"` คาดหวัง id harness ACP ภายนอก หรือรายการ `agents.list[]` ที่มี `runtime.type="acp"`; ใช้ runtime เอเจนต์ย่อยค่าเริ่มต้นสำหรับเอเจนต์ config ของ OpenClaw ปกติจาก `agents_list`
|
||||
- ใช้ `info`/`log` เพื่อตรวจสอบรายละเอียดและเอาต์พุตหลังจากเสร็จสิ้น
|
||||
- `/subagents spawn` เป็นโหมด one-shot (`mode: "run"`) สำหรับเซสชันถาวรที่ผูกกับเธรด ให้ใช้ `sessions_spawn` พร้อม `thread: true` และ `mode: "session"`
|
||||
- สำหรับเซสชัน ACP harness (Claude Code, Gemini CLI, OpenCode หรือ Codex ACP/acpx ที่ระบุชัดเจน) ให้ใช้ `sessions_spawn` พร้อม `runtime: "acp"` เมื่อเครื่องมือประกาศ runtime นั้น ดู [โมเดลการส่งของ ACP](/th/tools/acp-agents#delivery-model) เมื่อดีบักการเสร็จสิ้นหรือลูปเอเจนต์ต่อเอเจนต์ เมื่อเปิดใช้งาน Plugin `codex` การควบคุมแชท/เธรด Codex ควรเลือกใช้ `/codex ...` แทน ACP เว้นแต่ผู้ใช้จะขอ ACP/acpx อย่างชัดเจน
|
||||
- OpenClaw ซ่อน `runtime: "acp"` จนกว่าจะเปิดใช้งาน ACP, ผู้ร้องขอไม่ได้อยู่ใน sandbox และมีการโหลด Plugin แบ็กเอนด์ เช่น `acpx` แล้ว `runtime: "acp"` คาดหวัง id ของ ACP harness ภายนอก หรือรายการ `agents.list[]` ที่มี `runtime.type="acp"`; ใช้ runtime เอเจนต์ย่อยเริ่มต้นสำหรับเอเจนต์ config ปกติของ OpenClaw จาก `agents_list`
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## โหมดบริบท
|
||||
|
||||
เอเจนต์ย่อยแบบ native จะเริ่มแบบแยกเดี่ยว เว้นแต่ผู้เรียกจะขอ fork
|
||||
transcript ปัจจุบันอย่างชัดเจน
|
||||
เอเจนต์ย่อยแบบ native เริ่มแบบแยกเดี่ยว เว้นแต่ผู้เรียกจะขอ fork
|
||||
ทรานสคริปต์ปัจจุบันอย่างชัดเจน
|
||||
|
||||
| โหมด | ควรใช้เมื่อใด | พฤติกรรม |
|
||||
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
|
||||
| `isolated` | การวิจัยใหม่, การ implementation อิสระ, งานเครื่องมือที่ช้า, หรือสิ่งใดก็ตามที่สามารถสรุปในข้อความงานได้ | สร้าง transcript ลูกที่สะอาด นี่คือค่าเริ่มต้นและช่วยลดการใช้โทเค็น |
|
||||
| `fork` | งานที่ขึ้นกับบทสนทนาปัจจุบัน, ผลลัพธ์เครื่องมือก่อนหน้า, หรือคำสั่งที่ละเอียดอ่อนซึ่งมีอยู่แล้วใน transcript ของผู้ร้องขอ | แตกกิ่ง transcript ของผู้ร้องขอไปยังเซสชันลูกก่อนที่ลูกจะเริ่ม |
|
||||
| `isolated` | การค้นคว้าใหม่, การนำไปใช้ที่เป็นอิสระ, งานเครื่องมือช้า หรือสิ่งใดก็ตามที่สรุปงานในข้อความงานได้ | สร้างทรานสคริปต์ลูกใหม่สะอาด นี่คือค่าเริ่มต้นและช่วยลดการใช้โทเค็น |
|
||||
| `fork` | งานที่ขึ้นกับบทสนทนาปัจจุบัน, ผลลัพธ์เครื่องมือก่อนหน้า หรือคำสั่งที่มีรายละเอียดอ่อนซึ่งมีอยู่แล้วในทรานสคริปต์ของผู้ร้องขอ | แตกแขนงทรานสคริปต์ของผู้ร้องขอเข้าสู่เซสชันลูกก่อนที่ลูกจะเริ่ม |
|
||||
|
||||
ใช้ `fork` อย่างประหยัด มีไว้สำหรับการมอบหมายงานที่อ่อนไหวต่อบริบท ไม่ใช่
|
||||
สิ่งทดแทนการเขียน prompt งานที่ชัดเจน
|
||||
ใช้ `fork` เท่าที่จำเป็น ใช้สำหรับการมอบหมายงานที่ไวต่อบริบท ไม่ใช่
|
||||
สิ่งทดแทนการเขียนพรอมป์งานที่ชัดเจน
|
||||
|
||||
## เครื่องมือ: `sessions_spawn`
|
||||
|
||||
เริ่มการรันเอเจนต์ย่อยด้วย `deliver: false` บน lane `subagent` ระดับ global
|
||||
จากนั้นรันขั้นตอนประกาศและโพสต์คำตอบประกาศไปยังช่องแชตของผู้ร้องขอ
|
||||
เริ่มการรันเอเจนต์ย่อยด้วย `deliver: false` บนเลน `subagent` ส่วนกลาง
|
||||
จากนั้นรันขั้นตอนประกาศและโพสต์คำตอบประกาศไปยังช่องแชทของผู้ร้องขอ
|
||||
|
||||
ความพร้อมใช้งานขึ้นอยู่กับนโยบายเครื่องมือที่มีผลของผู้เรียก โปรไฟล์ `coding` และ
|
||||
`full` เปิดเผย `sessions_spawn` ตามค่าเริ่มต้น โปรไฟล์ `messaging`
|
||||
ไม่เปิดเผย; เพิ่ม `tools.alsoAllow: ["sessions_spawn", "sessions_yield",
|
||||
"subagents"]` หรือใช้ `tools.profile: "coding"` สำหรับเอเจนต์ที่ควรมอบหมายงานได้
|
||||
นโยบาย allow/deny ของ channel/group, provider, sandbox และรายเอเจนต์ยังสามารถ
|
||||
ลบเครื่องมือนี้หลังขั้นตอนโปรไฟล์ได้ ใช้ `/tools` จากเซสชันเดียวกันเพื่อยืนยันรายการเครื่องมือที่มีผล
|
||||
ความพร้อมใช้งานขึ้นกับนโยบายเครื่องมือที่มีผลของผู้เรียก โปรไฟล์ `coding` และ
|
||||
`full` เปิดเผย `sessions_spawn` โดยค่าเริ่มต้น โปรไฟล์ `messaging`
|
||||
ไม่เปิดเผย ให้เพิ่ม `tools.alsoAllow: ["sessions_spawn", "sessions_yield",
|
||||
"subagents"]` หรือใช้ `tools.profile: "coding"` สำหรับเอเจนต์ที่ควรมอบหมาย
|
||||
งาน นโยบายช่องทาง/กลุ่ม, provider, sandbox และ allow/deny รายเอเจนต์ยังสามารถ
|
||||
นำเครื่องมือออกหลังขั้นโปรไฟล์ได้ ใช้ `/tools` จากเซสชันเดียวกัน
|
||||
เพื่อยืนยันรายการเครื่องมือที่มีผล
|
||||
|
||||
**ค่าเริ่มต้น:**
|
||||
|
||||
- **โมเดล:** สืบทอดจากผู้เรียก เว้นแต่คุณตั้ง `agents.defaults.subagents.model` (หรือ `agents.list[].subagents.model` รายเอเจนต์); `sessions_spawn.model` ที่ระบุชัดเจนยังคงชนะ
|
||||
- **Thinking:** สืบทอดจากผู้เรียก เว้นแต่คุณตั้ง `agents.defaults.subagents.thinking` (หรือ `agents.list[].subagents.thinking` รายเอเจนต์); `sessions_spawn.thinking` ที่ระบุชัดเจนยังคงชนะ
|
||||
- **ระยะหมดเวลาการรัน:** หากละ `sessions_spawn.runTimeoutSeconds`, OpenClaw จะใช้ `agents.defaults.subagents.runTimeoutSeconds` เมื่อมีการตั้งค่าไว้; มิฉะนั้นจะ fallback เป็น `0` (ไม่มี timeout)
|
||||
- **ไทม์เอาต์การรัน:** หากละ `sessions_spawn.runTimeoutSeconds` ไว้ OpenClaw จะใช้ `agents.defaults.subagents.runTimeoutSeconds` เมื่อมีการตั้งค่า มิฉะนั้นจะ fallback เป็น `0` (ไม่มีไทม์เอาต์)
|
||||
|
||||
### พารามิเตอร์เครื่องมือ
|
||||
|
||||
@ -139,144 +152,145 @@ transcript ปัจจุบันอย่างชัดเจน
|
||||
คำอธิบายงานสำหรับเอเจนต์ย่อย
|
||||
</ParamField>
|
||||
<ParamField path="label" type="string">
|
||||
ป้ายกำกับที่มนุษย์อ่านได้แบบเลือกได้
|
||||
ป้ายกำกับที่มนุษย์อ่านได้ซึ่งเป็นทางเลือก
|
||||
</ParamField>
|
||||
<ParamField path="agentId" type="string">
|
||||
Spawn ภายใต้ id เอเจนต์อื่นเมื่อ `subagents.allowAgents` อนุญาต
|
||||
Spawn ภายใต้ id เอเจนต์อื่นเมื่อได้รับอนุญาตโดย `subagents.allowAgents`
|
||||
</ParamField>
|
||||
<ParamField path="runtime" type='"subagent" | "acp"' default="subagent">
|
||||
`acp` ใช้เฉพาะสำหรับ harness ACP ภายนอก (`claude`, `droid`, `gemini`, `opencode`, หรือ Codex ACP/acpx ที่ร้องขออย่างชัดเจน) และสำหรับรายการ `agents.list[]` ที่ `runtime.type` เป็น `acp`
|
||||
`acp` ใช้เฉพาะสำหรับ ACP harness ภายนอก (`claude`, `droid`, `gemini`, `opencode` หรือ Codex ACP/acpx ที่ขออย่างชัดเจน) และสำหรับรายการ `agents.list[]` ที่ `runtime.type` เป็น `acp`
|
||||
</ParamField>
|
||||
<ParamField path="resumeSessionId" type="string">
|
||||
เฉพาะ ACP Resume เซสชัน harness ACP ที่มีอยู่เมื่อ `runtime: "acp"`; ถูกละเว้นสำหรับการ spawn เอเจนต์ย่อยแบบ native
|
||||
เฉพาะ ACP เท่านั้น ดำเนินเซสชัน ACP harness ที่มีอยู่ต่อเมื่อ `runtime: "acp"`; ถูกละเว้นสำหรับการ spawn เอเจนต์ย่อยแบบ native
|
||||
</ParamField>
|
||||
<ParamField path="streamTo" type='"parent"'>
|
||||
เฉพาะ ACP สตรีมเอาต์พุตการรัน ACP ไปยังเซสชันแม่เมื่อ `runtime: "acp"`; ละเว้นสำหรับการ spawn เอเจนต์ย่อยแบบ native
|
||||
เฉพาะ ACP เท่านั้น สตรีมเอาต์พุตการรัน ACP ไปยังเซสชันแม่เมื่อ `runtime: "acp"`; ละไว้สำหรับการ spawn เอเจนต์ย่อยแบบ native
|
||||
</ParamField>
|
||||
<ParamField path="model" type="string">
|
||||
Override โมเดลเอเจนต์ย่อย ค่าที่ไม่ถูกต้องจะถูกข้ามและเอเจนต์ย่อยจะรันบนโมเดลค่าเริ่มต้นพร้อมคำเตือนในผลลัพธ์เครื่องมือ
|
||||
Override โมเดลเอเจนต์ย่อย ค่าที่ไม่ถูกต้องจะถูกข้ามและเอเจนต์ย่อยจะรันบนโมเดลเริ่มต้นพร้อมคำเตือนในผลลัพธ์เครื่องมือ
|
||||
</ParamField>
|
||||
<ParamField path="thinking" type="string">
|
||||
Override ระดับ thinking สำหรับการรันเอเจนต์ย่อย
|
||||
</ParamField>
|
||||
<ParamField path="runTimeoutSeconds" type="number">
|
||||
ค่าเริ่มต้นเป็น `agents.defaults.subagents.runTimeoutSeconds` เมื่อมีการตั้งค่า มิฉะนั้นเป็น `0` เมื่อมีการตั้งค่า การรันเอเจนต์ย่อยจะถูก abort หลัง N วินาที
|
||||
ค่าเริ่มต้นเป็น `agents.defaults.subagents.runTimeoutSeconds` เมื่อมีการตั้งค่า มิฉะนั้นเป็น `0` เมื่อตั้งค่าแล้ว การรันเอเจนต์ย่อยจะถูกยกเลิกหลังจาก N วินาที
|
||||
</ParamField>
|
||||
<ParamField path="thread" type="boolean" default="false">
|
||||
เมื่อเป็น `true` จะขอการผูกเธรดของช่องสำหรับเซสชันเอเจนต์ย่อยนี้
|
||||
เมื่อเป็น `true` จะขอการผูกเธรดของช่องทางสำหรับเซสชันเอเจนต์ย่อยนี้
|
||||
</ParamField>
|
||||
<ParamField path="mode" type='"run" | "session"' default="run">
|
||||
หากละ `thread: true` และ `mode` ค่าเริ่มต้นจะกลายเป็น `session` `mode: "session"` ต้องใช้ `thread: true`
|
||||
หาก `thread: true` และละ `mode` ไว้ ค่าเริ่มต้นจะกลายเป็น `session` `mode: "session"` ต้องใช้ `thread: true`
|
||||
</ParamField>
|
||||
<ParamField path="cleanup" type='"delete" | "keep"' default="keep">
|
||||
`"delete"` archive ทันทีหลังประกาศ (ยังคงเก็บ transcript ไว้ผ่านการเปลี่ยนชื่อ)
|
||||
`"delete"` จะเก็บถาวรทันทีหลังประกาศ (ยังคงเก็บทรานสคริปต์ไว้ผ่านการเปลี่ยนชื่อ)
|
||||
</ParamField>
|
||||
<ParamField path="sandbox" type='"inherit" | "require"' default="inherit">
|
||||
`require` ปฏิเสธการ spawn เว้นแต่ runtime ลูกเป้าหมายอยู่ใน sandbox
|
||||
`require` ปฏิเสธการ spawn เว้นแต่ runtime ลูกเป้าหมายจะอยู่ใน sandbox
|
||||
</ParamField>
|
||||
<ParamField path="context" type='"isolated" | "fork"' default="isolated">
|
||||
`fork` แตกกิ่ง transcript ปัจจุบันของผู้ร้องขอไปยังเซสชันลูก เอเจนต์ย่อยแบบ native เท่านั้น การ spawn ที่ผูกกับเธรดมีค่าเริ่มต้นเป็น `fork`; การ spawn ที่ไม่ใช่เธรดมีค่าเริ่มต้นเป็น `isolated`
|
||||
`fork` แตกแขนงทรานสคริปต์ปัจจุบันของผู้ร้องขอเข้าสู่เซสชันลูก เฉพาะเอเจนต์ย่อยแบบ native เท่านั้น การ spawn ที่ผูกกับเธรดมีค่าเริ่มต้นเป็น `fork`; การ spawn ที่ไม่ใช่เธรดมีค่าเริ่มต้นเป็น `isolated`
|
||||
</ParamField>
|
||||
|
||||
<Warning>
|
||||
`sessions_spawn` ไม่รับพารามิเตอร์การส่งมอบผ่านช่อง (`target`,
|
||||
`channel`, `to`, `threadId`, `replyTo`, `transport`) สำหรับการส่งมอบ ให้ใช้
|
||||
`sessions_spawn` ไม่รับพารามิเตอร์การส่งผ่านช่องทาง (`target`,
|
||||
`channel`, `to`, `threadId`, `replyTo`, `transport`) สำหรับการส่ง ให้ใช้
|
||||
`message`/`sessions_send` จากการรันที่ spawn แล้ว
|
||||
</Warning>
|
||||
|
||||
## เซสชันที่ผูกกับเธรด
|
||||
|
||||
เมื่อเปิดใช้งานการผูกเธรดสำหรับช่อง เอเจนต์ย่อยสามารถคงการผูกกับเธรดไว้ได้
|
||||
เพื่อให้ข้อความผู้ใช้ติดตามผลในเธรดนั้นยัง route ไปยังเซสชันเอเจนต์ย่อยเดียวกัน
|
||||
เมื่อเปิดใช้งานการผูกเธรดสำหรับช่องทาง เอเจนต์ย่อยสามารถคงการผูก
|
||||
กับเธรดไว้ เพื่อให้ข้อความผู้ใช้ติดตามผลในเธรดนั้นยังคงกำหนดเส้นทางไปยัง
|
||||
เซสชันเอเจนต์ย่อยเดียวกัน
|
||||
|
||||
### ช่องที่รองรับเธรด
|
||||
### ช่องทางที่รองรับเธรด
|
||||
|
||||
**Discord** เป็นช่องเดียวที่รองรับอยู่ในปัจจุบัน รองรับ
|
||||
เซสชัน subagent แบบคงอยู่ที่ผูกกับเธรด (`sessions_spawn` พร้อม
|
||||
**Discord** เป็นช่องทางเดียวที่รองรับในขณะนี้ รองรับ
|
||||
เซสชันเอเจนต์ย่อยที่ผูกกับเธรดแบบถาวร (`sessions_spawn` พร้อม
|
||||
`thread: true`), การควบคุมเธรดด้วยตนเอง (`/focus`, `/unfocus`, `/agents`,
|
||||
`/session idle`, `/session max-age`) และคีย์ adapter
|
||||
`/session idle`, `/session max-age`) และคีย์อะแดปเตอร์
|
||||
`channels.discord.threadBindings.enabled`,
|
||||
`channels.discord.threadBindings.idleHours`,
|
||||
`channels.discord.threadBindings.maxAgeHours`, และ
|
||||
`channels.discord.threadBindings.maxAgeHours` และ
|
||||
`channels.discord.threadBindings.spawnSessions`
|
||||
|
||||
### โฟลว์ด่วน
|
||||
|
||||
<Steps>
|
||||
<Step title="Spawn">
|
||||
`sessions_spawn` พร้อม `thread: true` (และ `mode: "session"` แบบเลือกได้)
|
||||
`sessions_spawn` พร้อม `thread: true` (และเลือกใส่ `mode: "session"` ได้)
|
||||
</Step>
|
||||
<Step title="Bind">
|
||||
OpenClaw สร้างหรือผูกเธรดกับ target ของเซสชันนั้นในช่องที่ใช้งานอยู่
|
||||
OpenClaw สร้างหรือผูกเธรดกับเป้าหมายเซสชันนั้นในช่องทางที่ใช้งานอยู่
|
||||
</Step>
|
||||
<Step title="Route follow-ups">
|
||||
การตอบกลับและข้อความติดตามผลในเธรดนั้น route ไปยังเซสชันที่ผูกไว้
|
||||
การตอบกลับและข้อความติดตามผลในเธรดนั้นจะถูกส่งต่อไปยังเซสชันที่ผูกไว้
|
||||
</Step>
|
||||
<Step title="Inspect timeouts">
|
||||
ใช้ `/session idle` เพื่อตรวจสอบ/อัปเดต auto-unfocus เมื่อไม่มีความเคลื่อนไหว และ
|
||||
`/session max-age` เพื่อควบคุม hard cap
|
||||
ใช้ `/session idle` เพื่อตรวจสอบ/อัปเดตการเลิกโฟกัสอัตโนมัติเมื่อไม่มีความเคลื่อนไหว และ
|
||||
`/session max-age` เพื่อควบคุมขีดจำกัดสูงสุดแบบตายตัว
|
||||
</Step>
|
||||
<Step title="Detach">
|
||||
ใช้ `/unfocus` เพื่อ detach ด้วยตนเอง
|
||||
ใช้ `/unfocus` เพื่อแยกออกด้วยตนเอง
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
### การควบคุมด้วยตนเอง
|
||||
|
||||
| คำสั่ง | ผลลัพธ์ |
|
||||
| คำสั่ง | ผลลัพธ์ |
|
||||
| ------------------ | --------------------------------------------------------------------- |
|
||||
| `/focus <target>` | ผูกเธรดปัจจุบัน (หรือสร้างเธรดใหม่) เข้ากับเป้าหมายเอเจนต์ย่อย/เซสชัน |
|
||||
| `/unfocus` | ลบการผูกสำหรับเธรดที่ถูกผูกอยู่ในปัจจุบัน |
|
||||
| `/agents` | แสดงรายการงานที่ทำงานอยู่และสถานะการผูก (`thread:<id>` หรือ `unbound`) |
|
||||
| `/session idle` | ตรวจสอบ/อัปเดตการยกเลิกโฟกัสอัตโนมัติเมื่อไม่ได้ใช้งาน (เฉพาะเธรดที่ถูกผูกและโฟกัสอยู่) |
|
||||
| `/session max-age` | ตรวจสอบ/อัปเดตขีดจำกัดสูงสุดแบบบังคับ (เฉพาะเธรดที่ถูกผูกและโฟกัสอยู่) |
|
||||
| `/focus <target>` | ผูกเธรดปัจจุบัน (หรือสร้างใหม่) กับเป้าหมาย sub-agent/เซสชัน |
|
||||
| `/unfocus` | ลบการผูกสำหรับเธรดที่ผูกอยู่ในปัจจุบัน |
|
||||
| `/agents` | แสดงรายการรันที่ใช้งานอยู่และสถานะการผูก (`thread:<id>` หรือ `unbound`) |
|
||||
| `/session idle` | ตรวจสอบ/อัปเดตการเลิกโฟกัสอัตโนมัติเมื่อว่าง (เฉพาะเธรดที่ผูกและโฟกัสอยู่) |
|
||||
| `/session max-age` | ตรวจสอบ/อัปเดตขีดจำกัดสูงสุดแบบตายตัว (เฉพาะเธรดที่ผูกและโฟกัสอยู่) |
|
||||
|
||||
### สวิตช์การกำหนดค่า
|
||||
|
||||
- **ค่าเริ่มต้นทั่วระบบ:** `session.threadBindings.enabled`, `session.threadBindings.idleHours`, `session.threadBindings.maxAgeHours`.
|
||||
- **คีย์แทนที่ระดับช่องทางและคีย์ผูกอัตโนมัติเมื่อสร้าง** ขึ้นอยู่กับอะแดปเตอร์ ดู [ช่องทางที่รองรับเธรด](#thread-supporting-channels) ด้านบน
|
||||
- **ค่าเริ่มต้นส่วนกลาง:** `session.threadBindings.enabled`, `session.threadBindings.idleHours`, `session.threadBindings.maxAgeHours`
|
||||
- **คีย์สำหรับการเขียนทับตามช่องทางและการผูกอัตโนมัติเมื่อ spawn** ขึ้นอยู่กับ adapter แต่ละตัว ดู [ช่องทางที่รองรับเธรด](#thread-supporting-channels) ด้านบน
|
||||
|
||||
ดู [ข้อมูลอ้างอิงการกำหนดค่า](/th/gateway/configuration-reference) และ
|
||||
[คำสั่ง Slash](/th/tools/slash-commands) สำหรับรายละเอียดอะแดปเตอร์ปัจจุบัน
|
||||
[คำสั่ง Slash](/th/tools/slash-commands) สำหรับรายละเอียด adapter ปัจจุบัน
|
||||
|
||||
### รายการที่อนุญาต
|
||||
### Allowlist
|
||||
|
||||
<ParamField path="agents.list[].subagents.allowAgents" type="string[]">
|
||||
รายการ ID เอเจนต์ที่สามารถกำหนดเป็นเป้าหมายผ่าน `agentId` แบบชัดเจน (`["*"]` อนุญาตทุกรายการ) ค่าเริ่มต้น: เฉพาะเอเจนต์ผู้ร้องขอ หากคุณตั้งค่ารายการและยังต้องการให้ผู้ร้องขอสร้างตัวเองด้วย `agentId` ให้ใส่ ID ของผู้ร้องขอไว้ในรายการ
|
||||
รายการ agent ids ที่สามารถกำหนดเป็นเป้าหมายผ่าน `agentId` แบบชัดเจน (`["*"]` อนุญาตทุกตัว) ค่าเริ่มต้น: เฉพาะเอเจนต์ผู้ร้องขอเท่านั้น หากคุณตั้งค่ารายการและยังต้องการให้ผู้ร้องขอ spawn ตัวเองด้วย `agentId` ให้ใส่ id ของผู้ร้องขอในรายการด้วย
|
||||
</ParamField>
|
||||
<ParamField path="agents.defaults.subagents.allowAgents" type="string[]">
|
||||
รายการเอเจนต์เป้าหมายเริ่มต้นที่อนุญาต ซึ่งใช้เมื่อเอเจนต์ผู้ร้องขอไม่ได้ตั้งค่า `subagents.allowAgents` ของตัวเอง
|
||||
allowlist ของเอเจนต์เป้าหมายเริ่มต้นที่ใช้เมื่อเอเจนต์ผู้ร้องขอไม่ได้ตั้งค่า `subagents.allowAgents` ของตัวเอง
|
||||
</ParamField>
|
||||
<ParamField path="agents.defaults.subagents.requireAgentId" type="boolean" default="false">
|
||||
บล็อกการเรียก `sessions_spawn` ที่ละ `agentId` (บังคับให้เลือกโปรไฟล์อย่างชัดเจน) การแทนที่รายเอเจนต์: `agents.list[].subagents.requireAgentId`
|
||||
บล็อกการเรียก `sessions_spawn` ที่ละ `agentId` (บังคับให้เลือกโปรไฟล์อย่างชัดเจน) การเขียนทับรายเอเจนต์: `agents.list[].subagents.requireAgentId`
|
||||
</ParamField>
|
||||
|
||||
หากเซสชันของผู้ร้องขออยู่ใน sandbox, `sessions_spawn` จะปฏิเสธเป้าหมาย
|
||||
ที่จะทำงานแบบไม่อยู่ใน sandbox
|
||||
หากเซสชันผู้ร้องขออยู่ใน sandbox, `sessions_spawn` จะปฏิเสธเป้าหมาย
|
||||
ที่จะรันแบบไม่อยู่ใน sandbox
|
||||
|
||||
### การค้นหา
|
||||
### การค้นพบ
|
||||
|
||||
ใช้ `agents_list` เพื่อดูว่า ID เอเจนต์ใดได้รับอนุญาตสำหรับ
|
||||
`sessions_spawn` อยู่ในขณะนี้ การตอบกลับมีโมเดลที่มีผลจริงของเอเจนต์แต่ละรายการ
|
||||
และเมทาดาทารันไทม์ที่ฝังอยู่ เพื่อให้ผู้เรียกแยกแยะ PI, เซิร์ฟเวอร์แอป Codex
|
||||
และรันไทม์เนทีฟอื่นที่กำหนดค่าไว้ได้
|
||||
ใช้ `agents_list` เพื่อดูว่า agent ids ใดได้รับอนุญาตสำหรับ
|
||||
`sessions_spawn` อยู่ในปัจจุบัน การตอบกลับจะรวมโมเดลที่มีผลจริงของแต่ละเอเจนต์ที่แสดง
|
||||
และข้อมูลเมตารันไทม์แบบฝัง เพื่อให้ผู้เรียกแยกแยะ PI, Codex
|
||||
app-server และ native runtimes อื่นที่กำหนดค่าไว้ได้
|
||||
|
||||
### การเก็บถาวรอัตโนมัติ
|
||||
|
||||
- เซสชันเอเจนต์ย่อยจะถูกเก็บถาวรโดยอัตโนมัติหลังจาก `agents.defaults.subagents.archiveAfterMinutes` (ค่าเริ่มต้น `60`)
|
||||
- เซสชัน sub-agent จะถูกเก็บถาวรโดยอัตโนมัติหลังจาก `agents.defaults.subagents.archiveAfterMinutes` (ค่าเริ่มต้น `60`)
|
||||
- การเก็บถาวรใช้ `sessions.delete` และเปลี่ยนชื่อทรานสคริปต์เป็น `*.deleted.<timestamp>` (โฟลเดอร์เดียวกัน)
|
||||
- `cleanup: "delete"` จะเก็บถาวรทันทีหลังประกาศ (ยังคงเก็บทรานสคริปต์ไว้ผ่านการเปลี่ยนชื่อ)
|
||||
- การเก็บถาวรอัตโนมัติเป็นแบบ best-effort; ตัวจับเวลาที่ค้างอยู่จะหายไปหาก Gateway รีสตาร์ท
|
||||
- `runTimeoutSeconds` จะไม่เก็บถาวรอัตโนมัติ; จะหยุดเฉพาะงานที่ทำงานอยู่เท่านั้น เซสชันยังคงอยู่จนกว่าจะเก็บถาวรอัตโนมัติ
|
||||
- การเก็บถาวรอัตโนมัติใช้กับเซสชันระดับความลึก 1 และระดับความลึก 2 เท่ากัน
|
||||
- การล้างเบราว์เซอร์แยกจากการล้างการเก็บถาวร: แท็บ/โปรเซสของเบราว์เซอร์ที่ติดตามไว้จะถูกปิดแบบ best-effort เมื่องานทำงานเสร็จ แม้จะเก็บระเบียนทรานสคริปต์/เซสชันไว้ก็ตาม
|
||||
- `cleanup: "delete"` จะเก็บถาวรทันทีหลังจากประกาศ (ยังคงเก็บทรานสคริปต์ไว้ผ่านการเปลี่ยนชื่อ)
|
||||
- การเก็บถาวรอัตโนมัติเป็นแบบ best-effort; ตัวจับเวลาที่ค้างอยู่จะหายไปหาก gateway รีสตาร์ท
|
||||
- `runTimeoutSeconds` จะ **ไม่** เก็บถาวรอัตโนมัติ; มันหยุดเฉพาะการรันเท่านั้น เซสชันจะยังคงอยู่จนกว่าจะเก็บถาวรอัตโนมัติ
|
||||
- การเก็บถาวรอัตโนมัติใช้กับเซสชัน depth-1 และ depth-2 เท่ากัน
|
||||
- การล้างข้อมูลเบราว์เซอร์แยกจากการล้างข้อมูลการเก็บถาวร: แท็บ/โปรเซสของเบราว์เซอร์ที่ติดตามไว้จะถูกปิดแบบ best-effort เมื่อการรันเสร็จสิ้น แม้จะยังเก็บระเบียนทรานสคริปต์/เซสชันไว้ก็ตาม
|
||||
|
||||
## เอเจนต์ย่อยแบบซ้อนกัน
|
||||
## Sub-agents แบบซ้อน
|
||||
|
||||
ตามค่าเริ่มต้น เอเจนต์ย่อยไม่สามารถสร้างเอเจนต์ย่อยของตัวเองได้
|
||||
(`maxSpawnDepth: 1`) ตั้งค่า `maxSpawnDepth: 2` เพื่อเปิดใช้การซ้อนหนึ่งระดับ
|
||||
นั่นคือ **รูปแบบตัวประสานงาน**: หลัก → เอเจนต์ย่อยตัวประสานงาน →
|
||||
เอเจนต์ย่อยของเอเจนต์ย่อยที่เป็นผู้ปฏิบัติงาน
|
||||
โดยค่าเริ่มต้น sub-agents ไม่สามารถ spawn sub-agents ของตัวเองได้
|
||||
(`maxSpawnDepth: 1`) ตั้งค่า `maxSpawnDepth: 2` เพื่อเปิดใช้งานการซ้อนหนึ่งระดับ
|
||||
นั่นคือ **รูปแบบ orchestrator**: main → orchestrator sub-agent →
|
||||
worker sub-sub-agents
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -295,156 +309,154 @@ transcript ปัจจุบันอย่างชัดเจน
|
||||
|
||||
### ระดับความลึก
|
||||
|
||||
| ความลึก | รูปแบบคีย์เซสชัน | บทบาท | สร้างได้หรือไม่ |
|
||||
| ความลึก | รูปแบบคีย์เซสชัน | บทบาท | Spawn ได้หรือไม่ |
|
||||
| ----- | -------------------------------------------- | --------------------------------------------- | ---------------------------- |
|
||||
| 0 | `agent:<id>:main` | เอเจนต์หลัก | เสมอ |
|
||||
| 1 | `agent:<id>:subagent:<uuid>` | เอเจนต์ย่อย (ตัวประสานงานเมื่ออนุญาตความลึก 2) | เฉพาะเมื่อ `maxSpawnDepth >= 2` |
|
||||
| 2 | `agent:<id>:subagent:<uuid>:subagent:<uuid>` | เอเจนต์ย่อยของเอเจนต์ย่อย (ผู้ปฏิบัติงานปลายทาง) | ไม่เคย |
|
||||
| 0 | `agent:<id>:main` | เอเจนต์หลัก | เสมอ |
|
||||
| 1 | `agent:<id>:subagent:<uuid>` | Sub-agent (orchestrator เมื่ออนุญาต depth 2) | เฉพาะเมื่อ `maxSpawnDepth >= 2` |
|
||||
| 2 | `agent:<id>:subagent:<uuid>:subagent:<uuid>` | Sub-sub-agent (worker ปลายทาง) | ไม่เคย |
|
||||
|
||||
### ลำดับการประกาศ
|
||||
### สายการประกาศ
|
||||
|
||||
ผลลัพธ์ไหลย้อนกลับขึ้นตามลำดับ:
|
||||
ผลลัพธ์จะไหลย้อนกลับขึ้นมาตามสาย:
|
||||
|
||||
1. ผู้ปฏิบัติงานระดับความลึก 2 เสร็จสิ้น → ประกาศไปยังพาเรนต์ของตัวเอง (ตัวประสานงานระดับความลึก 1)
|
||||
2. ตัวประสานงานระดับความลึก 1 ได้รับประกาศ สังเคราะห์ผลลัพธ์ เสร็จสิ้น → ประกาศไปยังหลัก
|
||||
3. เอเจนต์หลักได้รับประกาศและส่งให้ผู้ใช้
|
||||
1. Worker depth-2 เสร็จสิ้น → ประกาศไปยัง parent ของตัวเอง (orchestrator depth-1)
|
||||
2. Orchestrator depth-1 ได้รับประกาศ สังเคราะห์ผลลัพธ์ เสร็จสิ้น → ประกาศไปยัง main
|
||||
3. เอเจนต์หลักได้รับประกาศและส่งต่อให้ผู้ใช้
|
||||
|
||||
แต่ละระดับเห็นเฉพาะประกาศจากลูกโดยตรงของตัวเองเท่านั้น
|
||||
แต่ละระดับจะเห็นเฉพาะประกาศจาก children โดยตรงของตัวเองเท่านั้น
|
||||
|
||||
<Note>
|
||||
**คำแนะนำด้านการปฏิบัติการ:** เริ่มงานลูกหนึ่งครั้งและรอเหตุการณ์เสร็จสิ้น
|
||||
แทนการสร้างลูปโพลรอบ `sessions_list`,
|
||||
`sessions_history`, `/subagents list` หรือคำสั่ง sleep ของ `exec`
|
||||
`sessions_list` และ `/subagents list` จะคงความสัมพันธ์เซสชันลูก
|
||||
ให้โฟกัสกับงานสด ลูกที่ยังทำงานอยู่ยังคงแนบอยู่ ลูกที่จบแล้วจะยัง
|
||||
มองเห็นได้ในหน้าต่างรายการล่าสุดช่วงสั้น ๆ และลิงก์ลูกที่มีเฉพาะในสโตร์และเก่าแล้วจะ
|
||||
ถูกละเว้นหลังจากหน้าต่างความสดใหม่ของมัน วิธีนี้ป้องกันไม่ให้เมทาดาทา `spawnedBy` /
|
||||
`parentSessionKey` เก่าชุบชีวิตลูกเงาหลัง
|
||||
รีสตาร์ท หากเหตุการณ์เสร็จสิ้นของลูกมาถึงหลังจากคุณส่ง
|
||||
คำตอบสุดท้ายแล้ว การติดตามผลที่ถูกต้องคือโทเคนเงียบตามตัวอักษร
|
||||
**แนวทางปฏิบัติด้านการดำเนินงาน:** เริ่มงาน child เพียงครั้งเดียวและรอเหตุการณ์เสร็จสิ้น
|
||||
แทนการสร้างลูป polling รอบ `sessions_list`,
|
||||
`sessions_history`, `/subagents list` หรือคำสั่ง `exec` sleep
|
||||
`sessions_list` และ `/subagents list` จะรักษาความสัมพันธ์ child-session
|
||||
ให้โฟกัสอยู่กับงานที่ live อยู่ — children ที่ live จะยังคงแนบอยู่, children ที่จบแล้วจะยัง
|
||||
มองเห็นได้ในหน้าต่างล่าสุดช่วงสั้น ๆ และลิงก์ child แบบมีเฉพาะใน store ที่เก่าจะถูก
|
||||
ละเว้นหลังจากพ้นหน้าต่างความสดใหม่ การทำเช่นนี้ป้องกันไม่ให้ข้อมูลเมตาเก่า `spawnedBy` /
|
||||
`parentSessionKey` ชุบชีวิต ghost children หลังจาก
|
||||
รีสตาร์ท หากเหตุการณ์เสร็จสิ้นของ child มาถึงหลังจากคุณส่ง
|
||||
คำตอบสุดท้ายไปแล้ว follow-up ที่ถูกต้องคือโทเค็นเงียบตามตัวอักษร
|
||||
`NO_REPLY` / `no_reply`
|
||||
</Note>
|
||||
|
||||
### นโยบายเครื่องมือตามความลึก
|
||||
|
||||
- บทบาทและขอบเขตการควบคุมถูกเขียนลงในเมทาดาทาเซสชันตอนสร้าง ซึ่งทำให้คีย์เซสชันแบบแบนหรือที่กู้คืนมาไม่สามารถได้สิทธิ์ตัวประสานงานกลับคืนโดยไม่ตั้งใจ
|
||||
- **ความลึก 1 (ตัวประสานงาน เมื่อ `maxSpawnDepth >= 2`):** ได้รับ `sessions_spawn`, `subagents`, `sessions_list`, `sessions_history` เพื่อให้จัดการลูกของตัวเองได้ เครื่องมือเซสชัน/ระบบอื่นยังคงถูกปฏิเสธ
|
||||
- **ความลึก 1 (ปลายทาง เมื่อ `maxSpawnDepth == 1`):** ไม่มีเครื่องมือเซสชัน (พฤติกรรมเริ่มต้นปัจจุบัน)
|
||||
- **ความลึก 2 (ผู้ปฏิบัติงานปลายทาง):** ไม่มีเครื่องมือเซสชัน — `sessions_spawn` ถูกปฏิเสธเสมอที่ความลึก 2 ไม่สามารถสร้างลูกต่อได้
|
||||
- บทบาทและขอบเขตการควบคุมจะถูกเขียนลงในข้อมูลเมตาของเซสชันตอน spawn ซึ่งช่วยป้องกันไม่ให้คีย์เซสชันแบบแบนหรือที่กู้คืนมาได้รับสิทธิ์ orchestrator กลับมาโดยไม่ตั้งใจ
|
||||
- **Depth 1 (orchestrator, เมื่อ `maxSpawnDepth >= 2`):** ได้รับ `sessions_spawn`, `subagents`, `sessions_list`, `sessions_history` เพื่อให้จัดการ children ของตัวเองได้ เครื่องมือ session/system อื่นยังคงถูกปฏิเสธ
|
||||
- **Depth 1 (leaf, เมื่อ `maxSpawnDepth == 1`):** ไม่มีเครื่องมือเซสชัน (พฤติกรรมเริ่มต้นปัจจุบัน)
|
||||
- **Depth 2 (leaf worker):** ไม่มีเครื่องมือเซสชัน — `sessions_spawn` จะถูกปฏิเสธเสมอที่ depth 2 ไม่สามารถ spawn children ต่อได้
|
||||
|
||||
### ขีดจำกัดการสร้างรายเอเจนต์
|
||||
### ขีดจำกัดการ spawn รายเอเจนต์
|
||||
|
||||
แต่ละเซสชันเอเจนต์ (ทุกระดับความลึก) มีลูกที่ทำงานอยู่ได้สูงสุด `maxChildrenPerAgent`
|
||||
(ค่าเริ่มต้น `5`) ในแต่ละครั้ง วิธีนี้ป้องกันการกระจายงานเกินควบคุม
|
||||
จากตัวประสานงานเดียว
|
||||
เซสชันเอเจนต์แต่ละรายการ (ที่ความลึกใดก็ได้) สามารถมี children ที่ใช้งานอยู่ได้สูงสุด `maxChildrenPerAgent`
|
||||
(ค่าเริ่มต้น `5`) พร้อมกัน การตั้งค่านี้ป้องกัน fan-out ที่ควบคุมไม่ได้
|
||||
จาก orchestrator เดียว
|
||||
|
||||
### การหยุดแบบลูกโซ่
|
||||
### การหยุดแบบ cascade
|
||||
|
||||
การหยุดตัวประสานงานระดับความลึก 1 จะหยุดลูกระดับความลึก 2
|
||||
ทั้งหมดของมันโดยอัตโนมัติ:
|
||||
การหยุด orchestrator depth-1 จะหยุด children depth-2 ทั้งหมดของมันโดยอัตโนมัติ:
|
||||
|
||||
- `/stop` ในแชตหลักหยุดเอเจนต์ระดับความลึก 1 ทั้งหมดและหยุดแบบลูกโซ่ไปยังลูกระดับความลึก 2 ของพวกเขา
|
||||
- `/subagents kill <id>` หยุดเอเจนต์ย่อยที่ระบุและหยุดแบบลูกโซ่ไปยังลูกของมัน
|
||||
- `/subagents kill all` หยุดเอเจนต์ย่อยทั้งหมดสำหรับผู้ร้องขอและหยุดแบบลูกโซ่
|
||||
- `/stop` ในแชตหลักจะหยุดเอเจนต์ depth-1 ทั้งหมดและ cascade ไปยัง children depth-2 ของพวกเขา
|
||||
- `/subagents kill <id>` หยุด sub-agent เฉพาะตัวและ cascade ไปยัง children ของมัน
|
||||
- `/subagents kill all` หยุด sub-agents ทั้งหมดสำหรับผู้ร้องขอและ cascade
|
||||
|
||||
## การยืนยันตัวตน
|
||||
|
||||
การยืนยันตัวตนของเอเจนต์ย่อยถูกแก้ตาม **ID เอเจนต์** ไม่ใช่ตามประเภทเซสชัน:
|
||||
การยืนยันตัวตนของ sub-agent จะ resolve ตาม **agent id** ไม่ใช่ตามประเภทเซสชัน:
|
||||
|
||||
- คีย์เซสชันเอเจนต์ย่อยคือ `agent:<agentId>:subagent:<uuid>`
|
||||
- สโตร์การยืนยันตัวตนถูกโหลดจาก `agentDir` ของเอเจนต์นั้น
|
||||
- โปรไฟล์การยืนยันตัวตนของเอเจนต์หลักถูกผสานเข้าเป็น **fallback**; โปรไฟล์เอเจนต์จะแทนที่โปรไฟล์หลักเมื่อมีข้อขัดแย้ง
|
||||
- คีย์เซสชัน sub-agent คือ `agent:<agentId>:subagent:<uuid>`
|
||||
- auth store โหลดจาก `agentDir` ของเอเจนต์นั้น
|
||||
- auth profiles ของเอเจนต์หลักจะถูกผสานเข้ามาเป็น **fallback**; โปรไฟล์ของเอเจนต์จะเขียนทับโปรไฟล์หลักเมื่อมี conflict
|
||||
|
||||
การผสานเป็นแบบเพิ่มเข้าไป ดังนั้นโปรไฟล์หลักจึงพร้อมใช้งานเป็น
|
||||
fallback เสมอ ยังไม่รองรับการยืนยันตัวตนแบบแยกขาดต่อเอเจนต์อย่างสมบูรณ์
|
||||
การผสานเป็นแบบเพิ่มเข้ามา ดังนั้นโปรไฟล์หลักจะพร้อมใช้งานเป็น
|
||||
fallback เสมอ ยังไม่รองรับ auth ที่แยกอย่างสมบูรณ์ต่อเอเจนต์
|
||||
|
||||
## การประกาศ
|
||||
|
||||
เอเจนต์ย่อยรายงานกลับผ่านขั้นตอนประกาศ:
|
||||
Sub-agents รายงานกลับผ่านขั้นตอนการประกาศ:
|
||||
|
||||
- ขั้นตอนประกาศทำงานภายในเซสชันเอเจนต์ย่อย (ไม่ใช่เซสชันผู้ร้องขอ)
|
||||
- หากเอเจนต์ย่อยตอบกลับตรงกับ `ANNOUNCE_SKIP` จะไม่มีการโพสต์อะไร
|
||||
- หากข้อความผู้ช่วยล่าสุดเป็นโทเคนเงียบตรงตัว `NO_REPLY` / `no_reply` เอาต์พุตประกาศจะถูกระงับ แม้จะเคยมีความคืบหน้าที่มองเห็นได้ก่อนหน้านั้น
|
||||
- ขั้นตอนการประกาศรันภายในเซสชัน sub-agent (ไม่ใช่เซสชันผู้ร้องขอ)
|
||||
- หาก sub-agent ตอบกลับตรงกับ `ANNOUNCE_SKIP` จะไม่มีการโพสต์อะไร
|
||||
- หากข้อความ assistant ล่าสุดเป็นโทเค็นเงียบตรงตามตัวอักษร `NO_REPLY` / `no_reply` เอาต์พุตประกาศจะถูกระงับแม้ก่อนหน้านี้จะมีความคืบหน้าที่มองเห็นได้
|
||||
|
||||
การส่งมอบขึ้นอยู่กับความลึกของผู้ร้องขอ:
|
||||
|
||||
- เซสชันผู้ร้องขอระดับบนสุดใช้การเรียก `agent` แบบติดตามผลพร้อมการส่งมอบภายนอก (`deliver=true`)
|
||||
- เซสชันเอเจนต์ย่อยผู้ร้องขอแบบซ้อนกันจะได้รับการฉีดติดตามผลภายใน (`deliver=false`) เพื่อให้ตัวประสานงานสังเคราะห์ผลลัพธ์ลูกภายในเซสชันได้
|
||||
- หากเซสชันเอเจนต์ย่อยผู้ร้องขอแบบซ้อนกันหายไป OpenClaw จะ fallback ไปยังผู้ร้องขอของเซสชันนั้นเมื่อมี
|
||||
- เซสชันผู้ร้องขอระดับบนสุดใช้การเรียก `agent` แบบ follow-up พร้อมการส่งมอบภายนอก (`deliver=true`)
|
||||
- เซสชัน requester subagent แบบซ้อนจะได้รับการฉีด follow-up ภายใน (`deliver=false`) เพื่อให้ orchestrator สังเคราะห์ผลลัพธ์ child ภายในเซสชันได้
|
||||
- หากเซสชัน nested requester subagent หายไป OpenClaw จะ fallback ไปยังผู้ร้องขอของเซสชันนั้นเมื่อมี
|
||||
|
||||
สำหรับเซสชันผู้ร้องขอระดับบนสุด การส่งมอบโดยตรงในโหมดเสร็จสิ้นจะ
|
||||
แก้เส้นทางบทสนทนา/เธรดที่ถูกผูกและการแทนที่ของ hook ก่อน จากนั้นเติม
|
||||
ฟิลด์เป้าหมายช่องทางที่หายไปจากเส้นทางที่เซสชันผู้ร้องขอเก็บไว้
|
||||
วิธีนี้ทำให้การเสร็จสิ้นอยู่ในแชต/หัวข้อที่ถูกต้อง แม้ต้นทางการเสร็จสิ้น
|
||||
สำหรับเซสชันผู้ร้องขอระดับบนสุด การส่งมอบโดยตรงใน completion-mode จะ
|
||||
resolve เส้นทาง conversation/thread ที่ผูกอยู่และ hook override ก่อน จากนั้นเติม
|
||||
ฟิลด์ channel-target ที่ขาดจากเส้นทางที่จัดเก็บไว้ของเซสชันผู้ร้องขอ
|
||||
ซึ่งทำให้ completion อยู่ในแชต/หัวข้อที่ถูกต้อง แม้ต้นทาง completion
|
||||
จะระบุเฉพาะช่องทางก็ตาม
|
||||
|
||||
การรวมผลการเสร็จสิ้นของลูกถูกจำกัดขอบเขตไว้ที่งานผู้ร้องขอปัจจุบันเมื่อ
|
||||
สร้างข้อค้นพบการเสร็จสิ้นแบบซ้อนกัน เพื่อป้องกันไม่ให้เอาต์พุตลูกจากงานก่อนหน้า
|
||||
ที่เก่าแล้วรั่วไหลเข้าไปในการประกาศปัจจุบัน การตอบกลับประกาศจะคง
|
||||
การกำหนดเส้นทางเธรด/หัวข้อเมื่อมีในอะแดปเตอร์ช่องทาง
|
||||
การรวบรวม completion ของ child จะถูกจำกัดขอบเขตไว้ที่การรันผู้ร้องขอปัจจุบันเมื่อ
|
||||
สร้าง findings ของ nested completion เพื่อป้องกันไม่ให้เอาต์พุต child
|
||||
จากการรันก่อนหน้าที่เก่ารั่วเข้ามาในประกาศปัจจุบัน การตอบกลับประกาศจะรักษา
|
||||
การกำหนดเส้นทาง thread/topic เมื่อมีใน channel adapters
|
||||
|
||||
### บริบทประกาศ
|
||||
### บริบทการประกาศ
|
||||
|
||||
บริบทประกาศถูกทำให้เป็นมาตรฐานเป็นบล็อกเหตุการณ์ภายในที่เสถียร:
|
||||
บริบทการประกาศจะถูกทำให้เป็นมาตรฐานเป็นบล็อกเหตุการณ์ภายในที่เสถียร:
|
||||
|
||||
| ฟิลด์ | แหล่งที่มา |
|
||||
| ฟิลด์ | แหล่งที่มา |
|
||||
| -------------- | ------------------------------------------------------------------------------------------------------------- |
|
||||
| แหล่งที่มา | `subagent` หรือ `cron` |
|
||||
| ID เซสชัน | คีย์/ID เซสชันลูก |
|
||||
| ประเภท | ประเภทประกาศ + ป้ายกำกับงาน |
|
||||
| สถานะ | ได้จากผลลัพธ์รันไทม์ (`success`, `error`, `timeout` หรือ `unknown`) — **ไม่ได้** อนุมานจากข้อความโมเดล |
|
||||
| เนื้อหาผลลัพธ์ | ข้อความผู้ช่วยล่าสุดที่มองเห็นได้ มิฉะนั้นเป็นข้อความ tool/toolResult ล่าสุดที่ผ่านการทำให้ปลอดภัยแล้ว |
|
||||
| การติดตามผล | คำแนะนำที่อธิบายว่าเมื่อใดควรตอบกลับหรือคงความเงียบ |
|
||||
| Source | `subagent` หรือ `cron` |
|
||||
| Session ids | คีย์/id เซสชัน child |
|
||||
| Type | ประเภทประกาศ + ป้ายกำกับงาน |
|
||||
| Status | ได้มาจากผลลัพธ์รันไทม์ (`success`, `error`, `timeout` หรือ `unknown`) — **ไม่ได้** อนุมานจากข้อความโมเดล |
|
||||
| Result content | ข้อความ assistant ล่าสุดที่มองเห็นได้ มิฉะนั้นคือข้อความ tool/toolResult ล่าสุดที่ผ่านการ sanitize แล้ว |
|
||||
| Follow-up | คำสั่งที่อธิบายว่าเมื่อใดควรตอบกลับเทียบกับอยู่เงียบ |
|
||||
|
||||
งานที่ล้มเหลวในสถานะปลายทางจะรายงานสถานะล้มเหลวโดยไม่เล่นซ้ำข้อความตอบกลับ
|
||||
ที่จับไว้ เมื่อ timeout หากลูกผ่านไปได้เพียงการเรียกเครื่องมือ ประกาศ
|
||||
สามารถยุบประวัตินั้นเป็นสรุปความคืบหน้าบางส่วนแบบสั้น
|
||||
แทนการเล่นเอาต์พุตเครื่องมือดิบซ้ำ
|
||||
การรัน terminal ที่ล้มเหลวจะรายงานสถานะความล้มเหลวโดยไม่ replay
|
||||
ข้อความตอบกลับที่จับไว้ เมื่อ timeout หาก child ไปถึงแค่การเรียกเครื่องมือ
|
||||
ประกาศสามารถยุบประวัตินั้นเป็นสรุปความคืบหน้าบางส่วนแบบสั้น
|
||||
แทนการ replay เอาต์พุตเครื่องมือดิบ
|
||||
|
||||
### บรรทัดสถิติ
|
||||
|
||||
เพย์โหลดประกาศมีบรรทัดสถิติที่ท้ายสุด (แม้ถูกห่อบรรทัด):
|
||||
Payload ประกาศจะมีบรรทัดสถิติท้ายสุด (แม้เมื่อถูกครอบไว้):
|
||||
|
||||
- รันไทม์ (เช่น `runtime 5m12s`)
|
||||
- การใช้โทเคน (อินพุต/เอาต์พุต/ทั้งหมด)
|
||||
- ค่าใช้จ่ายประมาณการเมื่อกำหนดราคาของโมเดลไว้ (`models.providers.*.models[].cost`)
|
||||
- `sessionKey`, `sessionId` และเส้นทางทรานสคริปต์ เพื่อให้เอเจนต์หลักดึงประวัติผ่าน `sessions_history` หรือตรวจสอบไฟล์บนดิสก์ได้
|
||||
- Runtime (เช่น `runtime 5m12s`)
|
||||
- การใช้โทเค็น (input/output/total)
|
||||
- ค่าใช้จ่ายโดยประมาณเมื่อกำหนดราคาของโมเดลไว้ (`models.providers.*.models[].cost`)
|
||||
- `sessionKey`, `sessionId` และเส้นทางทรานสคริปต์ เพื่อให้เอเจนต์หลักสามารถดึงประวัติผ่าน `sessions_history` หรือตรวจสอบไฟล์บนดิสก์ได้
|
||||
|
||||
เมทาดาทาภายในมีไว้สำหรับการประสานงานเท่านั้น การตอบกลับที่แสดงต่อผู้ใช้
|
||||
ควรเขียนใหม่ด้วยเสียงผู้ช่วยตามปกติ
|
||||
ข้อมูลเมตาภายในมีไว้สำหรับ orchestration เท่านั้น; คำตอบที่ผู้ใช้เห็น
|
||||
ควรถูกเขียนใหม่ด้วยน้ำเสียง assistant ปกติ
|
||||
|
||||
### เหตุใดจึงควรใช้ `sessions_history`
|
||||
### เหตุผลที่ควรใช้ `sessions_history`
|
||||
|
||||
`sessions_history` เป็นเส้นทางการประสานงานที่ปลอดภัยกว่า:
|
||||
`sessions_history` เป็นเส้นทาง orchestration ที่ปลอดภัยกว่า:
|
||||
|
||||
- การเรียกคืนของผู้ช่วยถูกทำให้เป็นมาตรฐานก่อน: ลบแท็กการคิด; ลบโครง `<relevant-memories>` / `<relevant_memories>`; ลบบล็อกเพย์โหลด XML การเรียกเครื่องมือแบบข้อความธรรมดา (`<tool_call>`, `<function_call>`, `<tool_calls>`, `<function_calls>`) รวมถึงเพย์โหลดที่ถูกตัดทอนและไม่เคยปิดอย่างเรียบร้อย; ลบโครง tool-call/result ที่ถูกลดระดับและมาร์กเกอร์บริบทประวัติ; ลบโทเคนควบคุมโมเดลที่รั่ว (`<|assistant|>`, ASCII `<|...|>` อื่น, แบบเต็มความกว้าง `<|...|>`); ลบ XML การเรียกเครื่องมือ MiniMax ที่มีรูปแบบผิด
|
||||
- ข้อความที่ดูเหมือนข้อมูลประจำตัว/โทเคนจะถูกปกปิด
|
||||
- การเรียกคืนของ assistant จะถูกทำให้เป็นมาตรฐานก่อน: ลบ thinking tags; ลบโครง `<relevant-memories>` / `<relevant_memories>`; ลบบล็อก payload XML ของการเรียกเครื่องมือแบบ plain-text (`<tool_call>`, `<function_call>`, `<tool_calls>`, `<function_calls>`) รวมถึง payload ที่ถูกตัดทอนซึ่งไม่เคยปิดอย่างสมบูรณ์; ลบโครง tool-call/result ที่ถูกลดระดับและตัวทำเครื่องหมาย historical-context; ลบ model control tokens ที่รั่ว (`<|assistant|>`, ASCII `<|...|>` อื่น, full-width `<|...|>`); ลบ XML tool-call ของ MiniMax ที่ malformed
|
||||
- ข้อความที่ดูเหมือน credential/token จะถูก redact
|
||||
- บล็อกยาวสามารถถูกตัดทอนได้
|
||||
- ประวัติขนาดใหญ่มากสามารถทิ้งแถวเก่ากว่า หรือแทนที่แถวที่ใหญ่เกินด้วย `[sessions_history omitted: message too large]`
|
||||
- การตรวจสอบทรานสคริปต์ดิบบนดิสก์เป็น fallback เมื่อคุณต้องการทรานสคริปต์เต็มแบบตรงทุกไบต์
|
||||
- การตรวจสอบทรานสคริปต์ดิบบนดิสก์คือ fallback เมื่อคุณต้องการทรานสคริปต์แบบ byte-for-byte ครบถ้วน
|
||||
|
||||
## นโยบายเครื่องมือ
|
||||
|
||||
เอเจนต์ย่อยใช้โปรไฟล์และไปป์ไลน์นโยบายเครื่องมือเดียวกับพาเรนต์หรือ
|
||||
เอเจนต์เป้าหมายก่อน หลังจากนั้น OpenClaw จะใช้เลเยอร์ข้อจำกัด
|
||||
เอเจนต์ย่อย
|
||||
Sub-agent ใช้โปรไฟล์และไปป์ไลน์นโยบายเครื่องมือเดียวกับ agent หลักหรือ
|
||||
agent เป้าหมายก่อน จากนั้น OpenClaw จะใช้ชั้นข้อจำกัดของ sub-agent
|
||||
|
||||
เมื่อไม่มี `tools.profile` ที่จำกัด เอเจนต์ย่อยจะได้รับ **เครื่องมือทั้งหมด ยกเว้น
|
||||
เครื่องมือเซสชัน** และเครื่องมือระบบ:
|
||||
เมื่อไม่มี `tools.profile` ที่จำกัด sub-agent จะได้รับ **เครื่องมือทั้งหมด ยกเว้น
|
||||
เครื่องมือ session** และเครื่องมือระบบ:
|
||||
|
||||
- `sessions_list`
|
||||
- `sessions_history`
|
||||
- `sessions_send`
|
||||
- `sessions_spawn`
|
||||
|
||||
`sessions_history` ยังคงเป็นมุมมองการเรียกคืนที่มีขอบเขตและผ่านการทำให้ปลอดภัยที่นี่ด้วย —
|
||||
ไม่ใช่การดัมป์ทรานสคริปต์ดิบ
|
||||
`sessions_history` ยังคงเป็นมุมมองการเรียกคืนที่มีขอบเขตและผ่านการทำให้ปลอดภัยแล้วในที่นี้ด้วย —
|
||||
ไม่ใช่การดัมป์ transcript ดิบ
|
||||
|
||||
เมื่อ `maxSpawnDepth >= 2` เอเจนต์ย่อยตัวประสานงานระดับความลึก 1 จะได้รับ
|
||||
เมื่อ `maxSpawnDepth >= 2` sub-agent ตัว orchestrator ที่ depth-1 จะได้รับ
|
||||
`sessions_spawn`, `subagents`, `sessions_list` และ
|
||||
`sessions_history` เพิ่มเติม เพื่อให้จัดการลูกของตัวเองได้
|
||||
`sessions_history` เพิ่มเติม เพื่อให้สามารถจัดการลูกของตนได้
|
||||
|
||||
### แทนที่ผ่านการกำหนดค่า
|
||||
### Override ผ่าน config
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -468,12 +480,12 @@ fallback เสมอ ยังไม่รองรับการยืนย
|
||||
}
|
||||
```
|
||||
|
||||
`tools.subagents.tools.allow` เป็นตัวกรอง allow-only ขั้นสุดท้าย สามารถจำกัด
|
||||
`tools.subagents.tools.allow` เป็นตัวกรอง allow-only ขั้นสุดท้าย มันสามารถจำกัด
|
||||
ชุดเครื่องมือที่ resolve แล้วให้แคบลงได้ แต่ไม่สามารถ **เพิ่มกลับ** เครื่องมือที่ถูกนำออก
|
||||
โดย `tools.profile` ได้ ตัวอย่างเช่น `tools.profile: "coding"` รวม
|
||||
`web_search`/`web_fetch` แต่ไม่รวมเครื่องมือ `browser` หากต้องการให้
|
||||
sub-agent ที่ใช้ profile แบบ coding ใช้ระบบอัตโนมัติของเบราว์เซอร์ได้ ให้เพิ่ม browser ใน
|
||||
ขั้น profile:
|
||||
`web_search`/`web_fetch` แต่ไม่มีเครื่องมือ `browser` หากต้องการให้
|
||||
sub-agent ในโปรไฟล์ coding ใช้การทำงานอัตโนมัติของ browser ให้เพิ่ม browser ใน
|
||||
ขั้นโปรไฟล์:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -484,65 +496,64 @@ sub-agent ที่ใช้ profile แบบ coding ใช้ระบบอ
|
||||
}
|
||||
```
|
||||
|
||||
ใช้ `agents.list[].tools.alsoAllow: ["browser"]` แบบรายเอเจนต์เมื่อมีเพียง
|
||||
เอเจนต์เดียวที่ควรได้รับระบบอัตโนมัติของเบราว์เซอร์
|
||||
ใช้ `agents.list[].tools.alsoAllow: ["browser"]` แบบราย agent เมื่อมีเพียง
|
||||
agent เดียวที่ควรได้รับการทำงานอัตโนมัติของ browser
|
||||
|
||||
## ภาวะพร้อมกัน
|
||||
## การทำงานพร้อมกัน
|
||||
|
||||
Sub-agent ใช้ lane คิวในโปรเซสเฉพาะ:
|
||||
Sub-agent ใช้ lane คิวในโปรเซสโดยเฉพาะ:
|
||||
|
||||
- **ชื่อ lane:** `subagent`
|
||||
- **ภาวะพร้อมกัน:** `agents.defaults.subagents.maxConcurrent` (ค่าเริ่มต้น `8`)
|
||||
- **การทำงานพร้อมกัน:** `agents.defaults.subagents.maxConcurrent` (ค่าเริ่มต้น `8`)
|
||||
|
||||
## สถานะมีชีวิตและการกู้คืน
|
||||
## Liveness และการกู้คืน
|
||||
|
||||
OpenClaw ไม่ถือว่าการไม่มี `endedAt` เป็นหลักฐานถาวรว่า
|
||||
sub-agent ยังมีชีวิตอยู่ การรันที่ยังไม่จบซึ่งเก่ากว่าหน้าต่าง stale-run
|
||||
จะหยุดนับเป็น active/pending ใน `/subagents list`, สรุปสถานะ,
|
||||
gating การเสร็จสมบูรณ์ของ descendant และการตรวจสอบภาวะพร้อมกันต่อ session
|
||||
sub-agent ยังทำงานอยู่ run ที่ยังไม่สิ้นสุดซึ่งเก่ากว่าหน้าต่าง stale-run
|
||||
จะหยุดถูกนับเป็น active/pending ใน `/subagents list`, สรุปสถานะ,
|
||||
การ gating การเสร็จสิ้นของ descendant และการตรวจสอบ concurrency แบบราย session
|
||||
|
||||
หลังจาก Gateway รีสตาร์ต การรันที่ restore แล้วแต่ stale และยังไม่จบจะถูกตัดทิ้ง เว้นแต่
|
||||
session ลูกของการรันนั้นจะถูกทำเครื่องหมาย `abortedLastRun: true` session ลูกที่
|
||||
ถูกยกเลิกจากการรีสตาร์ตเหล่านั้นยังสามารถกู้คืนได้ผ่านโฟลว์กู้คืน orphan ของ sub-agent
|
||||
ซึ่งจะส่งข้อความ resume สังเคราะห์ก่อน
|
||||
ล้างเครื่องหมาย aborted
|
||||
หลังจาก Gateway restart แล้ว run ที่ restore กลับมาและยังไม่สิ้นสุดซึ่ง stale จะถูก prune เว้นแต่
|
||||
child session ของมันถูกทำเครื่องหมาย `abortedLastRun: true` child session ที่
|
||||
restart-aborted เหล่านั้นยังคงกู้คืนได้ผ่าน flow การกู้คืน orphan ของ sub-agent
|
||||
ซึ่งส่งข้อความ resume สังเคราะห์ก่อนล้าง marker ที่ถูก aborted
|
||||
|
||||
การกู้คืนอัตโนมัติหลังรีสตาร์ตถูกจำกัดต่อ session ลูก หาก
|
||||
sub-agent ลูกตัวเดิมถูกยอมรับให้กู้คืน orphan ซ้ำ ๆ ภายใน
|
||||
หน้าต่าง rapid re-wedge OpenClaw จะบันทึก recovery tombstone ใน
|
||||
session นั้นและหยุด auto-resume ให้ในการรีสตาร์ตภายหลัง รัน
|
||||
`openclaw tasks maintenance --apply` เพื่อ reconcile task record หรือ
|
||||
`openclaw doctor --fix` เพื่อล้าง flag การกู้คืน aborted ที่ stale บน
|
||||
การกู้คืนอัตโนมัติหลัง restart ถูกจำกัดแบบราย child session หาก child ของ
|
||||
sub-agent เดียวกันถูกยอมรับสำหรับการกู้คืน orphan ซ้ำ ๆ ภายใน
|
||||
หน้าต่าง rapid re-wedge OpenClaw จะคง recovery tombstone ไว้บน
|
||||
session นั้น และหยุด auto-resume มันในการ restart ภายหลัง ให้รัน
|
||||
`openclaw tasks maintenance --apply` เพื่อ reconcile ระเบียน task หรือ
|
||||
`openclaw doctor --fix` เพื่อล้าง flag การกู้คืนที่ aborted และ stale บน
|
||||
session ที่ถูก tombstone
|
||||
|
||||
<Note>
|
||||
หากการ spawn sub-agent ล้มเหลวด้วย Gateway `PAIRING_REQUIRED` /
|
||||
`scope-upgrade` ให้ตรวจสอบ RPC caller ก่อนแก้ไขสถานะ pairing
|
||||
การประสานงาน `sessions_spawn` ภายในควรเชื่อมต่อเป็น
|
||||
`client.id: "gateway-client"` พร้อม `client.mode: "backend"` ผ่าน auth แบบ
|
||||
direct loopback shared-token/password เส้นทางนั้นไม่ขึ้นกับ
|
||||
scope baseline ของ paired-device ของ CLI ผู้เรียกจากระยะไกล,
|
||||
`deviceIdentity` แบบ explicit, เส้นทาง device-token แบบ explicit และไคลเอนต์
|
||||
browser/node ยังต้องได้รับการอนุมัติ device ตามปกติสำหรับ scope upgrade
|
||||
`client.id: "gateway-client"` พร้อม `client.mode: "backend"` ผ่าน
|
||||
การ auth แบบ shared-token/password โดยตรงบน local loopback; เส้นทางนั้นไม่ขึ้นกับ
|
||||
baseline scope ของอุปกรณ์ที่จับคู่แล้วของ CLI caller ระยะไกล,
|
||||
`deviceIdentity` แบบระบุชัดเจน, เส้นทาง device-token แบบระบุชัดเจน และ client แบบ browser/node
|
||||
ยังต้องได้รับการอนุมัติอุปกรณ์ตามปกติสำหรับการอัปเกรด scope
|
||||
</Note>
|
||||
|
||||
## การหยุด
|
||||
|
||||
- การส่ง `/stop` ในแชต requester จะยกเลิก session ของ requester และหยุดการรัน sub-agent ที่ active ใด ๆ ที่ spawn จาก session นั้น โดย cascade ไปยังลูกซ้อน
|
||||
- `/subagents kill <id>` หยุด sub-agent เฉพาะตัวและ cascade ไปยังลูกของมัน
|
||||
- การส่ง `/stop` ในแชตของ requester จะ abort session ของ requester และหยุด run ของ sub-agent ที่ active ทั้งหมดที่ spawn จาก session นั้น โดย cascade ไปยังลูกที่ซ้อนอยู่
|
||||
- `/subagents kill <id>` หยุด sub-agent ที่ระบุและ cascade ไปยังลูกของมัน
|
||||
|
||||
## ข้อจำกัด
|
||||
|
||||
- การ announce ของ sub-agent เป็นแบบ **best-effort** หาก Gateway รีสตาร์ต งาน "announce back" ที่ pending จะสูญหาย
|
||||
- Sub-agent ยังคงใช้ทรัพยากรของโปรเซส Gateway เดียวกัน ให้ถือว่า `maxConcurrent` เป็นวาล์วนิรภัย
|
||||
- `sessions_spawn` เป็น non-blocking เสมอ: จะคืน `{ status: "accepted", runId, childSessionKey }` ทันที
|
||||
- context ของ sub-agent inject เฉพาะ `AGENTS.md` + `TOOLS.md` (ไม่มี `SOUL.md`, `IDENTITY.md`, `USER.md`, `HEARTBEAT.md` หรือ `BOOTSTRAP.md`)
|
||||
- ความลึกการซ้อนสูงสุดคือ 5 (`maxSpawnDepth` range: 1–5) แนะนำให้ใช้ความลึก 2 สำหรับกรณีใช้งานส่วนใหญ่
|
||||
- `maxChildrenPerAgent` จำกัดจำนวนลูกที่ active ต่อ session (ค่าเริ่มต้น `5`, range `1–20`)
|
||||
- การประกาศของ sub-agent เป็นแบบ **best-effort** หาก gateway restart งาน "announce back" ที่ค้างอยู่จะหายไป
|
||||
- Sub-agent ยังใช้ทรัพยากรของโปรเซส gateway เดียวกันร่วมกัน ให้ถือว่า `maxConcurrent` เป็นวาล์วนิรภัย
|
||||
- `sessions_spawn` เป็นแบบไม่ block เสมอ: มันส่งคืน `{ status: "accepted", runId, childSessionKey }` ทันที
|
||||
- Context ของ sub-agent inject เฉพาะ `AGENTS.md` + `TOOLS.md` (ไม่มี `SOUL.md`, `IDENTITY.md`, `USER.md`, `HEARTBEAT.md` หรือ `BOOTSTRAP.md`)
|
||||
- ความลึกการซ้อนสูงสุดคือ 5 (ช่วง `maxSpawnDepth`: 1–5) แนะนำให้ใช้ depth 2 สำหรับกรณีใช้งานส่วนใหญ่
|
||||
- `maxChildrenPerAgent` จำกัดจำนวนลูกที่ active ต่อ session (ค่าเริ่มต้น `5`, ช่วง `1–20`)
|
||||
|
||||
## ที่เกี่ยวข้อง
|
||||
|
||||
- [ACP agents](/th/tools/acp-agents)
|
||||
- [Agent send](/th/tools/agent-send)
|
||||
- [งานเบื้องหลัง](/th/automation/tasks)
|
||||
- [เครื่องมือ sandbox แบบหลายเอเจนต์](/th/tools/multi-agent-sandbox-tools)
|
||||
- [Background tasks](/th/automation/tasks)
|
||||
- [Multi-agent sandbox tools](/th/tools/multi-agent-sandbox-tools)
|
||||
|
||||
@ -1,46 +1,46 @@
|
||||
---
|
||||
read_when:
|
||||
- คุณต้องการใช้งาน Gateway จากเบราว์เซอร์
|
||||
- คุณต้องการเข้าถึง Tailnet โดยไม่ใช้อุโมงค์ SSH
|
||||
- คุณต้องการเข้าถึง Tailnet โดยไม่ต้องใช้อุโมงค์ SSH
|
||||
sidebarTitle: Control UI
|
||||
summary: UI ควบคุมที่ทำงานบนเบราว์เซอร์สำหรับ Gateway (แชท, โหนด, การกำหนดค่า)
|
||||
title: อินเทอร์เฟซควบคุม
|
||||
summary: อินเทอร์เฟซควบคุมบนเบราว์เซอร์สำหรับ Gateway (แชท, โหนด, การกำหนดค่า)
|
||||
title: ส่วนติดต่อผู้ใช้สำหรับควบคุม
|
||||
x-i18n:
|
||||
generated_at: "2026-05-04T02:28:08Z"
|
||||
generated_at: "2026-05-04T07:07:44Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: c890d83da2c296b600e4b5a00a538f37e6bd54da31fbe62113ecd6177b15626e
|
||||
source_hash: 07fbbe1c7fec5f67a04a231e02bdf0f7d16be9c5fe188915674d71fcd69002a5
|
||||
source_path: web/control-ui.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
UI ควบคุมเป็นแอปหน้าเดียวขนาดเล็กแบบ **Vite + Lit** ที่ให้บริการโดย Gateway:
|
||||
Control UI เป็นแอปหน้าเดียวขนาดเล็กแบบ **Vite + Lit** ที่ให้บริการโดย Gateway:
|
||||
|
||||
- ค่าเริ่มต้น: `http://<host>:18789/`
|
||||
- คำนำหน้าแบบไม่บังคับ: ตั้งค่า `gateway.controlUi.basePath` (เช่น `/openclaw`)
|
||||
- คำนำหน้าแบบเลือกได้: ตั้งค่า `gateway.controlUi.basePath` (เช่น `/openclaw`)
|
||||
|
||||
แอปนี้สื่อสาร **โดยตรงกับ Gateway WebSocket** บนพอร์ตเดียวกัน
|
||||
|
||||
## เปิดใช้งานด่วน (ภายในเครื่อง)
|
||||
## เปิดอย่างรวดเร็ว (ภายในเครื่อง)
|
||||
|
||||
หาก Gateway กำลังทำงานอยู่บนคอมพิวเตอร์เครื่องเดียวกัน ให้เปิด:
|
||||
|
||||
- [http://127.0.0.1:18789/](http://127.0.0.1:18789/) (หรือ [http://localhost:18789/](http://localhost:18789/))
|
||||
|
||||
หากหน้าเว็บโหลดไม่สำเร็จ ให้เริ่ม Gateway ก่อน: `openclaw gateway`
|
||||
หากหน้าโหลดไม่สำเร็จ ให้เริ่ม Gateway ก่อน: `openclaw gateway`
|
||||
|
||||
การยืนยันตัวตนถูกส่งระหว่าง WebSocket handshake ผ่าน:
|
||||
มีการส่ง Auth ระหว่างการจับมือ WebSocket ผ่าน:
|
||||
|
||||
- `connect.params.auth.token`
|
||||
- `connect.params.auth.password`
|
||||
- ส่วนหัวข้อมูลประจำตัวของ Tailscale Serve เมื่อ `gateway.auth.allowTailscale: true`
|
||||
- ส่วนหัวข้อมูลประจำตัวของพร็อกซีที่เชื่อถือได้เมื่อ `gateway.auth.mode: "trusted-proxy"`
|
||||
- ส่วนหัวตัวตนของ Tailscale Serve เมื่อ `gateway.auth.allowTailscale: true`
|
||||
- ส่วนหัวตัวตนของพร็อกซีที่เชื่อถือได้เมื่อ `gateway.auth.mode: "trusted-proxy"`
|
||||
|
||||
แผงการตั้งค่าแดชบอร์ดจะเก็บ token สำหรับเซสชันแท็บเบราว์เซอร์ปัจจุบันและ URL Gateway ที่เลือกไว้ ส่วนรหัสผ่านจะไม่ถูกจัดเก็บไว้ โดยปกติ onboarding จะสร้าง gateway token สำหรับการยืนยันตัวตนแบบความลับร่วมเมื่อเชื่อมต่อครั้งแรก แต่การยืนยันตัวตนด้วยรหัสผ่านก็ใช้งานได้เช่นกันเมื่อ `gateway.auth.mode` เป็น `"password"`
|
||||
แผงการตั้งค่าแดชบอร์ดจะเก็บโทเค็นสำหรับเซสชันแท็บเบราว์เซอร์ปัจจุบันและ URL Gateway ที่เลือกไว้ ส่วนรหัสผ่านจะไม่ถูกจัดเก็บ Onboarding มักสร้างโทเค็น Gateway สำหรับ Auth แบบ shared-secret เมื่อเชื่อมต่อครั้งแรก แต่ Auth ด้วยรหัสผ่านก็ใช้งานได้เช่นกันเมื่อ `gateway.auth.mode` เป็น `"password"`
|
||||
|
||||
## การจับคู่อุปกรณ์ (การเชื่อมต่อครั้งแรก)
|
||||
|
||||
เมื่อคุณเชื่อมต่อกับ UI ควบคุมจากเบราว์เซอร์หรืออุปกรณ์ใหม่ โดยปกติ Gateway จะต้องมี **การอนุมัติการจับคู่แบบครั้งเดียว** นี่เป็นมาตรการรักษาความปลอดภัยเพื่อป้องกันการเข้าถึงโดยไม่ได้รับอนุญาต
|
||||
เมื่อคุณเชื่อมต่อกับ Control UI จากเบราว์เซอร์หรืออุปกรณ์ใหม่ โดยปกติ Gateway จะต้องมี **การอนุมัติการจับคู่แบบครั้งเดียว** นี่เป็นมาตรการด้านความปลอดภัยเพื่อป้องกันการเข้าถึงโดยไม่ได้รับอนุญาต
|
||||
|
||||
**สิ่งที่คุณจะเห็น:** "disconnected (1008): pairing required"
|
||||
|
||||
@ -50,190 +50,190 @@ UI ควบคุมเป็นแอปหน้าเดียวขนา
|
||||
openclaw devices list
|
||||
```
|
||||
</Step>
|
||||
<Step title="อนุมัติตาม ID คำขอ">
|
||||
<Step title="อนุมัติด้วย ID คำขอ">
|
||||
```bash
|
||||
openclaw devices approve <requestId>
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
หากเบราว์เซอร์ลองจับคู่อีกครั้งโดยมีรายละเอียดการยืนยันตัวตนเปลี่ยนไป (บทบาท/ขอบเขต/กุญแจสาธารณะ) คำขอที่รอดำเนินการก่อนหน้าจะถูกแทนที่ และจะมีการสร้าง `requestId` ใหม่ ให้รัน `openclaw devices list` อีกครั้งก่อนอนุมัติ
|
||||
หากเบราว์เซอร์ลองจับคู่อีกครั้งด้วยรายละเอียด Auth ที่เปลี่ยนไป (บทบาท/ขอบเขต/กุญแจสาธารณะ) คำขอที่รอดำเนินการก่อนหน้าจะถูกแทนที่ และจะมีการสร้าง `requestId` ใหม่ ให้รัน `openclaw devices list` อีกครั้งก่อนอนุมัติ
|
||||
|
||||
หากเบราว์เซอร์จับคู่แล้ว และคุณเปลี่ยนจากสิทธิ์อ่านเป็นสิทธิ์เขียน/ผู้ดูแลระบบ ระบบจะถือว่านี่เป็นการอัปเกรดการอนุมัติ ไม่ใช่การเชื่อมต่อใหม่แบบเงียบ ๆ OpenClaw จะคงการอนุมัติเดิมไว้ บล็อกการเชื่อมต่อใหม่ที่มีขอบเขตกว้างกว่า และขอให้คุณอนุมัติชุดขอบเขตใหม่อย่างชัดเจน
|
||||
หากเบราว์เซอร์จับคู่ไว้แล้ว และคุณเปลี่ยนจากสิทธิ์อ่านเป็นสิทธิ์เขียน/ผู้ดูแลระบบ การเปลี่ยนนี้จะถือเป็นการอัปเกรดการอนุมัติ ไม่ใช่การเชื่อมต่อใหม่แบบเงียบ OpenClaw จะคงการอนุมัติเดิมไว้ บล็อกการเชื่อมต่อใหม่ที่มีสิทธิ์กว้างขึ้น และขอให้คุณอนุมัติชุดขอบเขตใหม่อย่างชัดเจน
|
||||
|
||||
เมื่ออนุมัติแล้ว อุปกรณ์จะถูกจดจำและจะไม่ต้องอนุมัติซ้ำ เว้นแต่คุณจะเพิกถอนด้วย `openclaw devices revoke --device <id> --role <role>` ดู [CLI อุปกรณ์](/th/cli/devices) สำหรับการหมุนเวียน token และการเพิกถอน
|
||||
เมื่ออนุมัติแล้ว อุปกรณ์จะถูกจดจำและไม่ต้องอนุมัติซ้ำ เว้นแต่คุณจะเพิกถอนด้วย `openclaw devices revoke --device <id> --role <role>` ดู [CLI สำหรับอุปกรณ์](/th/cli/devices) สำหรับการหมุนเวียนโทเค็นและการเพิกถอน
|
||||
|
||||
<Note>
|
||||
- การเชื่อมต่อเบราว์เซอร์แบบ local loopback โดยตรง (`127.0.0.1` / `localhost`) จะได้รับการอนุมัติอัตโนมัติ
|
||||
- Tailscale Serve สามารถข้ามรอบการจับคู่สำหรับเซสชันผู้ปฏิบัติงานของ UI ควบคุมได้เมื่อ `gateway.auth.allowTailscale: true`, ข้อมูลประจำตัว Tailscale ตรวจสอบผ่าน และเบราว์เซอร์แสดงข้อมูลประจำตัวของอุปกรณ์
|
||||
- การผูก Tailnet โดยตรง การเชื่อมต่อเบราว์เซอร์ผ่าน LAN และโปรไฟล์เบราว์เซอร์ที่ไม่มีข้อมูลประจำตัวอุปกรณ์ยังคงต้องได้รับการอนุมัติอย่างชัดเจน
|
||||
- โปรไฟล์เบราว์เซอร์แต่ละรายการจะสร้าง ID อุปกรณ์ที่ไม่ซ้ำกัน ดังนั้นการเปลี่ยนเบราว์เซอร์หรือล้างข้อมูลเบราว์เซอร์จะต้องจับคู่ใหม่
|
||||
- การเชื่อมต่อเบราว์เซอร์ผ่าน local loopback โดยตรง (`127.0.0.1` / `localhost`) จะได้รับการอนุมัติโดยอัตโนมัติ
|
||||
- Tailscale Serve สามารถข้ามรอบการจับคู่สำหรับเซสชันผู้ปฏิบัติงาน Control UI ได้เมื่อ `gateway.auth.allowTailscale: true`, ตรวจสอบตัวตน Tailscale สำเร็จ และเบราว์เซอร์แสดงตัวตนอุปกรณ์ของตน
|
||||
- การ bind กับ Tailnet โดยตรง, การเชื่อมต่อเบราว์เซอร์ผ่าน LAN และโปรไฟล์เบราว์เซอร์ที่ไม่มีตัวตนอุปกรณ์ยังคงต้องได้รับการอนุมัติอย่างชัดเจน
|
||||
- แต่ละโปรไฟล์เบราว์เซอร์จะสร้าง ID อุปกรณ์ที่ไม่ซ้ำกัน ดังนั้นการเปลี่ยนเบราว์เซอร์หรือล้างข้อมูลเบราว์เซอร์จะต้องจับคู่ใหม่
|
||||
|
||||
</Note>
|
||||
|
||||
## ข้อมูลประจำตัวส่วนบุคคล (ภายในเบราว์เซอร์)
|
||||
## ตัวตนส่วนบุคคล (ภายในเบราว์เซอร์)
|
||||
|
||||
UI ควบคุมรองรับข้อมูลประจำตัวส่วนบุคคลต่อเบราว์เซอร์ (ชื่อที่แสดงและอวาตาร์) ซึ่งแนบกับข้อความขาออกเพื่อระบุผู้ส่งในเซสชันที่ใช้ร่วมกัน ข้อมูลนี้อยู่ในที่เก็บข้อมูลของเบราว์เซอร์ จำกัดขอบเขตอยู่ที่โปรไฟล์เบราว์เซอร์ปัจจุบัน และไม่ซิงค์ไปยังอุปกรณ์อื่นหรือคงอยู่ฝั่งเซิร์ฟเวอร์ นอกเหนือจากเมตาดาต้าผู้เขียน transcript ตามปกติบนข้อความที่คุณส่งจริง การล้างข้อมูลไซต์หรือเปลี่ยนเบราว์เซอร์จะรีเซ็ตข้อมูลนี้ให้ว่างเปล่า
|
||||
Control UI รองรับตัวตนส่วนบุคคลต่อเบราว์เซอร์ (ชื่อที่แสดงและอวาตาร์) ที่แนบกับข้อความขาออกเพื่อการระบุแหล่งที่มาในเซสชันที่ใช้ร่วมกัน ตัวตนนี้อยู่ในที่เก็บข้อมูลของเบราว์เซอร์ ถูกจำกัดขอบเขตไว้ที่โปรไฟล์เบราว์เซอร์ปัจจุบัน และไม่ซิงค์ไปยังอุปกรณ์อื่นหรือจัดเก็บถาวรฝั่งเซิร์ฟเวอร์ นอกเหนือจากเมทาดาทาการเป็นผู้เขียนทรานสคริปต์ตามปกติบนข้อความที่คุณส่งจริง การล้างข้อมูลไซต์หรือเปลี่ยนเบราว์เซอร์จะรีเซ็ตให้ว่างเปล่า
|
||||
|
||||
รูปแบบภายในเบราว์เซอร์เดียวกันนี้ใช้กับการแทนที่อวาตาร์ของผู้ช่วยด้วย อวาตาร์ผู้ช่วยที่อัปโหลดจะซ้อนทับข้อมูลประจำตัวที่ Gateway แก้ไขได้เฉพาะบนเบราว์เซอร์ภายในเครื่องเท่านั้น และจะไม่เดินทางไปกลับผ่าน `config.patch` ฟิลด์ config ที่ใช้ร่วมกัน `ui.assistant.avatar` ยังคงพร้อมใช้งานสำหรับไคลเอนต์ที่ไม่ใช่ UI ซึ่งเขียนฟิลด์นี้โดยตรง (เช่น gateway แบบสคริปต์หรือแดชบอร์ดแบบกำหนดเอง)
|
||||
รูปแบบภายในเบราว์เซอร์เดียวกันนี้ใช้กับการแทนที่อวาตาร์ผู้ช่วยด้วย อวาตาร์ผู้ช่วยที่อัปโหลดจะซ้อนทับตัวตนที่ Gateway ระบุได้เฉพาะบนเบราว์เซอร์ภายในเครื่อง และจะไม่ส่งไปกลับผ่าน `config.patch` ฟิลด์การตั้งค่า `ui.assistant.avatar` ที่ใช้ร่วมกันยังคงพร้อมใช้งานสำหรับไคลเอนต์ที่ไม่ใช่ UI ซึ่งเขียนฟิลด์นี้โดยตรง (เช่น Gateway แบบสคริปต์หรือแดชบอร์ดแบบกำหนดเอง)
|
||||
|
||||
## ปลายทาง config ขณะรันไทม์
|
||||
## เอนด์พอยต์การตั้งค่ารันไทม์
|
||||
|
||||
UI ควบคุมดึงการตั้งค่าขณะรันไทม์จาก `/__openclaw/control-ui-config.json` ปลายทางนี้ถูกควบคุมด้วยการยืนยันตัวตน Gateway เดียวกับพื้นผิว HTTP ส่วนที่เหลือ: เบราว์เซอร์ที่ไม่ได้ยืนยันตัวตนจะดึงข้อมูลไม่ได้ และการดึงข้อมูลสำเร็จต้องมี gateway token/รหัสผ่านที่ถูกต้องอยู่แล้ว ข้อมูลประจำตัว Tailscale Serve หรือข้อมูลประจำตัวพร็อกซีที่เชื่อถือได้
|
||||
Control UI ดึงการตั้งค่ารันไทม์จาก `/__openclaw/control-ui-config.json` เอนด์พอยต์นั้นถูกควบคุมด้วย Auth ของ Gateway เดียวกันกับพื้นผิว HTTP ส่วนที่เหลือ: เบราว์เซอร์ที่ไม่ได้ยืนยันตัวตนจะดึงข้อมูลไม่ได้ และการดึงข้อมูลที่สำเร็จต้องมีโทเค็น/รหัสผ่าน Gateway ที่ยังใช้ได้อยู่แล้ว, ตัวตน Tailscale Serve หรือ ตัวตนพร็อกซีที่เชื่อถือได้
|
||||
|
||||
## การรองรับภาษา
|
||||
|
||||
UI ควบคุมสามารถแปลตัวเองตาม locale ของเบราว์เซอร์ในการโหลดครั้งแรก หากต้องการแทนที่ภายหลัง ให้เปิด **ภาพรวม -> การเข้าถึง Gateway -> ภาษา** ตัวเลือก locale อยู่ในการ์ดการเข้าถึง Gateway ไม่ได้อยู่ใต้ลักษณะภายนอก
|
||||
Control UI สามารถปรับภาษาให้ตรงกับโลเคลของเบราว์เซอร์ในการโหลดครั้งแรก หากต้องการแทนที่ในภายหลัง ให้เปิด **ภาพรวม -> การเข้าถึง Gateway -> ภาษา** ตัวเลือกโลเคลอยู่ในการ์ดการเข้าถึง 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 ในเบราว์เซอร์
|
||||
- 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-load ในเบราว์เซอร์
|
||||
- โลเคลที่เลือกจะถูกบันทึกในที่เก็บข้อมูลของเบราว์เซอร์และนำกลับมาใช้ในการเข้าชมครั้งต่อไป
|
||||
- คีย์คำแปลที่ขาดหายจะ fallback เป็นภาษาอังกฤษ
|
||||
|
||||
คำแปลเอกสารถูกสร้างสำหรับชุด locale ที่ไม่ใช่ภาษาอังกฤษเดียวกัน แต่ตัวเลือกภาษา Mintlify ในตัวของไซต์เอกสารจำกัดเฉพาะรหัส locale ที่ Mintlify ยอมรับ เอกสารภาษาไทย (`th`) และเปอร์เซีย (`fa`) ยังคงถูกสร้างใน publish repo แต่อาจยังไม่ปรากฏในตัวเลือกนั้นจนกว่า Mintlify จะรองรับรหัสเหล่านี้
|
||||
คำแปลเอกสารจะถูกสร้างสำหรับชุดโลเคลที่ไม่ใช่ภาษาอังกฤษเดียวกัน แต่ตัวเลือกภาษา Mintlify ในตัวของไซต์เอกสารถูกจำกัดไว้ที่รหัสโลเคลที่ Mintlify ยอมรับ เอกสารภาษาไทย (`th`) และเปอร์เซีย (`fa`) ยังคงถูกสร้างใน repo สำหรับเผยแพร่ แต่อาจยังไม่ปรากฏในตัวเลือกนั้นจนกว่า Mintlify จะรองรับรหัสเหล่านั้น
|
||||
|
||||
## ธีมลักษณะภายนอก
|
||||
## ธีมลักษณะที่ปรากฏ
|
||||
|
||||
แผงลักษณะภายนอกเก็บธีมในตัว Claw, Knot และ Dash รวมถึงช่องนำเข้า tweakcn แบบภายในเบราว์เซอร์หนึ่งช่อง หากต้องการนำเข้าธีม ให้เปิด [ธีม tweakcn](https://tweakcn.com/themes), เลือกหรือสร้างธีม, คลิก **แชร์** แล้ววางลิงก์ธีมที่คัดลอกไว้ในลักษณะภายนอก ตัวนำเข้ายังรองรับ URL registry แบบ `https://tweakcn.com/r/themes/<id>`, URL editor เช่น `https://tweakcn.com/editor/theme?theme=amethyst-haze`, พาธสัมพัทธ์ `/themes/<id>`, ID ธีมดิบ และชื่อธีมเริ่มต้น เช่น `amethyst-haze`
|
||||
แผงลักษณะที่ปรากฏยังคงมีธีม Claw, Knot และ Dash ในตัว รวมถึงช่องนำเข้า tweakcn แบบภายในเบราว์เซอร์หนึ่งช่อง หากต้องการนำเข้าธีม ให้เปิด [tweakcn editor](https://tweakcn.com/editor/theme), เลือกหรือสร้างธีม, คลิก **แชร์** และวางลิงก์ธีมที่คัดลอกไว้ลงในลักษณะที่ปรากฏ ตัวนำเข้ายังรองรับ URL รีจิสทรี `https://tweakcn.com/r/themes/<id>`, URL ตัวแก้ไขอย่าง `https://tweakcn.com/editor/theme?theme=amethyst-haze`, พาธสัมพัทธ์ `/themes/<id>`, ID ธีมดิบ และชื่อธีมเริ่มต้น เช่น `amethyst-haze`
|
||||
|
||||
ธีมที่นำเข้าจะถูกเก็บไว้เฉพาะในโปรไฟล์เบราว์เซอร์ปัจจุบันเท่านั้น ธีมเหล่านี้จะไม่ถูกเขียนลงใน config ของ Gateway และไม่ซิงค์ข้ามอุปกรณ์ การแทนที่ธีมที่นำเข้าจะอัปเดตช่องภายในหนึ่งช่องนั้น การล้างธีมจะเปลี่ยนธีมที่ใช้งานอยู่กลับเป็น Claw หากธีมที่นำเข้าถูกเลือกอยู่
|
||||
ธีมที่นำเข้าจะถูกเก็บไว้เฉพาะในโปรไฟล์เบราว์เซอร์ปัจจุบันเท่านั้น ธีมเหล่านี้จะไม่ถูกเขียนลงในการตั้งค่า Gateway และไม่ซิงค์ข้ามอุปกรณ์ การแทนที่ธีมที่นำเข้าจะอัปเดตช่องภายในเครื่องเพียงช่องเดียว การล้างธีมจะเปลี่ยนธีมที่ใช้งานกลับไปเป็น Claw หากธีมที่นำเข้าเคยถูกเลือกไว้
|
||||
|
||||
## สิ่งที่ทำได้ (ปัจจุบัน)
|
||||
## สิ่งที่ทำได้ (ตอนนี้)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="แชทและพูดคุย">
|
||||
- แชทกับโมเดลผ่าน Gateway WS (`chat.history`, `chat.send`, `chat.abort`, `chat.inject`)
|
||||
- พูดคุยผ่านเซสชันเรียลไทม์ของเบราว์เซอร์ OpenAI ใช้ WebRTC โดยตรง, Google Live ใช้ token เบราว์เซอร์แบบใช้ครั้งเดียวที่ถูกจำกัดผ่าน WebSocket และ plugin เสียงเรียลไทม์แบบ backend-only ใช้ทรานสปอร์ต relay ของ Gateway relay จะเก็บข้อมูลรับรองของผู้ให้บริการไว้บน Gateway ขณะที่เบราว์เซอร์สตรีม PCM จากไมโครโฟนผ่าน RPC `talk.realtime.relay*` และส่งการเรียกเครื่องมือ `openclaw_agent_consult` กลับผ่าน `chat.send` สำหรับโมเดล OpenClaw ขนาดใหญ่กว่าที่กำหนดค่าไว้
|
||||
- สตรีมการเรียกเครื่องมือ + การ์ดผลลัพธ์เครื่องมือสดในแชท (เหตุการณ์ agent)
|
||||
- พูดคุยผ่านเซสชันเรียลไทม์ของเบราว์เซอร์ OpenAI ใช้ WebRTC โดยตรง, Google Live ใช้โทเค็นเบราว์เซอร์แบบใช้ครั้งเดียวที่มีข้อจำกัดผ่าน WebSocket และ Plugin เสียงเรียลไทม์เฉพาะแบ็กเอนด์ใช้ทรานสปอร์ต relay ของ Gateway relay จะเก็บข้อมูลรับรองของผู้ให้บริการไว้บน Gateway ขณะที่เบราว์เซอร์สตรีม PCM จากไมโครโฟนผ่าน RPC `talk.realtime.relay*` และส่งการเรียกเครื่องมือ `openclaw_agent_consult` กลับผ่าน `chat.send` สำหรับโมเดล OpenClaw ที่ตั้งค่าไว้ขนาดใหญ่กว่า
|
||||
- สตรีมการเรียกเครื่องมือ + การ์ดเอาต์พุตเครื่องมือแบบสดในแชท (เหตุการณ์ของเอเจนต์)
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="ช่องทาง อินสแตนซ์ เซสชัน ความฝัน">
|
||||
- ช่องทาง: สถานะช่องทางในตัวรวมถึง plugin ที่ bundled/ภายนอก, การเข้าสู่ระบบ QR และ config รายช่องทาง (`channels.status`, `web.login.*`, `config.patch`)
|
||||
- ช่องทาง: สถานะช่องทางในตัวและช่องทาง Plugin แบบ bundled/ภายนอก, การเข้าสู่ระบบด้วย QR และการตั้งค่าต่อช่องทาง (`channels.status`, `web.login.*`, `config.patch`)
|
||||
- อินสแตนซ์: รายการ presence + รีเฟรช (`system-presence`)
|
||||
- เซสชัน: รายการ + การแทนที่โมเดล/thinking/fast/verbose/trace/reasoning รายเซสชัน (`sessions.list`, `sessions.patch`)
|
||||
- ความฝัน: สถานะ dreaming, สวิตช์เปิด/ปิด และตัวอ่านบันทึกความฝัน (`doctor.memory.status`, `doctor.memory.dreamDiary`, `config.patch`)
|
||||
- เซสชัน: รายการ + การแทนที่โมเดล/การคิด/เร็ว/ละเอียด/trace/reasoning ต่อเซสชัน (`sessions.list`, `sessions.patch`)
|
||||
- ความฝัน: สถานะ Dreaming, สวิตช์เปิด/ปิด และตัวอ่านบันทึกความฝัน (`doctor.memory.status`, `doctor.memory.dreamDiary`, `config.patch`)
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Cron, Skills, Node, การอนุมัติ exec">
|
||||
- งาน Cron: แสดงรายการ/เพิ่ม/แก้ไข/รัน/เปิดใช้งาน/ปิดใช้งาน + ประวัติการรัน (`cron.*`)
|
||||
- Skills: สถานะ, เปิดใช้งาน/ปิดใช้งาน, ติดตั้ง, อัปเดต API key (`skills.*`)
|
||||
- Node: รายการ + caps (`node.list`)
|
||||
- การอนุมัติ exec: แก้ไข allowlist ของ gateway หรือ node + นโยบาย ask สำหรับ `exec host=gateway/node` (`exec.approvals.*`)
|
||||
- Node: รายการ + ความสามารถ (`node.list`)
|
||||
- การอนุมัติ exec: แก้ไข allowlist ของ Gateway หรือ Node + นโยบายถามสำหรับ `exec host=gateway/node` (`exec.approvals.*`)
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Config">
|
||||
<Accordion title="การตั้งค่า">
|
||||
- ดู/แก้ไข `~/.openclaw/openclaw.json` (`config.get`, `config.set`)
|
||||
- ใช้ค่า + รีสตาร์ทพร้อมการตรวจสอบความถูกต้อง (`config.apply`) และปลุกเซสชันที่ใช้งานล่าสุด
|
||||
- การเขียนมี guard แบบ base-hash เพื่อป้องกันการทับการแก้ไขพร้อมกัน
|
||||
- การเขียน (`config.set`/`config.apply`/`config.patch`) จะ preflight การแก้ SecretRef ที่ใช้งานอยู่สำหรับ ref ใน payload config ที่ส่งมา; ref ที่ส่งมาซึ่งใช้งานอยู่แต่แก้ไม่ได้จะถูกปฏิเสธก่อนเขียน
|
||||
- การเรนเดอร์ schema + form (`config.schema` / `config.schema.lookup`, รวมถึงฟิลด์ `title` / `description`, hint ของ UI ที่ตรงกัน, สรุปลูกโดยตรง, เมตาดาต้าเอกสารบนโหนด object/wildcard/array/composition ที่ซ้อนกัน รวมถึง schema ของ plugin + ช่องทางเมื่อมี); editor Raw JSON พร้อมใช้งานเฉพาะเมื่อ snapshot มี raw round-trip ที่ปลอดภัย
|
||||
- หาก snapshot ไม่สามารถ round-trip ข้อความ raw ได้อย่างปลอดภัย Control UI จะบังคับใช้โหมด Form และปิดใช้งานโหมด Raw สำหรับ snapshot นั้น
|
||||
- editor Raw JSON "รีเซ็ตเป็นค่าที่บันทึกไว้" จะรักษารูปทรงที่เขียนแบบ raw (การจัดรูปแบบ, ความคิดเห็น, layout `$include`) แทนการเรนเดอร์ snapshot แบบแบนใหม่ ดังนั้นการแก้ไขภายนอกจะยังอยู่หลังรีเซ็ตเมื่อ snapshot สามารถ round-trip ได้อย่างปลอดภัย
|
||||
- ค่า object SecretRef แบบมีโครงสร้างจะแสดงเป็นแบบอ่านอย่างเดียวใน input ข้อความของฟอร์ม เพื่อป้องกันการทำให้ object กลายเป็น string โดยไม่ตั้งใจ
|
||||
- ใช้การตั้งค่า + รีสตาร์ทพร้อมการตรวจสอบ (`config.apply`) และปลุกเซสชันที่ใช้งานล่าสุด
|
||||
- การเขียนมีตัวป้องกัน base-hash เพื่อป้องกันการเขียนทับการแก้ไขที่เกิดขึ้นพร้อมกัน
|
||||
- การเขียน (`config.set`/`config.apply`/`config.patch`) จะตรวจสอบล่วงหน้าการ resolve SecretRef ที่ active สำหรับ refs ใน payload การตั้งค่าที่ส่งมา; refs ที่ active และส่งมาซึ่ง resolve ไม่ได้จะถูกปฏิเสธก่อนเขียน
|
||||
- การเรนเดอร์สคีมา + ฟอร์ม (`config.schema` / `config.schema.lookup`, รวมถึงฟิลด์ `title` / `description`, UI hints ที่ตรงกัน, สรุปลูกโดยตรง, เมทาดาทาเอกสารบนโหนด object/wildcard/array/composition ที่ซ้อนกัน รวมถึงสคีมา Plugin + ช่องทางเมื่อพร้อมใช้งาน); ตัวแก้ไข Raw JSON จะพร้อมใช้งานเฉพาะเมื่อ snapshot มีการ round-trip แบบ raw ที่ปลอดภัย
|
||||
- หาก snapshot ไม่สามารถ round-trip ข้อความ raw ได้อย่างปลอดภัย Control UI จะบังคับใช้โหมดฟอร์มและปิดใช้งานโหมด Raw สำหรับ snapshot นั้น
|
||||
- "รีเซ็ตเป็นค่าที่บันทึกไว้" ของตัวแก้ไข Raw JSON จะรักษารูปร่างที่เขียนแบบ raw ไว้ (การจัดรูปแบบ, ความคิดเห็น, เลย์เอาต์ `$include`) แทนการเรนเดอร์ snapshot แบบแบนใหม่ ดังนั้นการแก้ไขภายนอกจะยังคงอยู่หลังการรีเซ็ตเมื่อ snapshot สามารถ round-trip ได้อย่างปลอดภัย
|
||||
- ค่า object ของ SecretRef แบบมีโครงสร้างจะแสดงเป็นแบบอ่านอย่างเดียวในช่องข้อความของฟอร์ม เพื่อป้องกันการทำให้ object กลายเป็น string โดยไม่ตั้งใจ
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="ดีบัก บันทึก อัปเดต">
|
||||
- ดีบัก: snapshot สถานะ/สุขภาพ/โมเดล + บันทึกเหตุการณ์ + การเรียก RPC ด้วยตนเอง (`status`, `health`, `models.list`)
|
||||
- บันทึก: tail สดของไฟล์ log ของ gateway พร้อมตัวกรอง/ส่งออก (`logs.tail`)
|
||||
- อัปเดต: รันการอัปเดต package/git + รีสตาร์ท (`update.run`) พร้อมรายงานการรีสตาร์ท จากนั้น poll `update.status` หลังเชื่อมต่อใหม่เพื่อตรวจสอบเวอร์ชัน gateway ที่กำลังทำงาน
|
||||
- บันทึก: tail แบบสดของบันทึกไฟล์ Gateway พร้อมตัวกรอง/ส่งออก (`logs.tail`)
|
||||
- อัปเดต: รันการอัปเดตแพ็กเกจ/git + รีสตาร์ท (`update.run`) พร้อมรายงานการรีสตาร์ท จากนั้น poll `update.status` หลังเชื่อมต่อใหม่เพื่อตรวจสอบเวอร์ชัน Gateway ที่กำลังทำงาน
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="หมายเหตุแผงงาน Cron">
|
||||
- สำหรับงานแบบแยกเดี่ยว ค่า delivery เริ่มต้นคือการประกาศสรุป คุณสามารถเปลี่ยนเป็น none ได้หากต้องการการรันภายในเท่านั้น
|
||||
- สำหรับงานที่แยกอิสระ ค่าเริ่มต้นของการส่งคือประกาศสรุป คุณสามารถเปลี่ยนเป็นไม่มีได้หากต้องการการรันเฉพาะภายใน
|
||||
- ฟิลด์ช่องทาง/เป้าหมายจะปรากฏเมื่อเลือกประกาศ
|
||||
- โหมด Webhook ใช้ `delivery.mode = "webhook"` โดยตั้งค่า `delivery.to` เป็น URL HTTP(S) webhook ที่ถูกต้อง
|
||||
- สำหรับงาน main-session จะมีโหมด delivery แบบ webhook และ none ให้ใช้
|
||||
- ตัวควบคุมการแก้ไขขั้นสูงรวมถึง delete-after-run, ล้าง agent override, ตัวเลือก cron exact/stagger, การแทนที่โมเดล/thinking ของ agent และสวิตช์ delivery แบบ best-effort
|
||||
- การตรวจสอบความถูกต้องของฟอร์มอยู่ในบรรทัดเดียวกับข้อผิดพลาดระดับฟิลด์; ค่าที่ไม่ถูกต้องจะปิดใช้งานปุ่มบันทึกจนกว่าจะได้รับการแก้ไข
|
||||
- ตั้งค่า `cron.webhookToken` เพื่อส่ง bearer token เฉพาะ หากละเว้น webhook จะถูกส่งโดยไม่มีส่วนหัว auth
|
||||
- fallback ที่เลิกใช้แล้ว: งาน legacy ที่เก็บไว้พร้อม `notify: true` ยังสามารถใช้ `cron.webhook` ได้จนกว่าจะย้ายข้อมูล
|
||||
- โหมด Webhook ใช้ `delivery.mode = "webhook"` พร้อมตั้งค่า `delivery.to` เป็น URL HTTP(S) webhook ที่ถูกต้อง
|
||||
- สำหรับงาน main-session สามารถใช้โหมดการส่งแบบ Webhook และไม่มีได้
|
||||
- ตัวควบคุมการแก้ไขขั้นสูงประกอบด้วย delete-after-run, ล้างการแทนที่เอเจนต์, ตัวเลือก cron exact/stagger, การแทนที่โมเดล/การคิดของเอเจนต์ และสวิตช์การส่งแบบ best-effort
|
||||
- การตรวจสอบฟอร์มเป็นแบบ inline พร้อมข้อผิดพลาดระดับฟิลด์; ค่าที่ไม่ถูกต้องจะปิดใช้งานปุ่มบันทึกจนกว่าจะแก้ไข
|
||||
- ตั้งค่า `cron.webhookToken` เพื่อส่ง bearer token เฉพาะ หากละไว้ Webhook จะถูกส่งโดยไม่มีส่วนหัว Auth
|
||||
- fallback ที่เลิกใช้แล้ว: งาน legacy ที่จัดเก็บไว้พร้อม `notify: true` ยังสามารถใช้ `cron.webhook` ได้จนกว่าจะย้ายข้อมูล
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## พฤติกรรมการแชท
|
||||
## พฤติกรรมแชท
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="ความหมายของการส่งและประวัติ">
|
||||
- `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`
|
||||
- ระหว่างการส่งที่กำลังทำงานและการรีเฟรชประวัติขั้นสุดท้าย มุมมองแชตจะคงข้อความผู้ใช้/ผู้ช่วยแบบ optimistic ในเครื่องให้มองเห็นได้ หาก `chat.history` คืน snapshot ที่เก่ากว่าชั่วครู่ ทรานสคริปต์มาตรฐานจะแทนที่ข้อความในเครื่องเหล่านั้นเมื่อประวัติของ Gateway ตามทัน
|
||||
- เหตุการณ์ `chat` แบบสดคือสถานะการส่งมอบ ขณะที่ `chat.history` ถูกสร้างใหม่จากทรานสคริปต์เซสชันถาวร หลังเหตุการณ์ tool-final Control UI จะโหลดประวัติใหม่และรวมเฉพาะส่วนท้ายแบบ optimistic ขนาดเล็ก ขอบเขตของทรานสคริปต์มีอธิบายไว้ใน [WebChat](/th/web/webchat)
|
||||
- `chat.inject` เพิ่มบันทึกของผู้ช่วยต่อท้ายทรานสคริปต์เซสชันและกระจายเหตุการณ์ `chat` สำหรับการอัปเดตเฉพาะ UI (ไม่มีการรัน agent ไม่มีการส่งมอบผ่านช่องทาง)
|
||||
- ตัวเลือกโมเดลและการคิดในส่วนหัวแชตจะแพตช์เซสชันที่ใช้งานอยู่ทันทีผ่าน `sessions.patch`; สิ่งเหล่านี้เป็นการ override เซสชันแบบถาวร ไม่ใช่ตัวเลือกการส่งสำหรับเทิร์นเดียวเท่านั้น
|
||||
- การพิมพ์ `/new` ใน Control UI จะสร้างและสลับไปยังเซสชันแดชบอร์ดใหม่แบบเดียวกับ New Chat การพิมพ์ `/reset` จะคงการรีเซ็ตแบบในที่เดิมที่ชัดเจนของ Gateway สำหรับเซสชันปัจจุบัน
|
||||
- ตัวเลือกโมเดลแชตจะขอมุมมองโมเดลที่กำหนดค่าไว้ของ Gateway หากมี `agents.defaults.models` allowlist นั้นจะขับเคลื่อนตัวเลือก มิฉะนั้นตัวเลือกจะแสดงรายการ `models.providers.*.models` ที่ระบุชัดเจนพร้อมผู้ให้บริการที่มีการยืนยันตัวตนที่ใช้งานได้ แค็ตตาล็อกเต็มยังคงพร้อมใช้งานผ่าน debug `models.list` RPC ด้วย `view: "all"`
|
||||
- เมื่อรายงานการใช้งานเซสชัน Gateway สดแสดงแรงกดดันของบริบทสูง พื้นที่ตัวเรียบเรียงแชตจะแสดงประกาศบริบท และที่ระดับ Compaction ที่แนะนำ จะแสดงปุ่ม compact ที่รันเส้นทาง Compaction เซสชันปกติ snapshot โทเค็นที่ล้าสมัยจะถูกซ่อนไว้จนกว่า Gateway จะรายงานการใช้งานสดอีกครั้ง
|
||||
- `chat.send` เป็นแบบ **ไม่บล็อก**: ตอบรับทันทีด้วย `{ runId, status: "started" }` และสตรีมการตอบกลับผ่านเหตุการณ์ `chat`
|
||||
- การอัปโหลดแชตรองรับรูปภาพและไฟล์ที่ไม่ใช่วิดีโอ รูปภาพจะคงพาธรูปภาพดั้งเดิมไว้ ส่วนไฟล์อื่นจะถูกจัดเก็บเป็นสื่อที่จัดการโดยระบบและแสดงในประวัติเป็นลิงก์ไฟล์แนบ
|
||||
- การส่งซ้ำด้วย `idempotencyKey` เดิมจะส่งคืน `{ status: "in_flight" }` ระหว่างที่กำลังทำงาน และ `{ status: "ok" }` หลังเสร็จสิ้น
|
||||
- การตอบกลับของ `chat.history` ถูกจำกัดขนาดเพื่อความปลอดภัยของ UI เมื่อรายการทรานสคริปต์มีขนาดใหญ่เกินไป Gateway อาจตัดฟิลด์ข้อความยาว ละเว้นบล็อกเมทาดาทาที่หนัก และแทนที่ข้อความขนาดใหญ่เกินด้วยตัวยึดตำแหน่ง (`[chat.history omitted: message too large]`)
|
||||
- รูปภาพจากผู้ช่วย/ที่สร้างขึ้นจะถูกคงไว้เป็นการอ้างอิงสื่อที่จัดการโดยระบบ และให้บริการกลับผ่าน URL สื่อของ Gateway ที่ผ่านการยืนยันตัวตน ดังนั้นการโหลดซ้ำจึงไม่ขึ้นอยู่กับเพย์โหลดรูปภาพ base64 ดิบที่ต้องคงอยู่ในการตอบกลับประวัติแชต
|
||||
- `chat.history` ยังลบแท็กคำสั่งแบบอินไลน์ที่ใช้แสดงผลเท่านั้นออกจากข้อความผู้ช่วยที่มองเห็นได้ (เช่น `[[reply_to_*]]` และ `[[audio_as_voice]]`), เพย์โหลด XML การเรียกเครื่องมือแบบข้อความธรรมดา (รวมถึง `<tool_call>...</tool_call>`, `<function_call>...</function_call>`, `<tool_calls>...</tool_calls>`, `<function_calls>...</function_calls>` และบล็อกการเรียกเครื่องมือที่ถูกตัด), โทเค็นควบคุมโมเดล ASCII/เต็มความกว้างที่รั่วออกมา และละเว้นรายการผู้ช่วยที่ข้อความที่มองเห็นได้ทั้งหมดเป็นเพียงโทเค็นเงียบที่ตรงตัว `NO_REPLY` / `no_reply`
|
||||
- ระหว่างการส่งที่ยังทำงานอยู่และการรีเฟรชประวัติครั้งสุดท้าย มุมมองแชตจะยังคงแสดงข้อความผู้ใช้/ผู้ช่วยแบบคาดการณ์ในเครื่องไว้ หาก `chat.history` ส่งคืนสแนปช็อตเก่าชั่วครู่ ทรานสคริปต์ที่เป็นแหล่งอ้างอิงจะแทนที่ข้อความในเครื่องเหล่านั้นเมื่อประวัติ Gateway ตามทัน
|
||||
- เหตุการณ์ `chat` สดคือสถานะการส่งมอบ ขณะที่ `chat.history` ถูกสร้างใหม่จากทรานสคริปต์เซสชันที่คงทน หลังเหตุการณ์สุดท้ายของเครื่องมือ Control UI จะโหลดประวัติใหม่และผสานเฉพาะส่วนท้ายแบบคาดการณ์ขนาดเล็ก ขอบเขตของทรานสคริปต์มีเอกสารไว้ใน [WebChat](/th/web/webchat)
|
||||
- `chat.inject` ผนวกบันทึกของผู้ช่วยเข้ากับทรานสคริปต์เซสชันและกระจายเหตุการณ์ `chat` สำหรับการอัปเดตเฉพาะ UI (ไม่มีการรันเอเจนต์ ไม่มีการส่งผ่านช่องทาง)
|
||||
- ตัวเลือกโมเดลและการคิดในส่วนหัวแชตจะแพตช์เซสชันที่ใช้งานอยู่ทันทีผ่าน `sessions.patch`; สิ่งเหล่านี้เป็นการ override เซสชันแบบคงอยู่ ไม่ใช่ตัวเลือกการส่งที่ใช้เพียงหนึ่งรอบ
|
||||
- การพิมพ์ `/new` ใน Control UI จะสร้างและสลับไปยังเซสชันแดชบอร์ดใหม่เดียวกับ New Chat การพิมพ์ `/reset` จะคงการรีเซ็ตในตำแหน่งแบบชัดเจนของ Gateway สำหรับเซสชันปัจจุบัน
|
||||
- ตัวเลือกโมเดลแชตขอมุมมองโมเดลที่กำหนดค่าไว้ของ Gateway หากมี `agents.defaults.models` รายการอนุญาตนั้นจะขับเคลื่อนตัวเลือก มิฉะนั้นตัวเลือกจะแสดงรายการ `models.providers.*.models` ที่ระบุชัดเจน รวมถึงผู้ให้บริการที่มีการยืนยันตัวตนที่ใช้งานได้ แค็ตตาล็อกเต็มยังคงพร้อมใช้งานผ่าน RPC ดีบัก `models.list` พร้อม `view: "all"`
|
||||
- เมื่อรายงานการใช้งานเซสชัน Gateway ใหม่แสดงแรงกดดันบริบทสูง พื้นที่ตัวแต่งข้อความแชตจะแสดงประกาศบริบท และที่ระดับ Compaction ที่แนะนำจะแสดงปุ่มย่อบริบทซึ่งเรียกใช้เส้นทาง Compaction เซสชันปกติ สแนปช็อตโทเค็นที่ล้าสมัยจะถูกซ่อนไว้จนกว่า Gateway จะรายงานการใช้งานใหม่อีกครั้ง
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="โหมดพูดคุย (เรียลไทม์ในเบราว์เซอร์)">
|
||||
โหมดพูดคุยใช้ผู้ให้บริการเสียงเรียลไทม์ที่ลงทะเบียนไว้ กำหนดค่า OpenAI ด้วย `talk.provider: "openai"` พร้อม `talk.providers.openai.apiKey` หรือกำหนดค่า Google ด้วย `talk.provider: "google"` พร้อม `talk.providers.google.apiKey`; การกำหนดค่าผู้ให้บริการเรียลไทม์ของ Voice Call ยังสามารถนำกลับมาใช้เป็น fallback ได้ เบราว์เซอร์จะไม่ได้รับคีย์ API ผู้ให้บริการมาตรฐาน OpenAI จะได้รับ Realtime client secret แบบชั่วคราวสำหรับ WebRTC Google Live จะได้รับโทเค็นยืนยันตัวตน Live API แบบใช้ครั้งเดียวและจำกัดขอบเขตสำหรับเซสชัน WebSocket ของเบราว์เซอร์ โดยมีคำสั่งและการประกาศเครื่องมือที่ถูกล็อกไว้ในโทเค็นโดย Gateway ผู้ให้บริการที่เปิดเผยเฉพาะ backend realtime bridge จะทำงานผ่านการขนส่งแบบ relay ของ Gateway ดังนั้นข้อมูลรับรองและ vendor socket จะอยู่ฝั่งเซิร์ฟเวอร์ ขณะที่เสียงจากเบราว์เซอร์เคลื่อนผ่าน RPC ของ Gateway ที่ยืนยันตัวตนแล้ว พรอมป์เซสชัน Realtime ถูกประกอบโดย Gateway; `talk.realtime.session` ไม่ยอมรับการ override คำสั่งจากผู้เรียก
|
||||
โหมดพูดคุยใช้ผู้ให้บริการเสียงเรียลไทม์ที่ลงทะเบียนไว้ กำหนดค่า OpenAI ด้วย `talk.provider: "openai"` พร้อม `talk.providers.openai.apiKey` หรือกำหนดค่า Google ด้วย `talk.provider: "google"` พร้อม `talk.providers.google.apiKey`; การกำหนดค่าผู้ให้บริการเรียลไทม์ของ Voice Call ยังสามารถนำกลับมาใช้เป็นทางสำรองได้ เบราว์เซอร์จะไม่ได้รับคีย์ API ผู้ให้บริการมาตรฐาน OpenAI จะได้รับ client secret ของ Realtime แบบชั่วคราวสำหรับ WebRTC Google Live จะได้รับโทเค็นยืนยันตัวตน Live API แบบใช้ครั้งเดียวที่จำกัดไว้สำหรับเซสชัน WebSocket ในเบราว์เซอร์ โดยมีคำสั่งและการประกาศเครื่องมือถูกล็อกไว้ในโทเค็นโดย Gateway ผู้ให้บริการที่เปิดเผยเฉพาะบริดจ์เรียลไทม์ฝั่งแบ็กเอนด์จะทำงานผ่านทรานสปอร์ตรีเลย์ของ Gateway ดังนั้นข้อมูลรับรองและซ็อกเก็ตของผู้ขายจะอยู่ฝั่งเซิร์ฟเวอร์ ขณะที่เสียงของเบราว์เซอร์เคลื่อนผ่าน RPC ของ Gateway ที่ผ่านการยืนยันตัวตน พรอมป์เซสชัน Realtime ถูกประกอบโดย Gateway; `talk.realtime.session` ไม่รับการ override คำสั่งที่ผู้เรียกส่งมา
|
||||
|
||||
ในตัวเรียบเรียง Chat ตัวควบคุม Talk คือปุ่มรูปคลื่นถัดจากปุ่มถอดเสียงด้วยไมโครโฟน เมื่อ Talk เริ่มต้น แถวสถานะของตัวเรียบเรียงจะแสดง `Connecting Talk...` จากนั้นแสดง `Talk live` ขณะเชื่อมต่อเสียงแล้ว หรือ `Asking OpenClaw...` ขณะการเรียกเครื่องมือเรียลไทม์กำลังปรึกษาโมเดลขนาดใหญ่กว่าที่กำหนดค่าไว้ผ่าน `chat.send`
|
||||
ในตัวแต่งข้อความแชต ตัวควบคุม Talk คือปุ่มรูปคลื่นถัดจากปุ่มป้อนตามคำบอกด้วยไมโครโฟน เมื่อ Talk เริ่มต้น แถวสถานะของตัวแต่งข้อความจะแสดง `Connecting Talk...` จากนั้น `Talk live` ขณะเชื่อมต่อเสียงอยู่ หรือ `Asking OpenClaw...` ขณะที่การเรียกเครื่องมือเรียลไทม์กำลังปรึกษาโมเดลขนาดใหญ่ที่กำหนดค่าไว้ผ่าน `chat.send`
|
||||
|
||||
การ smoke แบบสดสำหรับ maintainer: `OPENAI_API_KEY=... GEMINI_API_KEY=... node --import tsx scripts/dev/realtime-talk-live-smoke.ts` ตรวจสอบการแลกเปลี่ยน SDP ของ OpenAI browser WebRTC, การตั้งค่า WebSocket ของเบราว์เซอร์สำหรับ Google Live constrained-token และ adapter เบราว์เซอร์ของ Gateway relay พร้อมสื่อไมโครโฟนจำลอง คำสั่งนี้พิมพ์เฉพาะสถานะผู้ให้บริการและไม่บันทึก secret
|
||||
การทดสอบสดสำหรับผู้ดูแล: `OPENAI_API_KEY=... GEMINI_API_KEY=... node --import tsx scripts/dev/realtime-talk-live-smoke.ts` ตรวจสอบการแลกเปลี่ยน SDP ของ OpenAI browser WebRTC, การตั้งค่า WebSocket ในเบราว์เซอร์ของ Google Live constrained-token และอะแดปเตอร์เบราว์เซอร์รีเลย์ของ Gateway พร้อมสื่อไมโครโฟนจำลอง คำสั่งนี้พิมพ์เฉพาะสถานะผู้ให้บริการและไม่บันทึกความลับ
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="หยุดและยกเลิก">
|
||||
- คลิก **หยุด** (เรียก `chat.abort`)
|
||||
- ขณะที่การรันกำลังทำงาน follow-up ปกติจะเข้าคิว คลิก **Steer** บนข้อความที่เข้าคิวเพื่อฉีด follow-up นั้นเข้าไปในเทิร์นที่กำลังทำงาน
|
||||
- พิมพ์ `/stop` (หรือวลี abort แบบ standalone เช่น `stop`, `stop action`, `stop run`, `stop openclaw`, `please stop`) เพื่อ abort นอกแบนด์
|
||||
- `chat.abort` รองรับ `{ sessionKey }` (ไม่มี `runId`) เพื่อ abort การรันที่ทำงานอยู่ทั้งหมดสำหรับเซสชันนั้น
|
||||
- คลิก **Stop** (เรียก `chat.abort`)
|
||||
- ขณะที่การรันกำลังทำงาน การติดตามผลตามปกติจะเข้าคิว คลิก **Steer** บนข้อความที่อยู่ในคิวเพื่อฉีดการติดตามผลนั้นเข้าไปในรอบที่กำลังรัน
|
||||
- พิมพ์ `/stop` (หรือวลีสั่งยกเลิกเดี่ยว ๆ เช่น `stop`, `stop action`, `stop run`, `stop openclaw`, `please stop`) เพื่อยกเลิกนอกแบนด์
|
||||
- `chat.abort` รองรับ `{ sessionKey }` (ไม่มี `runId`) เพื่อยกเลิกการรันที่ใช้งานอยู่ทั้งหมดสำหรับเซสชันนั้น
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="การเก็บส่วนบางส่วนหลัง abort">
|
||||
- เมื่อการรันถูก abort ข้อความผู้ช่วยบางส่วนยังสามารถแสดงใน UI ได้
|
||||
- Gateway จะเก็บข้อความผู้ช่วยบางส่วนที่ถูก abort ไว้ในประวัติทรานสคริปต์เมื่อมีเอาต์พุตในบัฟเฟอร์
|
||||
- รายการที่เก็บไว้มีเมทาดาทา abort เพื่อให้ผู้บริโภคทรานสคริปต์แยกส่วนบางส่วนจาก abort ออกจากเอาต์พุตที่เสร็จสมบูรณ์ตามปกติได้
|
||||
<Accordion title="การเก็บส่วนบางส่วนเมื่อยกเลิก">
|
||||
- เมื่อการรันถูกยกเลิก ข้อความผู้ช่วยบางส่วนยังสามารถแสดงใน UI ได้
|
||||
- Gateway คงข้อความผู้ช่วยบางส่วนที่ถูกยกเลิกไว้ในประวัติทรานสคริปต์เมื่อมีเอาต์พุตที่บัฟเฟอร์ไว้
|
||||
- รายการที่คงไว้มีเมทาดาทาการยกเลิก เพื่อให้ผู้บริโภคทรานสคริปต์แยกส่วนบางส่วนจากการยกเลิกออกจากเอาต์พุตที่เสร็จสมบูรณ์ตามปกติได้
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## การติดตั้ง PWA และ web push
|
||||
|
||||
Control UI มาพร้อม `manifest.webmanifest` และ service worker ดังนั้นเบราว์เซอร์สมัยใหม่จึงสามารถติดตั้งเป็น PWA แบบ standalone ได้ Web Push ช่วยให้ Gateway ปลุก PWA ที่ติดตั้งไว้ด้วยการแจ้งเตือนได้แม้แท็บหรือหน้าต่างเบราว์เซอร์จะไม่ได้เปิดอยู่
|
||||
Control UI มาพร้อม `manifest.webmanifest` และ service worker ดังนั้นเบราว์เซอร์สมัยใหม่จึงสามารถติดตั้งเป็น PWA แบบสแตนด์อโลนได้ Web Push ทำให้ Gateway ปลุก PWA ที่ติดตั้งแล้วด้วยการแจ้งเตือนได้ แม้เมื่อแท็บหรือหน้าต่างเบราว์เซอร์ไม่ได้เปิดอยู่
|
||||
|
||||
| พื้นที่ใช้งาน | ทำหน้าที่อะไร |
|
||||
| พื้นผิว | สิ่งที่ทำ |
|
||||
| ----------------------------------------------------- | ------------------------------------------------------------------ |
|
||||
| `ui/public/manifest.webmanifest` | manifest ของ PWA เบราว์เซอร์จะแสดงตัวเลือก "ติดตั้งแอป" เมื่อเข้าถึงได้ |
|
||||
| `ui/public/sw.js` | service worker ที่จัดการเหตุการณ์ `push` และการคลิกการแจ้งเตือน |
|
||||
| `push/vapid-keys.json` (ใต้ไดเรกทอรีสถานะของ OpenClaw) | keypair ของ VAPID ที่สร้างอัตโนมัติ ใช้ลงนาม payload ของ Web Push |
|
||||
| `push/web-push-subscriptions.json` | endpoint การสมัครรับข้อมูลของเบราว์เซอร์ที่เก็บถาวรไว้ |
|
||||
| `ui/public/manifest.webmanifest` | Manifest ของ PWA เบราว์เซอร์จะเสนอ "ติดตั้งแอป" เมื่อเข้าถึงได้ |
|
||||
| `ui/public/sw.js` | Service worker ที่จัดการเหตุการณ์ `push` และการคลิกการแจ้งเตือน |
|
||||
| `push/vapid-keys.json` (ภายใต้ไดเรกทอรีสถานะ OpenClaw) | คู่คีย์ VAPID ที่สร้างอัตโนมัติ ใช้ลงนามเพย์โหลด Web Push |
|
||||
| `push/web-push-subscriptions.json` | เอนด์พอยต์การสมัครรับของเบราว์เซอร์ที่คงไว้ |
|
||||
|
||||
Override keypair ของ VAPID ผ่าน env var บนกระบวนการ Gateway เมื่อคุณต้องการ pin คีย์ (สำหรับการปรับใช้หลายโฮสต์ การหมุนเวียน secret หรือการทดสอบ):
|
||||
Override คู่คีย์ VAPID ผ่านตัวแปรสภาพแวดล้อมบนโปรเซส Gateway เมื่อคุณต้องการตรึงคีย์ (สำหรับการปรับใช้หลายโฮสต์ การหมุนเวียนความลับ หรือการทดสอบ):
|
||||
|
||||
- `OPENCLAW_VAPID_PUBLIC_KEY`
|
||||
- `OPENCLAW_VAPID_PRIVATE_KEY`
|
||||
- `OPENCLAW_VAPID_SUBJECT` (ค่าเริ่มต้นคือ `mailto:openclaw@localhost`)
|
||||
|
||||
Control UI ใช้เมธอด Gateway ที่จำกัดด้วย scope เหล่านี้เพื่อลงทะเบียนและทดสอบการสมัครรับข้อมูลของเบราว์เซอร์:
|
||||
Control UI ใช้เมธอด Gateway ที่จำกัดด้วยสโคปเหล่านี้เพื่อลงทะเบียนและทดสอบการสมัครรับของเบราว์เซอร์:
|
||||
|
||||
- `push.web.vapidPublicKey` — ดึงคีย์สาธารณะ VAPID ที่ใช้งานอยู่
|
||||
- `push.web.subscribe` — ลงทะเบียน `endpoint` พร้อม `keys.p256dh`/`keys.auth`
|
||||
- `push.web.unsubscribe` — ลบ endpoint ที่ลงทะเบียนไว้
|
||||
- `push.web.test` — ส่งการแจ้งเตือนทดสอบไปยังการสมัครรับข้อมูลของผู้เรียก
|
||||
- `push.web.unsubscribe` — ลบเอนด์พอยต์ที่ลงทะเบียนไว้
|
||||
- `push.web.test` — ส่งการแจ้งเตือนทดสอบไปยังการสมัครรับของผู้เรียก
|
||||
|
||||
<Note>
|
||||
Web Push เป็นอิสระจากเส้นทาง relay ของ iOS APNS (ดู [การกำหนดค่า](/th/gateway/configuration) สำหรับ push ที่มี relay รองรับ) และเมธอด `push.test` ที่มีอยู่ ซึ่งมุ่งเป้าไปที่การจับคู่มือถือแบบ native
|
||||
Web Push เป็นอิสระจากเส้นทางรีเลย์ APNS ของ iOS (ดู [การกำหนดค่า](/th/gateway/configuration) สำหรับ push ที่มีรีเลย์รองรับ) และเมธอด `push.test` ที่มีอยู่ ซึ่งมุ่งเป้าไปที่การจับคู่มือถือแบบเนทีฟ
|
||||
</Note>
|
||||
|
||||
## การฝังแบบ hosted
|
||||
## การฝังแบบโฮสต์
|
||||
|
||||
ข้อความผู้ช่วยสามารถเรนเดอร์เนื้อหาเว็บแบบ hosted แบบอินไลน์ด้วย shortcode `[embed ...]` นโยบาย sandbox ของ iframe ถูกควบคุมโดย `gateway.controlUi.embedSandbox`:
|
||||
ข้อความผู้ช่วยสามารถเรนเดอร์เนื้อหาเว็บที่โฮสต์ไว้แบบอินไลน์ด้วยชอร์ตโค้ด `[embed ...]` นโยบาย sandbox ของ iframe ถูกควบคุมโดย `gateway.controlUi.embedSandbox`:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="เข้มงวด">
|
||||
ปิดการทำงานของสคริปต์ภายในการฝังแบบ hosted
|
||||
ปิดใช้งานการรันสคริปต์ภายในการฝังที่โฮสต์ไว้
|
||||
</Tab>
|
||||
<Tab title="scripts (ค่าเริ่มต้น)">
|
||||
อนุญาตการฝังแบบโต้ตอบได้ขณะยังคงแยก origin ไว้ นี่คือค่าเริ่มต้นและมักเพียงพอสำหรับเกม/วิดเจ็ตเบราว์เซอร์แบบ self-contained
|
||||
<Tab title="สคริปต์ (ค่าเริ่มต้น)">
|
||||
อนุญาตการฝังแบบโต้ตอบได้ ขณะยังคงแยกต้นทางไว้ นี่คือค่าเริ่มต้นและโดยทั่วไปเพียงพอสำหรับเกม/วิดเจ็ตในเบราว์เซอร์แบบสแตนด์อโลน
|
||||
</Tab>
|
||||
<Tab title="trusted">
|
||||
เพิ่ม `allow-same-origin` บน `allow-scripts` สำหรับเอกสาร same-site ที่ตั้งใจต้องใช้สิทธิ์ที่แข็งแรงกว่า
|
||||
<Tab title="เชื่อถือได้">
|
||||
เพิ่ม `allow-same-origin` บน `allow-scripts` สำหรับเอกสารในไซต์เดียวกันที่ตั้งใจต้องการสิทธิ์ที่แรงกว่า
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
@ -250,14 +250,14 @@ Web Push เป็นอิสระจากเส้นทาง relay ขอ
|
||||
```
|
||||
|
||||
<Warning>
|
||||
ใช้ `trusted` เฉพาะเมื่อเอกสารที่ฝังต้องการพฤติกรรม same-origin จริง ๆ สำหรับเกมและแคนวาสโต้ตอบส่วนใหญ่ที่ agent สร้างขึ้น `scripts` เป็นตัวเลือกที่ปลอดภัยกว่า
|
||||
ใช้ `trusted` เฉพาะเมื่อเอกสารที่ฝังจำเป็นต้องมีพฤติกรรม same-origin จริง ๆ สำหรับเกมและแคนวาสโต้ตอบส่วนใหญ่ที่เอเจนต์สร้างขึ้น `scripts` เป็นตัวเลือกที่ปลอดภัยกว่า
|
||||
</Warning>
|
||||
|
||||
URL ฝัง `http(s)` ภายนอกแบบ absolute ยังคงถูกบล็อกโดยค่าเริ่มต้น หากคุณตั้งใจต้องการให้ `[embed url="https://..."]` โหลดหน้าของบุคคลที่สาม ให้ตั้งค่า `gateway.controlUi.allowExternalEmbedUrls: true`
|
||||
URL การฝัง `http(s)` ภายนอกแบบสัมบูรณ์ยังคงถูกบล็อกโดยค่าเริ่มต้น หากคุณตั้งใจต้องการให้ `[embed url="https://..."]` โหลดหน้าของบุคคลที่สาม ให้ตั้งค่า `gateway.controlUi.allowExternalEmbedUrls: true`
|
||||
|
||||
## ความกว้างของข้อความแชต
|
||||
## ความกว้างข้อความแชต
|
||||
|
||||
ข้อความแชตที่จัดกลุ่มใช้ max-width เริ่มต้นที่อ่านง่าย การปรับใช้บนจอกว้างสามารถ override ได้โดยไม่ต้องแพตช์ CSS ที่ bundled ไว้ ด้วยการตั้งค่า `gateway.controlUi.chatMessageMaxWidth`:
|
||||
ข้อความแชตที่จัดกลุ่มใช้ค่า max-width เริ่มต้นที่อ่านง่าย การปรับใช้บนจอกว้างสามารถ override ได้โดยไม่ต้องแพตช์ CSS ที่รวมมา โดยตั้งค่า `gateway.controlUi.chatMessageMaxWidth`:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -269,13 +269,13 @@ URL ฝัง `http(s)` ภายนอกแบบ absolute ยังคงถ
|
||||
}
|
||||
```
|
||||
|
||||
ค่าจะถูกตรวจสอบก่อนถึงเบราว์เซอร์ ค่าที่รองรับรวมถึงความยาวและเปอร์เซ็นต์แบบธรรมดา เช่น `960px` หรือ `82%` พร้อมนิพจน์ความกว้างแบบจำกัด `min(...)`, `max(...)`, `clamp(...)`, `calc(...)` และ `fit-content(...)`
|
||||
ค่าจะถูกตรวจสอบก่อนถึงเบราว์เซอร์ ค่าที่รองรับรวมถึงความยาวธรรมดาและเปอร์เซ็นต์ เช่น `960px` หรือ `82%` รวมทั้งนิพจน์ความกว้าง `min(...)`, `max(...)`, `clamp(...)`, `calc(...)` และ `fit-content(...)` แบบมีข้อจำกัด
|
||||
|
||||
## การเข้าถึง tailnet (แนะนำ)
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Tailscale Serve แบบผสานรวม (แนะนำ)">
|
||||
คง Gateway ไว้บน loopback และให้ Tailscale Serve ทำ proxy ด้วย HTTPS:
|
||||
<Tab title="Tailscale Serve ในตัว (แนะนำ)">
|
||||
ให้ Gateway อยู่บน loopback และให้ Tailscale Serve เป็นพร็อกซีด้วย HTTPS:
|
||||
|
||||
```bash
|
||||
openclaw gateway --tailscale serve
|
||||
@ -285,16 +285,16 @@ URL ฝัง `http(s)` ภายนอกแบบ absolute ยังคงถ
|
||||
|
||||
- `https://<magicdns>/` (หรือ `gateway.controlUi.basePath` ที่คุณกำหนดค่าไว้)
|
||||
|
||||
โดยค่าเริ่มต้น คำขอ Control UI/WebSocket Serve สามารถยืนยันตัวตนผ่าน header ตัวตนของ Tailscale (`tailscale-user-login`) เมื่อ `gateway.auth.allowTailscale` เป็น `true` OpenClaw ตรวจสอบตัวตนโดย resolve ที่อยู่ `x-forwarded-for` ด้วย `tailscale whois` และจับคู่กับ header และยอมรับเฉพาะเมื่อคำขอเข้าถึง loopback พร้อม header `x-forwarded-*` ของ Tailscale สำหรับเซสชันผู้ปฏิบัติงาน Control UI ที่มีตัวตนอุปกรณ์เบราว์เซอร์ เส้นทาง Serve ที่ตรวจสอบแล้วนี้ยังข้ามรอบการจับคู่อุปกรณ์ด้วย เบราว์เซอร์ที่ไม่มีอุปกรณ์และการเชื่อมต่อบทบาท node ยังคงทำตามการตรวจสอบอุปกรณ์ปกติ ตั้งค่า `gateway.auth.allowTailscale: false` หากคุณต้องการบังคับใช้ข้อมูลรับรอง shared-secret อย่างชัดเจนแม้กับทราฟฟิก Serve จากนั้นใช้ `gateway.auth.mode: "token"` หรือ `"password"`
|
||||
โดยค่าเริ่มต้น คำขอ Control UI/WebSocket Serve สามารถยืนยันตัวตนผ่านส่วนหัวตัวตน Tailscale (`tailscale-user-login`) เมื่อ `gateway.auth.allowTailscale` เป็น `true` OpenClaw ตรวจสอบตัวตนโดย resolve ที่อยู่ `x-forwarded-for` ด้วย `tailscale whois` และจับคู่กับส่วนหัว และยอมรับเฉพาะเมื่อคำขอเข้ามาที่ loopback พร้อมส่วนหัว `x-forwarded-*` ของ Tailscale สำหรับเซสชันผู้ปฏิบัติงาน Control UI ที่มีตัวตนอุปกรณ์ของเบราว์เซอร์ เส้นทาง Serve ที่ผ่านการตรวจสอบนี้ยังข้ามรอบการจับคู่อุปกรณ์ด้วย เบราว์เซอร์ที่ไม่มีอุปกรณ์และการเชื่อมต่อบทบาท node ยังคงทำตามการตรวจสอบอุปกรณ์ตามปกติ ตั้งค่า `gateway.auth.allowTailscale: false` หากคุณต้องการบังคับใช้ข้อมูลรับรอง shared-secret อย่างชัดเจนแม้สำหรับทราฟฟิก Serve จากนั้นใช้ `gateway.auth.mode: "token"` หรือ `"password"`
|
||||
|
||||
สำหรับเส้นทางตัวตน Serve แบบ async นั้น ความพยายามยืนยันตัวตนที่ล้มเหลวสำหรับ IP ไคลเอนต์และ scope การยืนยันตัวตนเดียวกันจะถูกทำให้เป็นลำดับก่อนการเขียน rate-limit ดังนั้นการลองผิดซ้ำพร้อมกันจากเบราว์เซอร์เดียวกันอาจแสดง `retry later` ในคำขอที่สองแทนที่จะเป็น mismatch แบบธรรมดาสองรายการที่แข่งกันแบบขนาน
|
||||
สำหรับเส้นทางตัวตน Serve แบบ async นั้น ความพยายามยืนยันตัวตนที่ล้มเหลวสำหรับ IP ไคลเอนต์และสโคปการยืนยันตัวตนเดียวกันจะถูกทำให้เป็นลำดับก่อนเขียน rate-limit ดังนั้นการลองผิดพร้อมกันจากเบราว์เซอร์เดียวกันอาจแสดง `retry later` ในคำขอที่สอง แทนที่จะเป็น mismatch ธรรมดาสองรายการที่แข่งกันแบบขนาน
|
||||
|
||||
<Warning>
|
||||
การยืนยันตัวตน Serve แบบไม่มีโทเค็นถือว่าโฮสต์ gateway เชื่อถือได้ หากโค้ด local ที่ไม่น่าเชื่อถืออาจรันบนโฮสต์นั้น ให้บังคับใช้การยืนยันตัวตน token/password
|
||||
การยืนยันตัวตน Serve แบบไม่มีโทเค็นถือว่าโฮสต์ gateway นั้นเชื่อถือได้ หากโค้ดในเครื่องที่ไม่เชื่อถืออาจรันบนโฮสต์นั้น ให้บังคับใช้การยืนยันตัวตนด้วย token/password
|
||||
</Warning>
|
||||
|
||||
</Tab>
|
||||
<Tab title="Bind ไปยัง tailnet + token">
|
||||
<Tab title="ผูกกับ tailnet + token">
|
||||
```bash
|
||||
openclaw gateway --bind tailnet --token "$(openssl rand -hex 32)"
|
||||
```
|
||||
@ -312,19 +312,19 @@ URL ฝัง `http(s)` ภายนอกแบบ absolute ยังคงถ
|
||||
|
||||
หากคุณเปิดแดชบอร์ดผ่าน HTTP ธรรมดา (`http://<lan-ip>` หรือ `http://<tailscale-ip>`) เบราว์เซอร์จะทำงานใน **บริบทที่ไม่ปลอดภัย** และบล็อก WebCrypto โดยค่าเริ่มต้น OpenClaw **บล็อก** การเชื่อมต่อ Control UI ที่ไม่มีตัวตนอุปกรณ์
|
||||
|
||||
ข้อยกเว้นที่บันทึกไว้:
|
||||
ข้อยกเว้นที่มีเอกสาร:
|
||||
|
||||
- ความเข้ากันได้กับ HTTP ที่ไม่ปลอดภัยเฉพาะ localhost ด้วย `gateway.controlUi.allowInsecureAuth=true`
|
||||
- การยืนยันตัวตน Control UI ของผู้ปฏิบัติงานสำเร็จผ่าน `gateway.auth.mode: "trusted-proxy"`
|
||||
- ความเข้ากันได้ของ HTTP ที่ไม่ปลอดภัยเฉพาะ localhost ด้วย `gateway.controlUi.allowInsecureAuth=true`
|
||||
- การยืนยันตัวตน Control UI ของผู้ปฏิบัติงานที่สำเร็จผ่าน `gateway.auth.mode: "trusted-proxy"`
|
||||
- break-glass `gateway.controlUi.dangerouslyDisableDeviceAuth=true`
|
||||
|
||||
**การแก้ไขที่แนะนำ:** ใช้ HTTPS (Tailscale Serve) หรือเปิด UI ในเครื่อง:
|
||||
**วิธีแก้ที่แนะนำ:** ใช้ HTTPS (Tailscale Serve) หรือเปิด UI ภายในเครื่อง:
|
||||
|
||||
- `https://<magicdns>/` (Serve)
|
||||
- `http://127.0.0.1:18789/` (บนโฮสต์ Gateway)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="ลักษณะการทำงานของตัวสลับการรับรองความถูกต้องที่ไม่ปลอดภัย">
|
||||
<Accordion title="พฤติกรรมการสลับใช้การยืนยันตัวตนแบบไม่ปลอดภัย">
|
||||
```json5
|
||||
{
|
||||
gateway: {
|
||||
@ -335,14 +335,14 @@ URL ฝัง `http(s)` ภายนอกแบบ absolute ยังคงถ
|
||||
}
|
||||
```
|
||||
|
||||
`allowInsecureAuth` เป็นเพียงตัวสลับความเข้ากันได้สำหรับเครื่องภายในเท่านั้น:
|
||||
`allowInsecureAuth` เป็นเพียงตัวสลับความเข้ากันได้ภายในเครื่องเท่านั้น:
|
||||
|
||||
- อนุญาตให้เซสชัน Control UI บน localhost ดำเนินต่อได้โดยไม่มีข้อมูลประจำตัวของอุปกรณ์ในบริบท HTTP ที่ไม่ปลอดภัย
|
||||
- อนุญาตให้เซสชัน UI ควบคุมบน localhost ดำเนินต่อได้โดยไม่มีข้อมูลประจำตัวของอุปกรณ์ในบริบท HTTP ที่ไม่ปลอดภัย
|
||||
- ไม่ข้ามการตรวจสอบการจับคู่
|
||||
- ไม่ผ่อนปรนข้อกำหนดข้อมูลประจำตัวของอุปกรณ์ระยะไกล (ที่ไม่ใช่ localhost)
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="ใช้ในกรณีฉุกเฉินเท่านั้น">
|
||||
<Accordion title="ใช้เฉพาะกรณีฉุกเฉิน">
|
||||
```json5
|
||||
{
|
||||
gateway: {
|
||||
@ -354,14 +354,14 @@ URL ฝัง `http(s)` ภายนอกแบบ absolute ยังคงถ
|
||||
```
|
||||
|
||||
<Warning>
|
||||
`dangerouslyDisableDeviceAuth` ปิดการตรวจสอบข้อมูลประจำตัวของอุปกรณ์สำหรับ Control UI และเป็นการลดระดับความปลอดภัยอย่างรุนแรง ให้ย้อนกลับโดยเร็วหลังใช้งานฉุกเฉิน
|
||||
`dangerouslyDisableDeviceAuth` ปิดใช้งานการตรวจสอบข้อมูลประจำตัวของอุปกรณ์สำหรับ UI ควบคุม และเป็นการลดระดับความปลอดภัยอย่างรุนแรง ให้ย้อนกลับโดยเร็วหลังใช้ในเหตุฉุกเฉิน
|
||||
</Warning>
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="หมายเหตุเกี่ยวกับพร็อกซีที่เชื่อถือได้">
|
||||
- การรับรองความถูกต้องผ่านพร็อกซีที่เชื่อถือได้สำเร็จสามารถอนุญาตให้เซสชัน Control UI ของ **ผู้ปฏิบัติงาน** เข้าใช้งานได้โดยไม่มีข้อมูลประจำตัวของอุปกรณ์
|
||||
- สิ่งนี้ **ไม่** ขยายไปถึงเซสชัน Control UI บทบาท node
|
||||
- พร็อกซีย้อนกลับแบบ loopback บนโฮสต์เดียวกันยังคงไม่ตรงตามการรับรองความถูกต้องของพร็อกซีที่เชื่อถือได้ ดู [การรับรองความถูกต้องด้วยพร็อกซีที่เชื่อถือได้](/th/gateway/trusted-proxy-auth)
|
||||
- การยืนยันตัวตนผ่านพร็อกซีที่เชื่อถือได้สำเร็จสามารถอนุญาตเซสชัน UI ควบคุมของ **ผู้ปฏิบัติการ** ได้โดยไม่มีข้อมูลประจำตัวของอุปกรณ์
|
||||
- สิ่งนี้ **ไม่** ขยายไปถึงเซสชัน UI ควบคุมในบทบาทโหนด
|
||||
- พร็อกซีแบบย้อนกลับ local loopback บนโฮสต์เดียวกันยังคงไม่ผ่านการยืนยันตัวตนแบบพร็อกซีที่เชื่อถือได้ ดู [การยืนยันตัวตนด้วยพร็อกซีที่เชื่อถือได้](/th/gateway/trusted-proxy-auth)
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
@ -370,36 +370,46 @@ URL ฝัง `http(s)` ภายนอกแบบ absolute ยังคงถ
|
||||
|
||||
## นโยบายความปลอดภัยของเนื้อหา
|
||||
|
||||
Control UI มาพร้อมนโยบาย `img-src` ที่เข้มงวด: อนุญาตเฉพาะแอสเซ็ตจาก **origin เดียวกัน**, URL `data:` และ URL `blob:` ที่สร้างในเครื่องเท่านั้น URL รูปภาพระยะไกลแบบ `http(s)` และแบบสัมพันธ์กับโปรโตคอลจะถูกเบราว์เซอร์ปฏิเสธและจะไม่ส่งคำขอดึงข้อมูลผ่านเครือข่าย
|
||||
UI ควบคุมมาพร้อมกับนโยบาย `img-src` ที่เข้มงวด: อนุญาตเฉพาะแอสเซ็ต **ต้นทางเดียวกัน**, URL `data:`, และ URL `blob:` ที่สร้างภายในเครื่องเท่านั้น URL รูปภาพ `http(s)` ระยะไกลและ URL รูปภาพแบบสัมพันธ์กับโปรโตคอลจะถูกเบราว์เซอร์ปฏิเสธและจะไม่เกิดการดึงข้อมูลผ่านเครือข่าย
|
||||
|
||||
ความหมายในทางปฏิบัติ:
|
||||
ในทางปฏิบัติ หมายความว่า:
|
||||
|
||||
- อวาตาร์และรูปภาพที่ให้บริการภายใต้พาธสัมพัทธ์ (เช่น `/avatars/<id>`) ยังคงแสดงผล รวมถึง route อวาตาร์ที่ต้องรับรองความถูกต้องซึ่ง UI ดึงข้อมูลและแปลงเป็น URL `blob:` ภายในเครื่อง
|
||||
- URL `data:image/...` แบบอินไลน์ยังคงแสดงผล (มีประโยชน์สำหรับ payload ภายในโปรโตคอล)
|
||||
- URL `blob:` ภายในเครื่องที่สร้างโดย Control UI ยังคงแสดงผล
|
||||
- URL อวาตาร์ระยะไกลที่ปล่อยออกมาจาก metadata ของช่องทางจะถูกตัวช่วยอวาตาร์ของ Control UI ตัดออกและแทนที่ด้วยโลโก้/ป้ายกำกับในตัว ดังนั้นช่องทางที่ถูกเจาะหรือเป็นอันตรายจึงไม่สามารถบังคับให้เบราว์เซอร์ของผู้ปฏิบัติงานดึงรูปภาพระยะไกลตามอำเภอใจได้
|
||||
- อวาตาร์และรูปภาพที่ให้บริการใต้พาธสัมพันธ์ (เช่น `/avatars/<id>`) ยังคงแสดงผลได้ รวมถึงเส้นทางอวาตาร์ที่ต้องยืนยันตัวตนซึ่ง UI ดึงข้อมูลและแปลงเป็น URL `blob:` ภายในเครื่อง
|
||||
- URL `data:image/...` แบบอินไลน์ยังคงแสดงผลได้ (มีประโยชน์สำหรับเพย์โหลดภายในโปรโตคอล)
|
||||
- URL `blob:` ภายในเครื่องที่สร้างโดย UI ควบคุมยังคงแสดงผลได้
|
||||
- URL อวาตาร์ระยะไกลที่ปล่อยออกมาจากเมตาดาต้าของช่องทางจะถูกลบออกที่ตัวช่วยอวาตาร์ของ UI ควบคุม และแทนที่ด้วยโลโก้/แบดจ์ในตัว ดังนั้นช่องทางที่ถูกบุกรุกหรือประสงค์ร้ายจึงไม่สามารถบังคับให้เบราว์เซอร์ของผู้ปฏิบัติการดึงรูปภาพระยะไกลตามอำเภอใจได้
|
||||
|
||||
คุณไม่จำเป็นต้องเปลี่ยนอะไรเพื่อให้ได้ลักษณะการทำงานนี้ เพราะเปิดใช้อยู่เสมอและกำหนดค่าไม่ได้
|
||||
คุณไม่จำเป็นต้องเปลี่ยนอะไรเพื่อให้ได้พฤติกรรมนี้ เพราะเปิดใช้งานเสมอและกำหนดค่าไม่ได้
|
||||
|
||||
## การรับรองความถูกต้องของ route อวาตาร์
|
||||
## การยืนยันตัวตนของเส้นทางอวาตาร์
|
||||
|
||||
เมื่อกำหนดค่าการรับรองความถูกต้องของ Gateway แล้ว endpoint อวาตาร์ของ Control UI จะต้องใช้โทเค็น Gateway เดียวกับ API ส่วนที่เหลือ:
|
||||
เมื่อกำหนดค่าการยืนยันตัวตนของ Gateway แล้ว ปลายทางอวาตาร์ของ UI ควบคุมจะต้องใช้โทเค็น Gateway เดียวกับ API ส่วนที่เหลือ:
|
||||
|
||||
- `GET /avatar/<agentId>` ส่งคืนรูปภาพอวาตาร์ให้เฉพาะผู้เรียกที่รับรองความถูกต้องแล้วเท่านั้น `GET /avatar/<agentId>?meta=1` ส่งคืน metadata ของอวาตาร์ภายใต้กฎเดียวกัน
|
||||
- คำขอที่ไม่ได้รับรองความถูกต้องไปยัง route ใด route หนึ่งจะถูกปฏิเสธ (ตรงกับ route assistant-media ข้างเคียง) สิ่งนี้ป้องกันไม่ให้ route อวาตาร์รั่วไหลข้อมูลประจำตัวของ agent บนโฮสต์ที่ได้รับการป้องกันอยู่แล้ว
|
||||
- Control UI เองจะส่งต่อโทเค็น Gateway เป็นส่วนหัว bearer เมื่อดึงอวาตาร์ และใช้ URL blob ที่รับรองความถูกต้องแล้วเพื่อให้รูปภาพยังคงแสดงผลในแดชบอร์ด
|
||||
- `GET /avatar/<agentId>` ส่งคืนรูปภาพอวาตาร์ให้เฉพาะผู้เรียกที่ยืนยันตัวตนแล้วเท่านั้น `GET /avatar/<agentId>?meta=1` ส่งคืนเมตาดาต้าอวาตาร์ภายใต้กฎเดียวกัน
|
||||
- คำขอที่ไม่ได้ยืนยันตัวตนไปยังเส้นทางใดเส้นทางหนึ่งจะถูกปฏิเสธ (สอดคล้องกับเส้นทาง assistant-media ที่อยู่ข้างเคียง) ซึ่งป้องกันไม่ให้เส้นทางอวาตาร์เปิดเผยข้อมูลประจำตัวของเอเจนต์บนโฮสต์ที่ได้รับการป้องกันอยู่แล้ว
|
||||
- UI ควบคุมเองจะส่งต่อโทเค็น Gateway เป็นส่วนหัว bearer เมื่อดึงอวาตาร์ และใช้ URL blob ที่ยืนยันตัวตนแล้วเพื่อให้รูปภาพยังแสดงผลในแดชบอร์ดได้
|
||||
|
||||
หากคุณปิดการรับรองความถูกต้องของ Gateway (ไม่แนะนำบนโฮสต์ที่ใช้ร่วมกัน) route อวาตาร์ก็จะไม่ต้องรับรองความถูกต้องเช่นกัน สอดคล้องกับส่วนที่เหลือของ Gateway
|
||||
หากคุณปิดใช้งานการยืนยันตัวตนของ Gateway (ไม่แนะนำบนโฮสต์ที่ใช้ร่วมกัน) เส้นทางอวาตาร์จะไม่ต้องยืนยันตัวตนเช่นกัน ตามแนวทางเดียวกับส่วนที่เหลือของ Gateway
|
||||
|
||||
## การยืนยันตัวตนของเส้นทางสื่อผู้ช่วย
|
||||
|
||||
เมื่อกำหนดค่าการยืนยันตัวตนของ Gateway แล้ว ตัวอย่างสื่อภายในเครื่องของผู้ช่วยจะใช้เส้นทางสองขั้นตอน:
|
||||
|
||||
- `GET /__openclaw__/assistant-media?meta=1&source=<path>` ต้องใช้การยืนยันตัวตนผู้ปฏิบัติการของ UI ควบคุมตามปกติ เบราว์เซอร์จะส่งโทเค็น Gateway เป็นส่วนหัว bearer เมื่อตรวจสอบความพร้อมใช้งาน
|
||||
- การตอบกลับเมตาดาต้าที่สำเร็จจะมี `mediaTicket` อายุสั้นที่จำกัดขอบเขตกับพาธแหล่งที่มานั้นโดยตรง
|
||||
- URL รูปภาพ เสียง วิดีโอ และเอกสารที่เบราว์เซอร์แสดงผลจะใช้ `mediaTicket=<ticket>` แทนโทเค็นหรือรหัสผ่าน Gateway ที่ใช้งานอยู่ ตั๋วจะหมดอายุอย่างรวดเร็วและไม่สามารถอนุญาตแหล่งที่มาอื่นได้
|
||||
|
||||
สิ่งนี้ทำให้การแสดงผลสื่อตามปกติเข้ากันได้กับองค์ประกอบสื่อดั้งเดิมของเบราว์เซอร์ โดยไม่ใส่ข้อมูลรับรอง Gateway ที่นำกลับมาใช้ได้ซ้ำใน URL สื่อที่มองเห็นได้
|
||||
|
||||
## การสร้าง UI
|
||||
|
||||
Gateway ให้บริการไฟล์สแตติกจาก `dist/control-ui` สร้างไฟล์เหล่านั้นด้วย:
|
||||
Gateway ให้บริการไฟล์สแตติกจาก `dist/control-ui` สร้างไฟล์เหล่านี้ด้วย:
|
||||
|
||||
```bash
|
||||
pnpm ui:build
|
||||
```
|
||||
|
||||
ฐานแบบ absolute ที่เลือกใช้ได้ (เมื่อคุณต้องการ URL แอสเซ็ตแบบคงที่):
|
||||
ฐานแบบสัมบูรณ์ที่เป็นตัวเลือก (เมื่อคุณต้องการ URL แอสเซ็ตแบบคงที่):
|
||||
|
||||
```bash
|
||||
OPENCLAW_CONTROL_UI_BASE_PATH=/openclaw/ pnpm ui:build
|
||||
@ -411,11 +421,11 @@ OPENCLAW_CONTROL_UI_BASE_PATH=/openclaw/ pnpm ui:build
|
||||
pnpm ui:dev
|
||||
```
|
||||
|
||||
จากนั้นชี้ UI ไปยัง URL Gateway WS ของคุณ (เช่น `ws://127.0.0.1:18789`)
|
||||
จากนั้นชี้ UI ไปที่ URL WS ของ Gateway ของคุณ (เช่น `ws://127.0.0.1:18789`)
|
||||
|
||||
## การดีบัก/การทดสอบ: เซิร์ฟเวอร์พัฒนา + Gateway ระยะไกล
|
||||
## การดีบัก/ทดสอบ: เซิร์ฟเวอร์พัฒนา + Gateway ระยะไกล
|
||||
|
||||
Control UI เป็นไฟล์สแตติก เป้าหมาย WebSocket กำหนดค่าได้และอาจแตกต่างจาก HTTP origin ได้ สิ่งนี้สะดวกเมื่อคุณต้องการใช้เซิร์ฟเวอร์พัฒนา Vite ในเครื่อง แต่ให้ Gateway ทำงานที่อื่น
|
||||
UI ควบคุมเป็นไฟล์สแตติก เป้าหมาย WebSocket กำหนดค่าได้และอาจแตกต่างจากต้นทาง HTTP สิ่งนี้มีประโยชน์เมื่อคุณต้องการใช้เซิร์ฟเวอร์พัฒนา Vite ภายในเครื่อง แต่ Gateway ทำงานอยู่ที่อื่น
|
||||
|
||||
<Steps>
|
||||
<Step title="เริ่มเซิร์ฟเวอร์พัฒนา UI">
|
||||
@ -428,7 +438,7 @@ Control UI เป็นไฟล์สแตติก เป้าหมาย W
|
||||
http://localhost:5173/?gatewayUrl=ws%3A%2F%2F<gateway-host>%3A18789
|
||||
```
|
||||
|
||||
การรับรองความถูกต้องครั้งเดียวที่เลือกใช้ได้ (หากจำเป็น):
|
||||
การยืนยันตัวตนครั้งเดียวแบบตัวเลือก (หากจำเป็น):
|
||||
|
||||
```text
|
||||
http://localhost:5173/?gatewayUrl=wss%3A%2F%2F<gateway-host>%3A18789#token=<gateway-token>
|
||||
@ -439,17 +449,17 @@ Control UI เป็นไฟล์สแตติก เป้าหมาย W
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="หมายเหตุ">
|
||||
- `gatewayUrl` จะถูกเก็บใน localStorage หลังโหลดและถูกลบออกจาก URL
|
||||
- หากคุณส่ง endpoint `ws://` หรือ `wss://` แบบเต็มผ่าน `gatewayUrl` ให้เข้ารหัส URL ของค่า `gatewayUrl` เพื่อให้เบราว์เซอร์แยกวิเคราะห์ query string ได้ถูกต้อง
|
||||
- ควรส่ง `token` ผ่าน fragment ของ URL (`#token=...`) เมื่อทำได้ Fragment จะไม่ถูกส่งไปยังเซิร์ฟเวอร์ จึงหลีกเลี่ยงการรั่วไหลใน request-log และ Referer พารามิเตอร์ query แบบเดิม `?token=` ยังคงถูกนำเข้าเพียงครั้งเดียวเพื่อความเข้ากันได้ แต่ใช้เป็น fallback เท่านั้น และจะถูกตัดออกทันทีหลัง bootstrap
|
||||
- `password` ถูกเก็บไว้ในหน่วยความจำเท่านั้น
|
||||
- เมื่อตั้งค่า `gatewayUrl` แล้ว UI จะไม่ fallback ไปยัง credential จาก config หรือ environment ให้ระบุ `token` (หรือ `password`) อย่างชัดเจน การไม่มี credential ที่ระบุอย่างชัดเจนถือเป็นข้อผิดพลาด
|
||||
- `gatewayUrl` จะถูกเก็บไว้ใน localStorage หลังโหลดและถูกลบออกจาก URL
|
||||
- หากคุณส่งปลายทาง `ws://` หรือ `wss://` แบบเต็มผ่าน `gatewayUrl` ให้เข้ารหัสค่า `gatewayUrl` เป็น URL เพื่อให้เบราว์เซอร์แยกวิเคราะห์ query string ได้ถูกต้อง
|
||||
- ควรส่ง `token` ผ่าน fragment ของ URL (`#token=...`) เมื่อเป็นไปได้ Fragment จะไม่ถูกส่งไปยังเซิร์ฟเวอร์ ซึ่งช่วยหลีกเลี่ยงการรั่วไหลผ่านบันทึกคำขอและ Referer พารามิเตอร์ query `?token=` แบบเดิมยังคงถูกนำเข้าเพียงครั้งเดียวเพื่อความเข้ากันได้ แต่ใช้เป็นทางเลือกสำรองเท่านั้น และจะถูกลบทันทีหลัง bootstrap
|
||||
- `password` จะถูกเก็บไว้ในหน่วยความจำเท่านั้น
|
||||
- เมื่อกำหนด `gatewayUrl` แล้ว UI จะไม่ย้อนกลับไปใช้ข้อมูลรับรองจากค่ากำหนดหรือสภาพแวดล้อม ให้ระบุ `token` (หรือ `password`) อย่างชัดเจน การไม่มีข้อมูลรับรองที่ระบุอย่างชัดเจนถือเป็นข้อผิดพลาด
|
||||
- ใช้ `wss://` เมื่อ Gateway อยู่หลัง TLS (Tailscale Serve, พร็อกซี HTTPS เป็นต้น)
|
||||
- `gatewayUrl` จะถูกยอมรับเฉพาะในหน้าต่างระดับบนสุดเท่านั้น (ไม่ใช่แบบฝัง) เพื่อป้องกัน clickjacking
|
||||
- การปรับใช้ Control UI ที่ไม่ใช่ loopback ต้องตั้งค่า `gateway.controlUi.allowedOrigins` อย่างชัดเจน (origin แบบเต็ม) ซึ่งรวมถึงการตั้งค่าพัฒนาระยะไกลด้วย
|
||||
- การเริ่มต้น Gateway อาจเติม origin ภายในเครื่อง เช่น `http://localhost:<port>` และ `http://127.0.0.1:<port>` จาก bind และ port ของ runtime ที่มีผล แต่ origin ของเบราว์เซอร์ระยะไกลยังคงต้องมีรายการอย่างชัดเจน
|
||||
- อย่าใช้ `gateway.controlUi.allowedOrigins: ["*"]` ยกเว้นสำหรับการทดสอบภายในเครื่องที่ควบคุมอย่างเข้มงวด หมายถึงอนุญาต origin ของเบราว์เซอร์ใดก็ได้ ไม่ใช่ "จับคู่กับโฮสต์ใดก็ตามที่ฉันใช้อยู่"
|
||||
- `gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true` เปิดใช้งานโหมด fallback ของ origin จากส่วนหัว Host แต่เป็นโหมดความปลอดภัยที่อันตราย
|
||||
- `gatewayUrl` ยอมรับได้เฉพาะในหน้าต่างระดับบนสุดเท่านั้น (ไม่ใช่แบบฝัง) เพื่อป้องกัน clickjacking
|
||||
- การปรับใช้ UI ควบคุมที่ไม่ใช่ loopback ต้องตั้งค่า `gateway.controlUi.allowedOrigins` อย่างชัดเจน (ต้นทางแบบเต็ม) ซึ่งรวมถึงการตั้งค่าการพัฒนาระยะไกลด้วย
|
||||
- การเริ่มต้น Gateway อาจใส่ต้นทางภายในเครื่อง เช่น `http://localhost:<port>` และ `http://127.0.0.1:<port>` จาก bind และ port ของรันไทม์ที่มีผล แต่ต้นทางเบราว์เซอร์ระยะไกลยังคงต้องมีรายการที่ระบุไว้อย่างชัดเจน
|
||||
- อย่าใช้ `gateway.controlUi.allowedOrigins: ["*"]` ยกเว้นสำหรับการทดสอบภายในเครื่องที่ควบคุมอย่างเข้มงวด หมายถึงอนุญาตต้นทางเบราว์เซอร์ใดก็ได้ ไม่ใช่ "จับคู่กับโฮสต์ใดก็ตามที่ฉันกำลังใช้"
|
||||
- `gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true` เปิดใช้งานโหมดสำรองต้นทางจากส่วนหัว Host แต่เป็นโหมดความปลอดภัยที่อันตราย
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
@ -471,6 +481,6 @@ Control UI เป็นไฟล์สแตติก เป้าหมาย W
|
||||
## ที่เกี่ยวข้อง
|
||||
|
||||
- [แดชบอร์ด](/th/web/dashboard) — แดชบอร์ด Gateway
|
||||
- [การตรวจสอบสถานภาพ](/th/gateway/health) — การเฝ้าระวังสถานภาพ Gateway
|
||||
- [TUI](/th/web/tui) — ส่วนติดต่อผู้ใช้บนเทอร์มินัล
|
||||
- [การตรวจสอบสุขภาพ](/th/gateway/health) — การตรวจสอบสุขภาพ Gateway
|
||||
- [TUI](/th/web/tui) — อินเทอร์เฟซผู้ใช้แบบเทอร์มินัล
|
||||
- [WebChat](/th/web/webchat) — อินเทอร์เฟซแชตบนเบราว์เซอร์
|
||||
|
||||
Loading…
Reference in New Issue
Block a user