ระบบ 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 รองรับการโต้ตอบแบบต่างๆ:

EndpointMethodหน้าที่
/peer-infoGETส่งข้อมูล peer (hostname, IP, cwd, shell, platform)
/peer-msgPOSTรับข้อความ chat จาก peer อื่น
/peer-todoPOSTรับ task ที่ถูกมอบหมายจาก peer อื่น
/peer-execPOSTรันคำสั่ง 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-todo POST ตลอด 24/7
  • จัดคิว task ที่ได้รับและประมวลผลใน background workers
  • สูงสุด 3 workers พร้อมกัน; task timeout หลัง 30 นาที
  • ดูผลลัพธ์ผ่าน /peer todos และ /tasks

ไฟล์ในระบบ

ไฟล์หน้าที่
src/peer/PeerServer.tsHTTP server พร้อม endpoint /peer-info, /peer-msg, /peer-todo, /peer-exec
src/peer/PeerDiscovery.tsค้นหา peer ผ่านไฟล์ + UDP multicast บน LAN
src/peer/PeerStore.tsSingleton registry ใน memory (peers, messages, todos, tags)
src/peer/types.tsShared types และค่าคงที่ของ protocol
src/commands/peer/Interactive peer menu และ CLI commands
src/tools/Peer*Tool/16 AI agent tools สำหรับ peer operations
src/services/autonomous/agentLoop.tsDaemon integration: รับ remote tasks ผ่าน PeerServer