ระบบ Peer
Peer-to-peer บน LAN — ค้นหา Clew instances à¸à¸·à¹ˆà¸™, ส่งข้à¸à¸„วาม, มà¸à¸šà¸«à¸¡à¸²à¸¢à¸‡à¸²à¸™, à¹à¸¥à¸°à¸£à¸±à¸™à¸„ำสั่งระยะไà¸à¸¥
ระบบ peer à¸à¸¢à¸¹à¹ˆà¹ƒà¸™ src/peer/ à¹à¸¥à¸°à¸›à¸£à¸°à¸à¸à¸šà¸”้วย 3 ชั้นหลัà¸: PeerServer (HTTP server), PeerDiscovery (สà¹à¸à¸™ LAN), à¹à¸¥à¸° PeerStore (registry ในหน่วยความจำ)
สถาปัตยà¸à¸£à¸£à¸¡
┌─────────────────────────────────────────────────────────────────────────────â”
│ PEER SYSTEM FLOW │
└─────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────â”
│ /peer share │
│ (Machine A — Worker) │
└────────────┬─────────────┘
│
┌─────────────────┼─────────────────â”
â–¼ â–¼ â–¼
┌──────────────┠┌──────────────┠┌──────────────â”
│ PeerServer │ │PeerDiscovery │ │ PeerStore │
│ HTTP :random │ │ │ │ (in-memory) │
│ port │ │ │ │ │
└──────┬───────┘ └──────┬───────┘ └──────────────┘
│ │
│ ┌────────────┼────────────â”
│ │ │ │
│ ▼ ▼ ▼
│ ┌────────┠┌────────┠┌─────────────â”
│ │ File │ │ UDP │ │ PeerStore │
│ │ ~/.cl/ │ │multicast│ │ (singleton) │
│ │ peers/ │ │239... │ │ │
│ │{pid}. │ │:42069 │ │ │
│ │ json │ │ │ │ │
│ └────┬───┘ └────┬───┘ └─────────────┘
│ │ │
│ │ │ heartbeat ทุภ30s
│ │ │ stale timeout 90s
│ │ │
â–¼ â–¼ â–¼
┌─────────────────────────────────────────────────────â”
│ LAN NETWORK │
│ │
│ ┌─────────┠┌─────────┠│
│ │ Machine B│◄───────►│ Machine C│ ... │
│ │ Clew Code│ query │ Clew Code│ │
│ └────┬─────┘ └────┬─────┘ │
│ │ │ │
└────────┼────────────────────┼─────────────────────────┘
│ │
│ /peer discover │ /peer discover
â–¼ â–¼
â•â•â• WORKER (Machine A) ENDPOINTS â•â•â•
Peer à¸à¸·à¹ˆà¸™ POST /peer-info ──► { hostname, ip, cwd, shell, ... }
│ POST /peer-msg ──► รับข้à¸à¸„วาม chat
├───────────────► POST /peer-todo ──► รับ task (ไปà¸à¸¢à¸¹à¹ˆà¹ƒà¸™ inbox)
│ POST /peer-exec ──► รัน shell command + คืน stdout/stderr
â•â•â• CLIENT (Machine B) TOOLS â•â•â•
/peer discover ──► scan files + UDP query (3s timeout)
│
â–¼
[peer list]
│
┌───────────────────┼───────────────────â”
â–¼ â–¼ â–¼
/peer join /peer send_task /peer run
(POST /peer-info) (POST /peer-todo) (POST /peer-exec)
│
â–¼
/peer send_message ──► POST /peer-msg ──► inbox ปลายทาง
/peer broadcast ──► POST /peer-msg ──► ทุภpeer ที่เชื่à¸à¸¡à¸•่à¸
/peer ping ──► GET /peer-info ──► เช็ค alive
â•â•â• DAEMON (agentLoop.ts) â•â•â•
┌───────────────────────────────────â”
│ Autonomous Agent Loop │
│ - ฟัง /peer-todo ตลà¸à¸” 24/7 │
│ - รับ task จาภremote peers │
│ - execute ใน background worker │
│ - สูงสุด 3 workers พร้à¸à¸¡à¸à¸±à¸™ │
└───────────────────────────────────┘
â•â•â• DATA LIFECYCLE â•â•â•
advertise ──► heartbeat ทุภ30s
│
├── 90s ไม่มี heartbeat ──► stale → evict
│
stop share ──► send UDP "offline"
delete peer file
close HTTP server
เทคนิคà¹à¸¥à¸°à¸«à¸¥à¸±à¸à¸à¸²à¸£
Discovery à¹à¸šà¸šà¸ªà¸à¸‡à¸Šà¸±à¹‰à¸™ (Two-Layer Discovery)
ทำไมไม่ใช้à¹à¸„่ UDP multicast หรืà¸à¹à¸„่ file-based à¸à¸¢à¹ˆà¸²à¸‡à¹€à¸”ียว?
- File-based — ทำงานบนเครื่à¸à¸‡à¹€à¸”ียวà¸à¸±à¸™à¹„ด้ทันที โดยไม่ต้à¸à¸‡à¹ƒà¸Šà¹‰ network เลย à¹à¸„่à¸à¹ˆà¸²à¸™/เขียนไฟล์ JSON ใน
~/.claude/peers/ซึ่งเร็วà¸à¸§à¹ˆà¸²à¹à¸¥à¸°à¹„ม่ต้à¸à¸‡à¸à¸±à¸‡à¸§à¸¥à¹€à¸£à¸·à¹ˆà¸à¸‡ firewall - UDP Multicast — ข้ามเครื่à¸à¸‡à¹„ด้ผ่าน LAN ใช้ multicast group
239.255.37.37:42069ไม่ต้à¸à¸‡à¸£à¸¹à¹‰ IP ปลายทางล่วงหน้า - ทำไมต้à¸à¸‡à¸—ั้งสà¸à¸‡? — à¹à¸•่ละวิธีมีข้à¸à¸ˆà¸³à¸à¸±à¸”: file-based ข้ามเครื่à¸à¸‡à¹„ม่ได้, UDP multicast à¸à¸²à¸ˆà¸–ูà¸à¸šà¸¥à¹‡à¸à¸„ด้วย network policy à¸à¸²à¸£à¹ƒà¸Šà¹‰à¸—ั้งสà¸à¸‡à¸§à¸´à¸˜à¸µà¸—ำให้ discovery ทำงานได้ในทุà¸à¸ªà¸ าพà¹à¸§à¸”ล้à¸à¸¡ โดยไม่ต้à¸à¸‡à¹ƒà¸«à¹‰à¸œà¸¹à¹‰à¹ƒà¸Šà¹‰ configure à¸à¸°à¹„รเลย
Lease-based Task Claiming
เมื่à¸à¸¡à¸µà¸«à¸¥à¸²à¸¢ worker (หรืà¸à¸«à¸¥à¸²à¸¢ daemon process) วิ่งพร้à¸à¸¡à¸à¸±à¸™ จะป้à¸à¸‡à¸à¸±à¸™à¹„ม่ให้ task ถูà¸à¸—ำซ้ำได้à¸à¸¢à¹ˆà¸²à¸‡à¹„ร?
- Atomic lease — à¸à¹ˆà¸à¸™à¹€à¸£à¸´à¹ˆà¸¡ task, worker ต้à¸à¸‡à¸‚ภlease ด้วย
leaseTask(id, agentId)ซึ่งเช็คว่า task ยังไม่มีใครจà¸à¸‡ à¹à¸¥à¸°à¹€à¸‚ียน lease owner + expiry timestamp ลงไฟล์à¹à¸šà¸š atomic (read-modify-write ภายใต้ lock) - Lease expiry — ถ้า worker crash หรืภdisconnect, lease จะหมดà¸à¸²à¸¢à¸¸à¹€à¸à¸‡ (default 30 นาที) ทำให้ worker à¸à¸·à¹ˆà¸™à¸¡à¸²à¸£à¸±à¸šà¸‡à¸²à¸™à¸•่à¸à¹„ด้ — crash recovery โดยไม่ต้à¸à¸‡à¸¡à¸µ distributed coordinator
- Stale lease cleanup — ตà¸à¸™ startLoop จะรภ2 วินาที à¹à¸¥à¹‰à¸§à¹€à¸£à¸µà¸¢à¸
expireLeases()เพื่ภclear lease เà¸à¹ˆà¸²à¸ˆà¸²à¸ session à¸à¹ˆà¸à¸™à¸«à¸™à¹‰à¸² - ทำไมไม่ใช้ lock file? — lock file à¹à¸šà¸š OS-level (flock) ใช้ข้าม process บนเครื่à¸à¸‡à¹€à¸”ียวà¸à¸±à¸™à¹„ด้ à¹à¸•่ใช้ข้ามเครื่à¸à¸‡à¹„ม่ได้ Lease บนไฟล์ JSON à¹à¸à¹‰à¸›à¸±à¸à¸«à¸²à¸™à¸µà¹‰à¹„ด้โดยไม่ต้à¸à¸‡à¸žà¸¶à¹ˆà¸‡ external service à¸à¸¢à¹ˆà¸²à¸‡ Redis/ZooKeeper
Heartbeat + Stale Eviction
Peer discovery ต้à¸à¸‡à¸£à¸¹à¹‰à¸§à¹ˆà¸²à¹ƒà¸„รยัง alive à¸à¸¢à¸¹à¹ˆ โดยไม่ต้à¸à¸‡ polling:
- Push-based heartbeat — à¹à¸•่ละ peer ส่ง beacon ทุภ30 วินาที ผ่านทั้ง file (เขียน timestamp ใหม่) à¹à¸¥à¸° UDP multicast
- Pull-based eviction — consumer เช็คà¸à¸²à¸¢à¸¸à¸‚à¸à¸‡ peer entry ถ้าเà¸à¸´à¸™ 90 วินาที (
PEER_STALE_TIMEOUT) ถืà¸à¸§à¹ˆà¸² stale → evict - 3× heartbeat interval — timeout = 3 × heartbeat interval เป็นค่า default ในระบบ distributed systems (ให้โà¸à¸à¸²à¸ª retry à¸à¹ˆà¸à¸™å®£å¸ƒà¸•าย)
- Graceful shutdown — ตà¸à¸™
/peer stopจะส่ง UDP "offline" message + ลบไฟล์ peer ทันที ไม่ต้à¸à¸‡à¸£à¸ timeout
Random Port Binding
PeerServer bind ที่ port 0 (OS เลืà¸à¸ port ว่างให้):
- No port conflicts — ถ้าใช้ fixed port à¹à¸¥à¹‰à¸§à¸¡à¸µà¸«à¸¥à¸²à¸¢ instance จะชนà¸à¸±à¸™
- Security through obscurity — port สุ่มทำให้ attacker สà¹à¸à¸™à¸«à¸²à¸¢à¸²à¸à¸à¸§à¹ˆà¸² fixed port (à¹à¸•่ไม่ใช่ security หลัภ— security จริงà¸à¸¢à¸¹à¹ˆà¸—ี่ authentication layer)
- Discovery solves discovery — ไม่ต้à¸à¸‡à¸£à¸¹à¹‰ port ล่วงหน้า เพราะ discovery protocol จะบà¸à¸ port ให้เà¸à¸‡
Message Broadcasting
peer_broadcast ส่ง task ไปทุภpeer ที่เชื่à¸à¸¡à¸•่à¸à¸žà¸£à¹‰à¸à¸¡à¸à¸±à¸™:
- ไม่ใช่ UDP broadcast — ใช้ HTTP POST sequential ไปทีละ peer (fire-and-forget)
- รà¸à¸‡à¸£à¸±à¸š parallel สูงสุด 8 peers ต่ภ1 batch
- เหมาะสำหรับ: deploy to all machines, run tests everywhere, health check ทุภnode
à¸à¸‡à¸„์ประà¸à¸à¸šà¸«à¸¥à¸±à¸
PeerServer src/peer/PeerServer.ts
HTTP server ขนาดเล็à¸à¸—ี่เริ่มบน port สุ่ม (OS เลืà¸à¸à¹ƒà¸«à¹‰) เมื่à¸à¸£à¸±à¸™ /peer share à¹à¸•่ละ endpoint รà¸à¸‡à¸£à¸±à¸šà¸à¸²à¸£à¹‚ต้ตà¸à¸šà¹à¸šà¸šà¸•่างๆ:
| Endpoint | Method | หน้าที่ |
|---|---|---|
/peer-info | GET | ส่งข้à¸à¸¡à¸¹à¸¥ peer (hostname, IP, cwd, shell, platform) |
/peer-msg | POST | รับข้à¸à¸„วาม chat จาภpeer à¸à¸·à¹ˆà¸™ |
/peer-todo | POST | รับ task ที่ถูà¸à¸¡à¸à¸šà¸«à¸¡à¸²à¸¢à¸ˆà¸²à¸ peer à¸à¸·à¹ˆà¸™ |
/peer-exec | POST | รันคำสั่ง shell à¹à¸¥à¸°à¸ªà¹ˆà¸‡à¸„ืน stdout/stderr |
PeerDiscovery src/peer/PeerDiscovery.ts
à¸à¸¥à¹„à¸à¸„้นหา 2 วิธีทำงานร่วมà¸à¸±à¸™:
- File-based — à¹à¸•่ละ instance เขียนไฟล์
~/.claude/peers/{pid}.jsonเà¸à¹‡à¸šà¸‚้à¸à¸¡à¸¹à¸¥ hostname, IP, port, shell, cwd instances à¸à¸·à¹ˆà¸™à¸à¹ˆà¸²à¸™à¹„ฟล์เพื่à¸à¸„้นหา peer ในเครื่à¸à¸‡à¹€à¸”ียวà¸à¸±à¸™ - UDP Multicast — ส่ง heartbeat beacon ไปที่
239.255.37.37:42069ทุภ30 วินาที ตà¸à¸šà¸à¸¥à¸±à¸šclew-peer-queryด้วยclew-peer-infoใช้ข้ามเครื่à¸à¸‡ - Stale eviction — Peer ที่ไม่เห็น 90 วินาที (
PEER_STALE_TIMEOUT) จะถูà¸à¸¥à¸šà¸à¸±à¸•โนมัติ
PeerStore src/peer/PeerStore.ts
Singleton registry ในหน่วยความจำที่เà¸à¹‡à¸š peer ทั้งหมดที่รู้จัภ(ทั้งที่ค้นพบà¹à¸¥à¸°à¸—ี่ join เà¸à¸‡), ข้à¸à¸„วาม chat, todos, à¹à¸¥à¸° custom tags (ชื่à¸à¸—ี่à¸à¸³à¸«à¸™à¸”เà¸à¸‡, บทบาท)
- Discovered peers — ถูà¸à¸¥à¸šà¸à¸±à¸•โนมัติเมื่ภstale
- Joined connections — คงà¸à¸¢à¸¹à¹ˆà¸–าวร ไม่ถูà¸à¸¥à¸šà¸à¸±à¸•โนมัติ
- Tags — ชื่à¸à¸—ี่à¸à¸³à¸«à¸™à¸”เà¸à¸‡à¹à¸¥à¸°à¸šà¸—บาทต่ภpeer
Discovery Protocol
DiscoveryMessage =
| { type: "clew-peer-query", version: 1 } // broadcast scan
| { type: "clew-peer-info", version: 1, // heartbeat / response
id: string, hostname: string, ip: string, port: number,
cwd: string, sessionId?: string, appVersion: string,
shell?: string, platform?: string, term?: string,
status: "online" | "offline" }
UDP port: 42069
Multicast IP: 239.255.37.37
Heartbeat: ทุภ30 วินาที
Stale after: 90 วินาที
คำสั่ง
| คำสั่ง | คำà¸à¸˜à¸´à¸šà¸²à¸¢ |
|---|---|
/peer | เปิดเมนู interactive (share, join, discover, inbox) |
/peer share | เริ่มประà¸à¸²à¸¨ instance นี้เป็น worker บน LAN |
/peer stop | หยุดประà¸à¸²à¸¨à¹à¸¥à¸°à¸›à¸´à¸” peer server |
/peer discover | สà¹à¸à¸™à¸«à¸² peers (file + UDP, timeout 3s) |
/peer join <host> <port> | เชื่à¸à¸¡à¸•่à¸à¸à¸±à¸š remote peer ด้วย host à¹à¸¥à¸° port |
/peer name <ชื่à¸> | à¸à¸³à¸«à¸™à¸”ชื่à¸à¸—ี่à¹à¸ªà¸”งสำหรับตัวเà¸à¸‡ |
/peer role <บทบาท> | à¸à¸³à¸«à¸™à¸”บทบาท (builder, tester, deployer, ฯลฯ) |
/peer inbox | ดูข้à¸à¸„วามà¹à¸¥à¸° todos ที่รà¸à¸à¸¢à¸¹à¹ˆà¸ˆà¸²à¸ peers |
/peer disconnect <peer> | ตัดà¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸à¸¡à¸•่à¸à¸ˆà¸²à¸ peer ที่ระบุ |
/peer todos | à¹à¸ªà¸”งรายà¸à¸²à¸£ task ทั้งหมดที่ได้รับ |
/peer todo done <id> | ทำเครื่à¸à¸‡à¸«à¸¡à¸²à¸¢ task ว่าเสร็จà¹à¸¥à¹‰à¸§ |
AI Tools
เครื่à¸à¸‡à¸¡à¸·à¸à¸—ี่ AI agent ใช้เพื่à¸à¹‚ต้ตà¸à¸šà¸à¸±à¸šà¸£à¸°à¸šà¸š peer:
| Tool | คำà¸à¸˜à¸´à¸šà¸²à¸¢ |
|---|---|
peer_discover | สà¹à¸à¸™ LAN หา Clew workers |
peer_join | เชื่à¸à¸¡à¸•่à¸à¸à¸±à¸š remote peer ผ่าน HTTP |
peer_ping | ตรวจสà¸à¸šà¸§à¹ˆà¸² peer à¸à¸à¸™à¹„ลน์à¸à¸¢à¸¹à¹ˆà¸«à¸£à¸·à¸à¹„ม่ (GET /peer-info) |
peer_info | ดึงข้à¸à¸¡à¸¹à¸¥ peer à¸à¸¢à¹ˆà¸²à¸‡à¸¥à¸°à¹€à¸à¸µà¸¢à¸” |
peer_send_message | ส่งข้à¸à¸„วาม chat ไปที่ peer |
peer_send_task | มà¸à¸šà¸«à¸¡à¸²à¸¢ task ให้ remote worker |
peer_broadcast | ส่ง task ไปทุภpeer ที่เชื่à¸à¸¡à¸•่à¸à¸žà¸£à¹‰à¸à¸¡à¸à¸±à¸™ |
peer_run | รันคำสั่ง shell บน remote worker |
peer_disconnect | ลบ peer à¸à¸à¸à¸ˆà¸²à¸à¸£à¸²à¸¢à¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸à¸¡à¸•่ภ|
peer_list_messages | à¹à¸ªà¸”งข้à¸à¸„วาม chat ทั้งหมดที่ได้รับ |
peer_list_roles | à¹à¸ªà¸”งรายà¸à¸²à¸£ peers พร้à¸à¸¡à¸šà¸—บาท |
peer_list_tasks | à¹à¸ªà¸”ง task ทั้งหมดà¹à¸¥à¸°à¸ªà¸–านะ |
peer_set_name | à¸à¸³à¸«à¸™à¸”ชื่à¸à¸—ี่à¹à¸ªà¸”งให้ peer |
peer_set_role | à¸à¸³à¸«à¸™à¸”บทบาทให้ peer |
peer_share | เปิด/ปิด/เช็คสถานะà¸à¸²à¸£à¹à¸Šà¸£à¹Œ |
à¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸à¸¡à¸•่à¸à¸à¸±à¸š DAEMON
Autonomous agent loop (src/services/autonomous/agentLoop.ts) เชื่à¸à¸¡à¸•่à¸à¸à¸±à¸š PeerServer เพื่à¸à¸£à¸±à¸š task จาภremote peers:
- ฟัง
/peer-todoPOST ตลà¸à¸” 24/7 - จัดคิว task ที่ได้รับà¹à¸¥à¸°à¸›à¸£à¸°à¸¡à¸§à¸¥à¸œà¸¥à¹ƒà¸™ background workers
- สูงสุด 3 workers พร้à¸à¸¡à¸à¸±à¸™; task timeout หลัง 30 นาที
- ดูผลลัพธ์ผ่าน
/peer todosà¹à¸¥à¸°/tasks
ไฟล์ในระบบ
| ไฟล์ | หน้าที่ |
|---|---|
src/peer/PeerServer.ts | HTTP server พร้à¸à¸¡ endpoint /peer-info, /peer-msg, /peer-todo, /peer-exec |
src/peer/PeerDiscovery.ts | ค้นหา peer ผ่านไฟล์ + UDP multicast บน LAN |
src/peer/PeerStore.ts | Singleton registry ใน memory (peers, messages, todos, tags) |
src/peer/types.ts | Shared types à¹à¸¥à¸°à¸„่าคงที่ขà¸à¸‡ protocol |
src/commands/peer/ | Interactive peer menu à¹à¸¥à¸° CLI commands |
src/tools/Peer*Tool/ | 16 AI agent tools สำหรับ peer operations |
src/services/autonomous/agentLoop.ts | Daemon integration: รับ remote tasks ผ่าน PeerServer |