Move troubleshooting and implementation docs to docs/
Relocate 30 non-essential .md files (investigation notes, fix summaries, implementation details, status reports) from the project root into docs/ to reduce clutter. Core operational docs (README, quickstart guides, configuration references) remain in the root. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
283
docs/TYPING_INDICATORS.md
Normal file
283
docs/TYPING_INDICATORS.md
Normal file
@@ -0,0 +1,283 @@
|
||||
# Typing Indicators Investigation
|
||||
|
||||
## Overview
|
||||
|
||||
This document outlines how to investigate and implement typing indicators for the Kosmi bridge. Typing indicators show when users are actively typing messages.
|
||||
|
||||
## Monitoring Approach
|
||||
|
||||
### Using the Auth Monitoring Script
|
||||
|
||||
The `cmd/monitor-auth/main.go` script already captures all WebSocket traffic. To investigate typing indicators:
|
||||
|
||||
```bash
|
||||
# Run the monitoring script
|
||||
./bin/monitor-auth -room "https://app.kosmi.io/room/@hyperspaceout"
|
||||
|
||||
# In the Kosmi room, start typing (but don't send)
|
||||
# Watch the console output for WebSocket messages
|
||||
```
|
||||
|
||||
### What to Look For
|
||||
|
||||
Typing indicators are typically implemented as:
|
||||
|
||||
1. **GraphQL Subscription** (receiving typing events):
|
||||
```graphql
|
||||
subscription {
|
||||
userTyping(roomId: "...") {
|
||||
user {
|
||||
id
|
||||
displayName
|
||||
}
|
||||
isTyping
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. **GraphQL Mutation** (sending typing status):
|
||||
```graphql
|
||||
mutation {
|
||||
setTyping(roomId: "...", isTyping: true)
|
||||
}
|
||||
```
|
||||
|
||||
3. **WebSocket Message Format**:
|
||||
- Look for messages with type `"next"` or `"data"`
|
||||
- Payload might contain `userTyping`, `typing`, `isTyping`, or similar fields
|
||||
- Usually sent when user starts/stops typing
|
||||
|
||||
### Expected Message Patterns
|
||||
|
||||
**When user starts typing:**
|
||||
```json
|
||||
{
|
||||
"type": "next",
|
||||
"id": "typing-subscription",
|
||||
"payload": {
|
||||
"data": {
|
||||
"userTyping": {
|
||||
"user": {
|
||||
"id": "user-123",
|
||||
"displayName": "Alice"
|
||||
},
|
||||
"isTyping": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**When user stops typing:**
|
||||
```json
|
||||
{
|
||||
"type": "next",
|
||||
"id": "typing-subscription",
|
||||
"payload": {
|
||||
"data": {
|
||||
"userTyping": {
|
||||
"user": {
|
||||
"id": "user-123",
|
||||
"displayName": "Alice"
|
||||
},
|
||||
"isTyping": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
Once typing indicators are discovered:
|
||||
|
||||
### 1. Add Subscription to GraphQL Client
|
||||
|
||||
In `bridge/kosmi/graphql_ws_client.go`, add a typing subscription:
|
||||
|
||||
```go
|
||||
func (c *GraphQLWSClient) subscribeToTyping() error {
|
||||
typingMsg := WSMessage{
|
||||
ID: "subscribe-typing",
|
||||
Type: messageTypeSubscribe,
|
||||
Payload: map[string]interface{}{
|
||||
"query": `subscription OnUserTyping($roomId: String!) {
|
||||
userTyping(roomId: $roomId) {
|
||||
user {
|
||||
id
|
||||
displayName
|
||||
username
|
||||
}
|
||||
isTyping
|
||||
}
|
||||
}`,
|
||||
"variables": map[string]interface{}{
|
||||
"roomId": c.roomID,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return c.conn.WriteJSON(typingMsg)
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Handle Typing Events
|
||||
|
||||
Add a callback for typing events:
|
||||
|
||||
```go
|
||||
type TypingPayload struct {
|
||||
Data struct {
|
||||
UserTyping struct {
|
||||
User struct {
|
||||
ID string `json:"id"`
|
||||
DisplayName string `json:"displayName"`
|
||||
Username string `json:"username"`
|
||||
} `json:"user"`
|
||||
IsTyping bool `json:"isTyping"`
|
||||
} `json:"userTyping"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
func (c *GraphQLWSClient) OnTyping(callback func(*TypingPayload)) {
|
||||
c.typingCallback = callback
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Send Typing Status
|
||||
|
||||
Add a method to send typing status:
|
||||
|
||||
```go
|
||||
func (c *GraphQLWSClient) SendTyping(isTyping bool) error {
|
||||
msg := WSMessage{
|
||||
ID: fmt.Sprintf("set-typing-%d", time.Now().Unix()),
|
||||
Type: messageTypeSubscribe,
|
||||
Payload: map[string]interface{}{
|
||||
"query": `mutation SetTyping($roomId: String!, $isTyping: Boolean!) {
|
||||
setTyping(roomId: $roomId, isTyping: $isTyping) {
|
||||
ok
|
||||
}
|
||||
}`,
|
||||
"variables": map[string]interface{}{
|
||||
"roomId": c.roomID,
|
||||
"isTyping": isTyping,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return c.conn.WriteJSON(msg)
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Integrate with Matterbridge
|
||||
|
||||
In `bridge/kosmi/kosmi.go`, map typing events to Matterbridge:
|
||||
|
||||
```go
|
||||
func (b *Bkosmi) handleTypingEvent(payload *TypingPayload) {
|
||||
username := payload.Data.UserTyping.User.DisplayName
|
||||
if username == "" {
|
||||
username = payload.Data.UserTyping.User.Username
|
||||
}
|
||||
|
||||
rmsg := config.Message{
|
||||
Username: username,
|
||||
Channel: "main",
|
||||
Account: b.Account,
|
||||
Event: config.EventUserTyping,
|
||||
Protocol: "kosmi",
|
||||
}
|
||||
|
||||
if payload.Data.UserTyping.IsTyping {
|
||||
b.Remote <- rmsg
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Send Typing from IRC
|
||||
|
||||
When IRC users type, send typing indicator to Kosmi:
|
||||
|
||||
```go
|
||||
func (b *Bkosmi) Send(msg config.Message) (string, error) {
|
||||
// Handle typing indicators
|
||||
if msg.Event == config.EventUserTyping {
|
||||
if b.client != nil {
|
||||
b.client.SendTyping(true)
|
||||
// Set a timer to send false after 5 seconds
|
||||
time.AfterFunc(5*time.Second, func() {
|
||||
b.client.SendTyping(false)
|
||||
})
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// ... rest of Send implementation
|
||||
}
|
||||
```
|
||||
|
||||
## Use Cases
|
||||
|
||||
### 1. Show Typing in IRC
|
||||
|
||||
When Kosmi users type, show in IRC:
|
||||
```
|
||||
*** Alice is typing...
|
||||
```
|
||||
|
||||
### 2. Show Typing in Kosmi
|
||||
|
||||
When IRC users type, send typing indicator to Kosmi.
|
||||
|
||||
### 3. Fake Typing During Image Generation
|
||||
|
||||
When generating room code images (which takes ~2-3 seconds), send typing indicator:
|
||||
|
||||
```go
|
||||
func (b *Bkosmi) sendRoomCodeImage(roomCode string) error {
|
||||
// Send typing indicator
|
||||
if b.client != nil {
|
||||
b.client.SendTyping(true)
|
||||
defer b.client.SendTyping(false)
|
||||
}
|
||||
|
||||
// Generate and send image
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
This makes the bot appear more responsive while processing.
|
||||
|
||||
## Testing
|
||||
|
||||
1. **Manual Testing**:
|
||||
- Run monitoring script
|
||||
- Type in Kosmi (don't send)
|
||||
- Observe WebSocket traffic
|
||||
- Document the message format
|
||||
|
||||
2. **Integration Testing**:
|
||||
- Implement typing support
|
||||
- Test bidirectional typing indicators
|
||||
- Verify timing (typing should stop after inactivity)
|
||||
|
||||
3. **Edge Cases**:
|
||||
- Multiple users typing simultaneously
|
||||
- Typing indicator timeout
|
||||
- Connection loss during typing
|
||||
|
||||
## Status
|
||||
|
||||
- ✅ Monitoring script created (`cmd/monitor-auth/main.go`)
|
||||
- ⏳ **TODO**: Run monitoring script and capture typing events
|
||||
- ⏳ **TODO**: Document actual message format
|
||||
- ⏳ **TODO**: Implement typing support (optional)
|
||||
|
||||
## Notes
|
||||
|
||||
- Typing indicators are a "nice to have" feature
|
||||
- Implementation depends on Kosmi actually supporting them
|
||||
- If not supported, this can be skipped
|
||||
- The monitoring script is ready to capture the traffic when needed
|
||||
|
||||
Reference in New Issue
Block a user