Presence
OpenClaw "presence"는 다음의 가벼운 best‑effort 뷰입니다:
- Gateway 자체, 그리고
- Gateway에 연결된 클라이언트 (mac app, WebChat, CLI 등)
Presence는 주로 macOS 앱의 Instances 탭을 렌더링하고 운영자에게 빠른 가시성을 제공하는 데 사용됩니다.
Presence 필드 (표시되는 내용)
Presence 항목은 다음과 같은 필드를 가진 구조화된 객체입니다:
- instanceId (선택사항이지만 강력히 권장): 안정적인 클라이언트 identity (일반적으로 connect.client.instanceId)
- host: 사람이 읽기 쉬운 호스트 이름
- ip: best‑effort IP 주소
- version: 클라이언트 버전 문자열
- deviceFamily / modelIdentifier: 하드웨어 힌트
- mode: ui, webchat, cli, backend, probe, test, node, ...
- lastInputSeconds: "마지막 사용자 입력 이후 초" (알려진 경우)
- reason: self, connect, node-connected, periodic, ...
- ts: 마지막 업데이트 타임스탬프 (epoch 이후 ms)
Producer (presence의 출처)
Presence 항목은 여러 소스에서 생성되고 병합됩니다.
1) Gateway self 항목
Gateway는 항상 시작 시 "self" 항목을 생성하므로 클라이언트가 연결되기 전에도 UI에 gateway 호스트가 표시됩니다.
2) WebSocket 연결
모든 WS 클라이언트는 connect 요청으로 시작합니다. 핸드셰이크가 성공하면 Gateway는 해당 연결에 대한 presence 항목을 upsert합니다.
일회성 CLI 명령어가 표시되지 않는 이유
CLI는 종종 짧은 일회성 명령을 위해 연결됩니다. Instances 목록을 스팸하지 않도록 client.mode === "cli"는 presence 항목으로 전환되지 않습니다.
3) system-event beacon
클라이언트는 system-event 메소드를 통해 더 풍부한 주기적 beacon을 보낼 수 있습니다. mac 앱은 이를 사용하여 호스트 이름, IP 및 lastInputSeconds를 보고합니다.
4) Node 연결 (role: node)
Node가 role: node로 Gateway WebSocket을 통해 연결되면 Gateway는 해당 node에 대한 presence 항목을 upsert합니다(다른 WS 클라이언트와 동일한 플로우).
병합 + 중복 제거 규칙 (instanceId가 중요한 이유)
Presence 항목은 단일 인메모리 맵에 저장됩니다:
- 항목은 presence 키로 키가 지정됩니다.
- 최선의 키는 재시작 후에도 유지되는 안정적인 instanceId(connect.client.instanceId에서)입니다.
- 키는 대소문자를 구분하지 않습니다.
클라이언트가 안정적인 instanceId 없이 재연결하면 중복 행으로 표시될 수 있습니다.
TTL 및 제한된 크기
Presence는 의도적으로 임시적입니다:
- TTL: 5분보다 오래된 항목은 제거됩니다
- 최대 항목: 200 (가장 오래된 것부터 삭제)
이는 목록을 신선하게 유지하고 무제한 메모리 증가를 방지합니다.
원격/터널 주의사항 (loopback IP)
클라이언트가 SSH 터널 / 로컬 포트 포워드를 통해 연결하면 Gateway는 원격 주소를 127.0.0.1로 볼 수 있습니다. 좋은 클라이언트 보고 IP를 덮어쓰지 않도록 loopback 원격 주소는 무시됩니다.
Consumer
macOS Instances 탭
macOS 앱은 system-presence의 출력을 렌더링하고 마지막 업데이트의 age를 기반으로 작은 상태 표시기(Active/Idle/Stale)를 적용합니다.
디버깅 팁
- 원시 목록을 보려면 Gateway에 대해 system-presence를 호출하세요.
- 중복이 표시되는 경우:
- 클라이언트가 핸드셰이크에서 안정적인 client.instanceId를 보내는지 확인
- 주기적 beacon이 동일한 instanceId를 사용하는지 확인
- 연결 파생 항목에 instanceId가 누락되어 있는지 확인(중복이 예상됨)