# Kosmi WebSocket Protocol Findings

## Key Discoveries from Browser Monitoring

### Room ID Format
- Browser uses `"@hyperspaceout"` (WITH @ symbol) for all operations
- Our script was using `"hyperspaceout"` (WITHOUT @) - this is why `joinRoom` failed with `ROOM_NOT_FOUND`

### Page Load Sequence
The browser does NOT call `joinRoom` mutation. Instead, it:

1. **Connects to WebSocket** at `wss://engine.kosmi.io/gql-ws`
2. **Sends `connection_init`** with auth token
3. **Immediately starts subscribing** to various topics:
   - `OnNewMessage(roomId: "@hyperspaceout")` - for chat messages
   - `OnLinkedMembers(roomId: "@hyperspaceout")` - for room members
   - `OnMediaPlayerUpdateState(roomId: "@hyperspaceout")` - for media player
   - `OnMediaPlayerUpdateSubtitles(roomId: "@hyperspaceout")` - for subtitles
   - `OnMediasoupUpdate(roomId: "@hyperspaceout")` - for WebRTC
   - `OnRoomUpdate(roomId: "@hyperspaceout")` - for room state
   - `OnMessageReadersUpdate(roomId: "@hyperspaceout")` - for read receipts

### Sending Messages
To send a message, the browser likely uses:
```graphql
mutation SendMessage($body: String!, $roomId: String!) {
  sendMessage(body: $body, roomId: $roomId) {
    ok
  }
}
```

With variables:
```json
{
  "body": "message text",
  "roomId": "@hyperspaceout"
}
```

### Authentication
The `connection_init` payload includes:
- `token`: JWT from `anonLogin` mutation
- `ua`: Base64-encoded User-Agent
- `v`: App version "4364"
- `r`: Empty string for anonymous users

## Next Steps

1. ✅ Use `"@hyperspaceout"` (with @) instead of `"hyperspaceout"`
2. ✅ Skip the `joinRoom` mutation entirely
3. ✅ Just send the `sendMessage` mutation directly after `connection_ack`
4. Test if the message appears in chat

## Important Note

The `sendMessage` mutation returns `{ ok: true }` even when the message doesn't appear in chat. This suggests that:
- The mutation succeeds on the server side
- But the message might be filtered or not broadcast
- Possibly because we're not "subscribed" to the room's message feed
- Or because anonymous users have restrictions

We should subscribe to `OnNewMessage` to see if our sent messages come back through the subscription.

