Web interfaces
สถาปัตยกรรมแดชบอร์ด
วิสัยทัศน์
ปัจจุบันการทำงานกับเอเจนต์เป็นเพียงสตรีมข้อความ แดชบอร์ดจะเปลี่ยนสิ่งนี้ให้เป็น โต๊ะทำงาน: เอเจนต์แสดงวิดเจ็ตแบบสดที่โต้ตอบได้ ผู้ใช้ปักหมุดวิดเจ็ตเหล่านั้นไว้บน พื้นที่ถาวร แชตเชื่อมติดไว้ด้านข้าง (หรือซ่อนไว้) และเนื้อหาหลักคือ บอร์ด ผู้ใช้เปลี่ยนจาก "สนทนากับเอเจนต์" เป็น "ใช้งานแผงควบคุมที่ เอเจนต์สร้างให้" โดยไม่ต้องออกจากเซสชันเลย
หลักการ:
- บอร์ดเป็นอีกหน้าหนึ่งของเซสชัน ไม่ใช่ออบเจ็กต์ใหม่ ทุกเซสชัน (เธรด)
มีสองหน้า ได้แก่ บันทึกบทสนทนาและบอร์ด เซสชันที่ไม่มีวิดเจ็ตปักหมุด
จะเป็นแชตธรรมดา เมื่อปักหมุดวิดเจ็ตหนึ่งรายการ บอร์ดก็จะมีอยู่ บอร์ดสืบทอด
ข้อมูลระบุตัวตนของเซสชัน ความเป็นเจ้าของโดยเอเจนต์ การตั้งชื่อ การปักหมุด และวงจรชีวิต ไม่มี
dashboard_createไม่มีรีจิสทรีบอร์ด และไม่มีโมเดล ACL แยกต่างหาก - ความเท่าเทียมของเอเจนต์ ทุกสิ่งที่ผู้ใช้ทำบนบอร์ดได้ เอเจนต์ก็ทำได้ ด้วยเครื่องมือ ได้แก่ เพิ่ม/อัปเดต/นำวิดเจ็ตออก จัดเรียงวิดเจ็ต จัดการแท็บ สลับ แท็บที่มองเห็น และเชื่อมติดหรือซ่อนแชต
- เป็นส่วนเนทีฟ ไม่ใช่การฝัง บอร์ดเป็นคอมโพเนนต์ Lit ในเชลล์ Control UI (ใช้ระบบการออกแบบเดียวกับส่วนอื่นของแอป) เฉพาะ เนื้อหา ของวิดเจ็ตเท่านั้นที่ ถูกแยกไว้ใน iframe ไม่มีแถบ URL และไม่มีส่วนควบคุมของเบราว์เซอร์
- พื้นผิวสำหรับเอเจนต์ขนาดเล็ก วิดเจ็ตได้รับการอ้างถึงด้วยชื่อที่คงที่และอัปเดต ณ ตำแหน่งเดิม เลย์เอาต์เป็นกริดแบบยืดหยุ่นที่จัดพื้นที่ให้กระชับโดยอัตโนมัติ เอเจนต์ระบุขนาดและ จุดยึดเท่านั้น ไม่ระบุพิกเซลหรือพิกัด
- ใช้ความสามารถแทนความไว้วางใจ โค้ดวิดเจ็ตเป็น HTML/JS ใด ๆ ที่เอเจนต์เขียนขึ้น และทำงานในแซนด์บ็อกซ์ที่เข้มงวด การเข้าถึง (ข้อมูล Gateway การดำเนินการ เครือข่าย) มีได้เฉพาะผ่าน แมนิเฟสต์ความสามารถที่ประกาศไว้และได้รับอนุญาตจากผู้ดำเนินการ
แนวคิด
| แนวคิด | คำจำกัดความ |
|---|---|
| เซสชัน (เธรด) | เซสชัน Gateway ที่มีอยู่ ซึ่งใช้ sessionKey ที่คงที่เป็นคีย์ และมีเอเจนต์เป็นเจ้าของ |
| บอร์ด | หน้าวิดเจ็ตของหนึ่งเซสชัน มีอยู่ก็ต่อเมื่อเซสชันมีวิดเจ็ต/แท็บ และยังคงอยู่หลัง /new//reset (เชื่อมโยงกับ sessionKey ไม่ใช่บันทึกบทสนทนา) |
| แท็บ | หน้าสำหรับนำเสนอของบอร์ด ซึ่งกำหนดวิดเจ็ต การจัดเรียง และสถานะการเชื่อมติดแชต (left/right/bottom/hidden) บอร์ดเริ่มต้นด้วยแท็บโดยนัยหนึ่งแท็บ |
| วิดเจ็ต | โปรแกรม HTML/JS ที่มีชื่อและทำงานในแซนด์บ็อกซ์ ซึ่งเซสชันเป็นเจ้าของ อ้างถึงด้วย sessionKey + name และอัปเดต ณ ตำแหน่งเดิมตามชื่อ |
| แมนิเฟสต์ความสามารถ | การประกาศขอบเขตการเข้าถึงแยกตามวิดเจ็ต ได้แก่ data (การผูกข้อมูลแบบอ่าน), actions (กริยาที่อยู่ในรายการอนุญาต), prompt (ส่งไปยังเซสชัน), net (ต้นทางที่อนุญาต) |
| ปักหมุด (วิดเจ็ต) | การย้ายวิดเจ็ตจากบันทึกบทสนทนาไปยังบอร์ดของเซสชัน (ผ่านส่วนควบคุมสำหรับผู้ใช้หรืออาร์กิวเมนต์เครื่องมือของเอเจนต์) การเลิกปักหมุดจะนำวิดเจ็ตออกจากบอร์ด |
| ปักหมุด (เซสชัน) | การปักหมุดเซสชันในแถบด้านข้างที่มีอยู่ เซสชันที่ปักหมุดและมีบอร์ดจะเปิดที่หน้าบอร์ด |
ขั้นตอนการใช้งาน UX
- การยกระดับ: เอเจนต์เรียก
show_widgetในแชตใดก็ได้ → วิดเจ็ตแสดงแบบอินไลน์ ในบันทึกบทสนทนาเหมือนในปัจจุบันทุกประการ → เมื่อวางเมาส์เหนือจะแสดง ปักหมุดไปยังแดชบอร์ด → วิดเจ็ต ปรากฏบนบอร์ดของเซสชัน เอเจนต์สามารถส่งpin: trueเพื่อทำเช่นเดียวกัน - มุมมองบอร์ด: เซสชันที่มีบอร์ดจะมีตัวสลับหน้า (แชต / แดชบอร์ด) มุมมองบอร์ด = แถบแท็บ (เฉพาะเมื่อมี >1 แท็บ) + กริดแบบยืดหยุ่น + บานหน้าต่างแชตที่เชื่อมติด แชตที่เชื่อมติดสามารถปรับขนาด ย้ายตำแหน่ง (ซ้าย/ขวา/ล่าง) และยุบได้เหมือน แถบด้านข้างทุกประการ ระบบจะจดจำสถานะการเชื่อมติดแยกตามแท็บ
- การลาก: ผู้ใช้ลากวิดเจ็ต กริดจะจัดพื้นที่ให้กระชับโดยอัตโนมัติ (วิดเจ็ตเลื่อนขึ้น และวิดเจ็ตข้างเคียง จัดเรียงใหม่) การปรับขนาดด้วยจุดจับจะยึดตามระดับขนาดที่กำหนด ไม่มีการวางตามพิกเซล — สำหรับทุกคน
- คำเตือนการรีเซ็ต:
/new//resetในเซสชันที่มีบอร์ดจะขอ การยืนยันใน UI เว็บ ("บริบทจะถูกรีเซ็ต แต่แดชบอร์ดยังคงอยู่") และเก็บ บอร์ดไว้ - แถบด้านข้าง: เซสชันที่ปักหมุดจะแสดงหน้าบอร์ดเมื่อมีบอร์ด บอร์ดของเซสชันหน้าแรกคือ "แดชบอร์ดเอเจนต์" เริ่มต้น
- การโต้ตอบ (สามระดับ ดูด้านล่าง): เหตุการณ์สถานะแบบเงียบ การส่ง พรอมป์ที่มองเห็นได้ และทริกเกอร์ระบบอัตโนมัติ
ระดับการโต้ตอบ
- เหตุการณ์สถานะ (ค่าเริ่มต้น) การโต้ตอบกับ UI ของวิดเจ็ตที่โมเดลควรรับรู้
แต่ไม่ควรตอบกลับ
bridge.emitState({...})จะผนวก ประกาศเซสชันแบบมีโครงสร้าง (ใช้กลไกเดียวกับประกาศกิจกรรมกลุ่ม) ระบบจะไม่ เริ่มรอบการทำงานของเอเจนต์ โมเดลจะเห็นประกาศที่สะสมไว้ในการทำงานครั้งถัดไป - พรอมป์ (การสนทนาโดยชัดแจ้ง)
bridge.sendPrompt(text)— ต้องมีการ กระตุ้นโดยผู้ใช้ ส่งข้อความผู้ใช้ที่มองเห็นได้เข้าสู่เซสชัน (แชตที่เชื่อมติด จะแสดงข้อความนั้น) มีการจำกัดอัตรา การส่งแต่ละครั้งต้องได้รับการยืนยันจากผู้ใช้ เว้นแต่วิดเจ็ตจะมี สิทธิ์ความสามารถprompt - ระบบอัตโนมัติ
bridge.runAction(name, args)— เรียกใช้การดำเนินการที่ประกาศใน แมนิเฟสต์ ชุดกริยาเริ่มต้น ได้แก่cron.trigger(เรียกใช้งาน Cron ที่มีอยู่ทันที) และbinding.refreshงาน Cron ทำงานอยู่แล้วในเซสชันการทำงานแบบแยกที่มองเห็นได้ และสามารถใช้โมเดลที่มีต้นทุนต่ำกว่า นี่คือเส้นทางที่ "โมเดลขนาดเล็กขับเคลื่อนวิดเจ็ต" ไม่มีเซสชันที่ซ่อนอยู่ไม่ว่าที่ใด
โมเดลวิดเจ็ตและการโฮสต์
HTML/JS ของวิดเจ็ตเขียนโดยเอเจนต์ (โดยทั่วไปผ่าน show_widget) ถูกห่อ
ด้วยเชลล์เอกสารมาตรฐาน (เมตา CSP ตัวรายงานขนาด และบูตสแตรปบริดจ์) และ
แสดงผลใน <iframe sandbox="allow-scripts"> (ไม่ใช้ allow-same-origin เด็ดขาด)
- วิดเจ็ตแบบอินไลน์ (บันทึกบทสนทนา) ยังคงใช้ไปป์ไลน์เอกสารแคนวาสปัจจุบัน: เขียนไว้ใต้ไดเรกทอรีสถานะ ให้บริการโดย Gateway ล้างตามขอบเขต และไม่ต้อง อนุมัติ (เนื่องจากไม่มีความสามารถโดยโครงสร้างอยู่แล้ว — การส่งพรอมป์ต้องได้รับการยืนยันจากผู้ใช้)
- วิดเจ็ตบอร์ด เป็นสถานะเซสชัน: ไบต์อยู่ในฐานข้อมูล SQLite ของเอเจนต์
ที่เป็นเจ้าของ (
board_widgets) และให้บริการผ่านเส้นทาง Gateway หลัก (/__openclaw__/board/<agentId>/<sessionKey>/<name>/) ที่อ่านฐานข้อมูล การปักหมุดวิดเจ็ตจากบันทึกบทสนทนาจะคัดลอกไบต์ ขีดจำกัด: 256 KB ต่อวิดเจ็ต และ 48 วิดเจ็ตต่อบอร์ด - อัปเดต ณ ตำแหน่งเดิม: การส่งวิดเจ็ตที่มี
nameเดิมอีกครั้งจะแทนที่ ไบต์ เพิ่มค่าrevisionกระจายboard.changedและมุมมองสดจะโหลด เฉพาะ iframe นั้นใหม่ - การตรึงไบต์: ความสามารถที่ได้รับอนุญาตจะผูกกับ sha256 ของไบต์
วิดเจ็ต การเปลี่ยนไบต์จะคงสิทธิ์
data/net/actionsไว้เฉพาะเมื่อรีวิชันใหม่ ประกาศส่วนย่อยของแมนิเฟสต์ที่ได้รับอนุญาต แมนิเฟสต์ที่ขยายขอบเขตจะ ขออนุมัติจากผู้ดำเนินการอีกครั้ง
วิดเจ็ตโฮสต์เนื้อหา ส่วนแอป MCP เป็นเนื้อหาชนิดหนึ่ง
วิดเจ็ตคือองค์ประกอบพื้นฐานของ OpenClaw: เซลล์บอร์ดที่มีชื่อ ปักหมุดแล้ว กำหนดขนาดแล้ว เซสชันเป็นเจ้าของ และมีระเบียนสิทธิ์ เนื้อหาที่แสดงอยู่ภายในเป็น ชนิดเนื้อหา:
html— เอเจนต์เขียนผ่านshow_widgetโดยเก็บไบต์ไว้ในพื้นที่จัดเก็บของบอร์ดmcp-app— มุมมองแอป MCP ของบุคคลที่สาม (ทรัพยากรui://จากเซิร์ฟเวอร์ ที่กำหนดค่าไว้) ซึ่งโฮสต์อยู่ภายในเซลล์วิดเจ็ต
แอป MCP ไม่ได้กำหนดโมเดลวิดเจ็ต แต่วิดเจ็ตได้รับความสามารถในการโฮสต์
แอปเหล่านี้ ข้อมูลระบุตัวตน ตำแหน่ง การปักหมุด สิทธิ์ และ API สำหรับผู้เขียนยังคง
เป็นของ OpenClaw ดังนั้นโค้ด show_widget จึงยังสั้นเท่าปัจจุบันและไม่
จำเป็นต้องทราบว่าข้อกำหนด MCP Apps มีอยู่
โครงสร้างพื้นฐานที่ใช้ร่วมกันด้านล่าง (นี่คือจุดที่เกิดการลดความซับซ้อน):
- โฮสต์แซนด์บ็อกซ์หนึ่งระบบ วิดเจ็ต
htmlแสดงผลผ่านไปป์ไลน์ที่เสริมความปลอดภัยเดียวกับ ที่แอป MCP ใช้เมื่อเปิดตัว (iframe ซ้อนสองชั้นบนต้นทางแซนด์บ็อกซ์เฉพาะ CSP แยกตามวิดเจ็ตที่ประกาศไว้และถอดรหัสแบบปิดเมื่อผิดพลาด) แทนโฮสต์ iframe เฉพาะกิจระบบที่สอง พร็อกซีรับ HTML เป็นค่า ดังนั้นเนื้อหาในเครื่องจึง เป็นกรณีปกติโดยธรรมชาติ - โมเดลการให้สิทธิ์หนึ่งระบบ ขอบเขตการเข้าถึงของวิดเจ็ตคือรายการอนุญาตที่ได้รับสิทธิ์
ไม่ว่าจะเป็นชนิดใด: สำหรับวิดเจ็ต
htmlคือเครื่องมือโฮสต์ ส่วนวิดเจ็ตmcp-appคือ เครื่องมือของเซิร์ฟเวอร์ที่แอปมองเห็นได้ (ผ่านกลไกallowedAppToolNamesที่มีอยู่ โดยทำให้คงทนแยกตามวิดเจ็ตแทนที่จะแยกตามรอบการสร้าง) - เครื่องมือโฮสต์สำหรับวิดเจ็ต
html(เปิดให้ใช้ผ่านบริดจ์วิดเจ็ตและตรวจสอบ กับสิทธิ์ที่ได้รับ):openclaw.prompt.send— ระดับ 2 กำหนดเส้นทางผ่านตัวเขียนข้อความที่มองเห็นได้ และต้องได้รับการยืนยันจากผู้ใช้ เว้นแต่จะได้รับอนุญาตopenclaw.state.emit— ประกาศเซสชันระดับ 1 (รวมรายการและจำกัดขนาด)openclaw.data.read— การผูกข้อมูลแบบอ่านอย่างเดียวที่กำหนดพารามิเตอร์ได้ (ชุด RPC แบบอ่านซึ่งอยู่ในรายการอนุญาตที่มีอยู่) โดย Gateway เป็นผู้แก้ค่าopenclaw.cron.trigger— ระบบอัตโนมัติระดับ 3
net= CSP การเข้าถึงเครือข่ายใช้การประกาศ CSP แยกตามวิดเจ็ต ที่เปิดใช้งานแล้ว (connect-srcต้นทาง) วิดเจ็ตสภาพอากาศที่อัปเดตตัวเอง ดึงข้อมูล API โดยตรงจากแซนด์บ็อกซ์โดยไม่เกี่ยวข้องกับ Gateway- สิทธิ์ วิดเจ็ตที่ไม่ประกาศสิ่งใดจะแสดงผลทันที (ทำงานในแซนด์บ็อกซ์
default-src 'none'และการส่งพรอมป์แต่ละครั้งต้องได้รับการยืนยัน) ซึ่งมีระดับความไว้วางใจเดียวกับ วิดเจ็ตแชตแบบอินไลน์ในปัจจุบัน เครื่องมือ/ต้นทางที่ประกาศไว้จะทำให้วิดเจ็ตอยู่ในpendingบนบอร์ด: การ์ดตัวยึดจะแสดงรายการเหล่านั้นด้วยภาษาที่มนุษย์อ่านเข้าใจ พร้อม อนุญาต/ปฏิเสธ ด้วยการแตะครั้งเดียว สิทธิ์แยกตามชื่อวิดเจ็ต สำหรับวิดเจ็ตhtmlสิทธิ์จะถูกตรึงตามไบต์ (sha256) และไบต์ที่เปลี่ยนไปจะคงสิทธิ์ไว้เฉพาะเมื่อ การประกาศมีขอบเขตแคบลง - ชิมสำหรับผู้เขียน ตัวห่อเอกสารจะแทรก
window.openclaw.sendPrompt/emitState/read/callเป็น API ที่คงที่สำหรับผู้เขียน ไม่ว่าการขนส่งเบื้องหลังจะเป็นช่องทางของเราหรือ AppBridge ก็เป็น รายละเอียดภายในที่ผู้เขียนวิดเจ็ตจะไม่เห็น การรายงานขนาดและโทเค็นธีม ใช้บริดจ์เดียวกัน
การแสดงบันทึกบทสนทนา: การ์ดวิดเจ็ตหนึ่งใบ
การแสดงแบบอินไลน์รวมเป็นหนึ่งบนองค์ประกอบพื้นฐานของวิดเจ็ต เมื่อผลลัพธ์เครื่องมือมี UI —
เอาต์พุต show_widget หรือผลลัพธ์เครื่องมือ MCP ที่มีทรัพยากรแอป — ระบบจะ
สร้าง วิดเจ็ตชั่วคราวที่ตั้งชื่ออัตโนมัติ (จำกัดขอบเขตตามเซสชันและถูกล้างออก) และ
บันทึกบทสนทนาจะแสดงการ์ดวิดเจ็ตใบเดียวที่แจกจ่ายตามชนิดเนื้อหา
การแสดงแอป MCP อัตโนมัติยังคงเป็นไปตามที่ข้อกำหนดคาดหวังทุกประการ (โมเดลไม่ต้องทำงานเพิ่ม)
เพียงแต่เบื้องล่าง เป็น วิดเจ็ต การทำเช่นนี้จะลบกรณีพิเศษ mcpApp
แบบขนานในการแสดงผลแชต (การจำกัดตามพื้นผิวและการขจัดรายการซ้ำแยกต่างหาก) ทำให้ UI
แบบอินไลน์ทั้งหมดมีส่วนควบคุมการปักหมุดเดียวกัน และทำให้รีจิสทรีวิดเจ็ตเป็นเส้นทางหลัก
สำหรับเปิดอีกครั้ง (การสร้างคืนจากการสแกนบันทึกบทสนทนายังคงเป็นทางเลือกสำรองสำหรับประวัติ
ที่ไม่เคยปักหมุด) โฮสต์แบบสแตนด์อโลนที่อ่านอย่างเดียวและใช้ตั๋วมีส่วนทับซ้อนกับบอร์ดในฐานะ
พื้นผิวถาวรสำหรับเปิดอีกครั้ง — เป็นตัวเลือกสำหรับการรวมระบบที่ต้องประเมินใน T6 ไม่ใช่
ข้อสันนิษฐาน
การจัดองค์ประกอบ: v1 ใช้การวางติดกันในกริด (วิดเจ็ตส่วนควบคุมของเอเจนต์อยู่ถัดจากวิดเจ็ตแอปบน แท็บเดียวกัน) v2 เพิ่ม สล็อตแอปที่โฮสต์จัดการ — HTML ของวิดเจ็ตเอเจนต์ประกาศ บริเวณสล็อต และโฮสต์ประกอบมุมมองแอปจริงเป็นแซนด์บ็อกซ์ระดับเดียวกัน แอปจะไม่แสดงผลภายใน iframe ของเอเจนต์ เพราะการซ้อนจะทำลายข้อมูลระบุตัวตน ของบริดจ์และเปิดทางให้เกิดการซ้อนทับ/คลิกแจ็ก UI แอปที่ได้รับสิทธิ์ ดังนั้นสล็อตจึงเป็น สัญญาเลย์เอาต์ ไม่ใช่การฝัง
วิดเจ็ตจากเซิร์ฟเวอร์ (แอป MCP ที่ปักหมุด)
เมื่อใช้โฮสต์แบบรวม การปักหมุดแอป MCP ของบุคคลที่สามเป็นเพียงวิดเจ็ตที่
ดึงเนื้อหาจากเซิร์ฟเวอร์แทนการจัดเก็บ: board_widgets จะเก็บ
ตัวอธิบาย (serverName, toolName, uiResourceUri, ต้นทาง
toolCallId + sessionKey) แทนไบต์ HTML และบอร์ดจะออก
สัญญาเช่ามุมมองใหม่เมื่อพ้น TTL 10 นาทีของรอบแชต (ดึงทรัพยากร ui://
ใหม่เมื่อข้อมูลล้าสมัย) มุมมองแอป MCP แบบอินไลน์ในแชตมีตัวเลือก ปักหมุดไปยังแดชบอร์ด
เช่นเดียวกับวิดเจ็ตของเอเจนต์ มุมมองที่เปิดใหม่เป็นแบบอ่านอย่างเดียวในขณะนี้ตามการออกแบบ
แอปที่ปักหมุดซึ่งควรโต้ตอบได้ต่อเนื่องจะได้รับสิทธิ์ถาวรสำหรับเครื่องมือที่แอปมองเห็นได้ของเซิร์ฟเวอร์
(แสดงรายการอนุญาตอย่างชัดเจนแก่ผู้ดำเนินการขณะปักหมุด) โดยแยกจาก
รอบการออกสิทธิ์ แอปที่ปักหมุดแต่ไม่ได้รับสิทธิ์จะยังคงเป็นแบบอ่านอย่างเดียว — แต่ยังมีประโยชน์สำหรับ
แดชบอร์ดแสดงผล v1 ปักหมุดไปยังบอร์ดของเซสชันต้นทาง การปักหมุดข้ามเซสชัน
ต้องใช้ตัวกลางสัญญาเช่าและต้องรอก่อน ประสานงานกับ PR #109807 ที่เปิดอยู่ (ui/message
การกำหนดเส้นทางคอมโพสเซอร์ การส่งต่อธีม/ขนาด)
เลย์เอาต์: กริดแบบยืดหยุ่น
12 คอลัมน์ ความสูงแถวคงที่ จัดให้กระชับอัตโนมัติ (เลื่อนขึ้นตามแรงโน้มถ่วง ดันหลบเมื่อ
ลาก — ความหมายแบบ gridstack แต่พัฒนาขึ้นเอง; คณิตศาสตร์กริดยังคงบริสุทธิ์และ
ไม่ขึ้นกับ DOM) สถานะเลย์เอาต์วิดเจ็ตต่อแท็บ: { name, w (1-12), h (rows) } รวมถึง
ลำดับ คำศัพท์สำหรับเอเจนต์:
size:sm(3×3) ·md(6×4) ·lg(8×6) ·xl(12×8) ·full(แท็บวิดเจ็ตเดียว)after: <widgetName>จุดยึดลำดับที่ไม่บังคับ; หากละไว้ = ต่อท้าย- ผู้ใช้ลาก/ปรับขนาดได้อย่างอิสระ; โมเดลลำดับ+ขนาดเดียวกันสามารถส่งไปกลับได้
โมเดลข้อมูล (DB ต่อเอเจนต์)
ตารางใหม่ใน agents/<agentId>/agent/openclaw-agent.sqlite
(ต้องเพิ่มเวอร์ชันสคีมาของ DB เอเจนต์ — ต้องได้รับการอนุมัติจากผู้ดำเนินการ
ก่อนรวมการเปลี่ยนแปลงนี้):
CREATE TABLE board_tabs ( session_key TEXT NOT NULL, tab_id TEXT NOT NULL, -- slug title TEXT NOT NULL, position INTEGER NOT NULL, chat_dock TEXT NOT NULL DEFAULT 'right', -- left|right|bottom|hidden created_by TEXT NOT NULL, -- 'user' | 'agent' PRIMARY KEY (session_key, tab_id)) STRICT; CREATE TABLE board_widgets ( session_key TEXT NOT NULL, name TEXT NOT NULL, -- stable widget name tab_id TEXT NOT NULL, title TEXT, html BLOB NOT NULL, -- wrapped document source sha256 TEXT NOT NULL, revision INTEGER NOT NULL, size_w INTEGER NOT NULL, size_h INTEGER NOT NULL, position INTEGER NOT NULL, -- order within tab (auto-compact input) manifest TEXT NOT NULL DEFAULT '{}', -- capability manifest JSON grant_state TEXT NOT NULL DEFAULT 'none', -- none|pending|granted|rejected granted_sha TEXT, -- byte-frozen grant created_by TEXT NOT NULL, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL, PRIMARY KEY (session_key, name)) STRICT;การมีอยู่ของบอร์ด = มีแถวใดก็ตามสำหรับ sessionKey การลบเซสชันจะลบ
แถวบอร์ดของเซสชันนั้น /new//reset จะไม่แตะต้องแถวเหล่านี้
พื้นผิวโปรโตคอล
RPC (ตารางเมธอดหลัก สคีมา typebox ใน gateway-protocol):
board.get { sessionKey }→ แท็บ + เมทาดาทาวิดเจ็ต (ไม่มีไบต์) —operator.readboard.update { sessionKey, ops[] }— CRUD/จัดลำดับแท็บใหม่, ย้าย/ปรับขนาด/ ลบ/เลิกปักหมุดวิดเจ็ต, สถานะด็อก, โฟกัสแท็บ —operator.writeboard.widget.put { sessionKey, name, html, manifest, placement }—operator.write(เส้นทางเครื่องมือเอเจนต์และเส้นทางปักหมุด)board.widget.grant { sessionKey, name, decision }—operator.approvalsboard.event { sessionKey, widget, payload }— รับเข้าเหตุการณ์สถานะระดับ 1 —operator.write
เหตุการณ์ (ใน EVENT_SCOPE_GUARDS, ขอบเขตการอ่าน):
board.changed { sessionKey, revision, widget? }— สถานะที่คงอยู่เปลี่ยนแปลง; UI ดึงข้อมูลใหม่ (และโหลด iframe หนึ่งรายการใหม่เมื่อมีwidget)board.command { sessionKey, command }— ควบคุม UI ชั่วคราว (เอเจนต์สลับ แท็บที่มองเห็นหรือสลับด็อกแชต) — รูปแบบui.command
ไบต์ของวิดเจ็ตให้บริการผ่านพื้นผิว HTTP ที่ผ่านการยืนยันตัวตน ไม่ใช่ซ็อกเก็ต
เครื่องมือเอเจนต์
มีเครื่องมือทั้งหมดสามรายการ (อยู่ในแกนหลัก ลงทะเบียนเสมอ; การเรนเดอร์ถูกควบคุมด้วย
ความสามารถไคลเอนต์ inline-widgets เช่นเดียวกับปัจจุบัน):
show_widget { title, widget_code, name?, pin?, size?, tab?, after?, capabilities? }— สร้าง/อัปเดตตามชื่อ;pinวางรายการนั้นบนบอร์ด หากไม่มีname/pinจะทำงานเหมือนปัจจุบันทุกประการ (อินไลน์ ชั่วคราว)dashboard { action, ... }— คำสั่งจัดการบอร์ด:read,tab_create,tab_update,tab_delete,tabs_reorder,widget_move,widget_remove,unpin,focus_tab,set_chat_dock- เครื่องมือ
cronที่มีอยู่ครอบคลุมระดับระบบอัตโนมัติแล้ว; ไม่ต้องมีเครื่องมือใหม่
คำอธิบายเครื่องมือสอนคำศัพท์เกี่ยวกับขนาด/จุดยึดและโมเดลระดับ เอเจนต์
จะได้รับแจ้งเหตุการณ์ระดับ 1 ของผู้ใช้ผ่านประกาศของเซสชัน เช่น
[dashboard] user clicked "Refresh" on widget weather (tab main)
สิ่งที่รายการนี้เข้ามาแทนที่
- ลบ
extensions/workspacesฟีเจอร์ทดลอง,enabledByDefault: false, ไม่เคยอยู่ในรุ่นเสถียร (ปรากฏครั้งแรกในรุ่นเบตา 2026.7.2) ไม่มี การย้ายข้อมูล; กฎ doctor จะลบ<stateDir>/workspaces/ที่ตกค้างหากมี แนวคิดที่นำมาใช้: คณิตศาสตร์กริดบริสุทธิ์ โมเดลความปลอดภัยของบริดจ์ (การเริ่มต้นพอร์ต, การควบคุมการผูก, ขีดจำกัดอัตรา), การอนุมัติแบบตรึงไบต์ - การโฮสต์วิดเจ็ตย้ายจาก
extensions/canvasไปยังแกนหลัก ที่เก็บเอกสารแคนวาส ตัวห่อเอกสาร การให้บริการ HTTP และเครื่องมือshow_widgetจะกลายเป็นส่วนแกนหลัก (src/canvas/); Plugin จะเก็บเครื่องมือควบคุม node-canvas (canvas) และ A2UI ไว้ การประกาศpluginSurfaceUrls["canvas"]และ เส้นทาง/__openclaw__/canvasเป็นสัญญาไคลเอนต์เนทีฟที่เผยแพร่แล้วและยังคง เสถียร เซสชัน Discord ยังคงใช้ตัวแปรshow_widgetที่ Discord เป็นเจ้าของ - ไม่แตะต้อง WorkBoard (การผสานรวมเป็นโครงการติดตามผล)
สิ่งที่ไม่ใช่เป้าหมาย (โครงการนี้)
- การแชร์บอร์ดหลายผู้ใช้/ACL (ในอนาคต; จะมาผ่านการแชร์เซสชัน)
- การเรนเดอร์บอร์ดแบบเนทีฟบน macOS/iOS (จะใช้งานได้ทุกที่ที่ฝัง Control UI; เส้นทางวิดเจ็ตอินไลน์ไม่มีการเปลี่ยนแปลง)
- วิดเจ็ตข้อมูลในตัว (การ์ดเซสชัน/การใช้งาน/cron) — บริดจ์ความสามารถร่วมกับ วิดเจ็ตที่เอเจนต์สร้างครอบคลุม v1; รีจิสทรีชนิดในตัวสามารถเพิ่มภายหลังได้
- WorkBoard บนแดชบอร์ด
แผนการดำเนินงาน
เวิร์กทรีอิสระ สร้างด้วย Codex รีวิว+รวมตามลำดับ รวมแล้วค่อยแก้ไข
| # | แบรนช์ | ขอบเขต | ขึ้นกับ |
|---|---|---|---|
| T1 | claude/dashboard-remove-workspaces |
ลบ Plugin เวิร์กสเปซ + UI + เอกสาร + คีย์ i18n; กฎล้างข้อมูลของ doctor | — |
| T2 | claude/dashboard-canvas-core |
ยกระดับการโฮสต์วิดเจ็ต + show_widget ไปยังแกนหลัก; Plugin แคนวาสเก็บเครื่องมือโหนดไว้; ไม่มีการเปลี่ยนแปลงพฤติกรรม |
— |
| T3 | claude/dashboard-domain |
ตาราง DB เอเจนต์ (เพิ่มเวอร์ชันสคีมา), RPC board.* + เหตุการณ์, เครื่องมือ dashboard, อาร์กิวเมนต์ปักหมุด/ชื่อ/แมนิเฟสต์ show_widget, ประกาศระดับ 1, รีเซ็ตโดยคงบอร์ดไว้ |
T2 |
| T4 | claude/dashboard-ui |
หน้าบอร์ด + แถบแท็บ + กริดยืดหยุ่นจัดให้กระชับอัตโนมัติ + ด็อกแชต (ซ้าย/ขวา/ล่าง/ซ่อน) + ตัวเลือกปักหมุดทรานสคริปต์ + หน้าบอร์ดในแถบด้านข้าง + การยืนยันรีเซ็ต | T3 (ใช้ม็อกก่อนผ่านฟิกซ์เจอร์สำหรับการพัฒนา) |
| T5 | claude/dashboard-capabilities |
ที่เก็บ/ UI สำหรับสิทธิ์ + การตรึงไบต์; ย้ายวิดเจ็ต html ไปยังโฮสต์แซนด์บ็อกซ์ที่ใช้ร่วมกัน; เครื่องมือโฮสต์ (openclaw.prompt.send/state.emit/data.read/cron.trigger); CSP net; ชิมสำหรับการเขียน |
T3, T4 |
| T7 | claude/dashboard-mcp-apps |
ชนิดเนื้อหา mcp-app: ตัวเลือกปักหมุดในมุมมองแอปอินไลน์, การจัดเก็บตัวอธิบาย, การออก/รีเฟรชสัญญาเช่าใหม่, สิทธิ์เครื่องมือเซิร์ฟเวอร์แบบถาวร (ใช้โฮสต์ MCP Apps ที่เผยแพร่แล้วซ้ำ) |
T3, T4 |
| T6 | ปรับแต่ง | E2E แบบสดบน Gateway ชั่วคราว (คีย์จริง), ภาพหน้าจอ, การแก้ไข, เขียน /web/dashboard ใหม่โดยเน้นผู้ใช้, รีวิวการเปิดใช้เป็นค่าเริ่มต้น |
ทั้งหมด |
การตรวจสอบความถูกต้องตามกฎของรีโพ: ใช้ vitest แบบเจาะจงในเครื่อง, เกตทั้งหมดบน
Crabbox/Testbox, $autoreview ก่อนรวมทุกครั้ง, การพิสูจน์แบบสดสำหรับ T6.