Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 51 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,55 @@ const stats = await getGhCacheStats();
- Short args: `gh.repos.get({"owner":"octocat","repo":"Hello-World"})#b3117af2`
- Long args: `gh.repos.get({"owner":"octocat","descripti...bbbbbbbbbb"})#4240f076`

## ComfyPR Bot Skills

### Overview

The ComfyPR Bot (defined in `bot/index.ts`) is a Slack-integrated AI assistant that helps with research, documentation, and code investigation tasks. When spawned, the bot agent has access to several specialized skills.

### Available Skills

The bot agent prompt (lines 390-396 in `bot/index.ts`) includes the following skills:

1. **Web Search**
- Search the web for relevant information
- Gather up-to-date information and context

2. **GitHub Repository Access**
- Clone any repositories from https://github.com/Comfy-Org
- Inspect codebases at `./codes/Comfy-Org/[repo]/tree/[branch]`
- Read and analyze source code

3. **Slack Integration**
- **Update messages**: `bun ../bot/slack/msg-update.ts --channel ${event.channel} --ts ${quickRespondMsg.ts} --text "<response>"`
- **Read threads**: `bun ../bot/slack/msg-read-thread.ts --channel ${event.channel} --ts [ts]`
- Update responses frequently to provide live progress updates

4. **Notion Documentation Search**
- Search Notion docs from Comfy-Org team: `./bot/notion-search.ts`
- Access internal documentation and knowledge base

### Context Repositories

The bot has knowledge of these Comfy-Org repositories:

- **comfyanonymous/ComfyUI**: Main ComfyUI repository (Python ML backend)
- **Comfy-Org/ComfyUI_frontend**: Frontend codebase (Vue + TypeScript)
- **Comfy-Org/docs**: Documentation, setup guides, tutorials, API references
- **Comfy-Org/desktop**: Desktop application
- **Comfy-Org/registry**: registry.comfy.org for custom-nodes and extensions
- **Comfy-Org/workflow_templates**: Official shared workflow templates

### Usage

The bot is automatically spawned when:

1. A user mentions the bot in a Slack channel
2. The message is in an authorized channel (`#comfypr-bot` or `#pr-bot`)
3. The bot determines that agent assistance is needed

See `bot/README.md` for documentation on the individual skill scripts.

## SFlow Stream Processing Library

### Overview
Expand All @@ -111,7 +160,7 @@ SFlow is a powerful functional stream processing library used throughout the cod

### Implementation Details

- **Package**: `sflow@1.24.0`
- **Package**: `sflow@1.24.0`
- **Author**: snomiao
- **License**: MIT
- **Core Concepts**: SFlow is built around composable stream operators, lazy evaluation, and support for both synchronous and asynchronous data flows.
- **Core Concepts**: SFlow is built around composable stream operators, lazy evaluation, and support for both synchronous and asynchronous data flows.
178 changes: 178 additions & 0 deletions bot/BUGFIX.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
# Bug Fixes: Slack WebSocket Message Handling

## Problem 1: App Mention Event Schema Mismatch

The bot was not processing some `app_mention` events from Slack, logging them as `MSG_NOT_MATCHED` in `bot/msg.log`.

## Problem 2: System Messages Not Handled

The bot was logging Slack WebSocket system messages (like "hello" and "disconnect") as `MSG_NOT_MATCHED`, even though they are normal protocol messages.

## Root Cause

The Zod schema for `app_mention` events in `bot/index.ts` had two issues:

1. **`client_msg_id` was required** - But Slack doesn't always include this field (especially for retry attempts or certain message types)
2. **`attachments` field was missing** - Events with attachments (like message unfurls) were being rejected

## Event Analysis

From `bot/msg.log`, the actual event structure was:

```typescript
{
type: 'app_mention',
user: 'U04F3GHTG2X',
ts: '1766560478.446979',
// ❌ client_msg_id: MISSING!
text: '<@U078499LK5K> do some research...',
team: 'T0462DJ9G3C',
blocks: [...],
channel: 'C0A51KF8SMU',
assistant_thread: {...},
attachments: [...], // ❌ Not in schema!
event_ts: '1766560478.446979'
}
```

## Solution

Updated the Zod schema and TypeScript interface in `bot/index.ts`:

### Before (lines 35-48)

```typescript
const zAppMentionEvent = z.object({
type: z.literal("app_mention"),
user: z.string(),
ts: z.string(),
client_msg_id: z.string(), // ❌ Required
text: z.string(),
team: z.string(),
thread_ts: z.string().optional(),
parent_user_id: z.string().optional(),
blocks: z.array(z.any()),
channel: z.string(),
assistant_thread: z.any().optional(),
// ❌ attachments missing
event_ts: z.string(),
});
```

### After (lines 35-49)

```typescript
const zAppMentionEvent = z.object({
type: z.literal("app_mention"),
user: z.string(),
ts: z.string(),
client_msg_id: z.string().optional(), // ✅ Optional
text: z.string(),
team: z.string(),
thread_ts: z.string().optional(),
parent_user_id: z.string().optional(),
blocks: z.array(z.any()),
channel: z.string(),
assistant_thread: z.any().optional(),
attachments: z.array(z.any()).optional(), // ✅ Added
event_ts: z.string(),
});
```

Also updated the TypeScript interface for `processSlackAppMentionEvent` (lines 83-97) to match.

## Verification

Created test script `/tmp/test_schema.ts` that successfully validates the previously failing event against the updated schema:

```bash
$ bun /tmp/test_schema.ts
✅ SUCCESS! Event matches the schema.
```

---

## Fix 2: Handle Slack WebSocket System Messages

### Problem

The bot was logging normal Slack WebSocket protocol messages as unmatched:

```json
{
"type": "hello",
"num_connections": 1,
"debug_info": {
"host": "applink-6",
"build_number": 8,
"approximate_connection_time": 18060
},
"connection_info": {
"app_id": "A078498JA5T"
}
}
```

The "hello" message is sent by Slack to acknowledge a successful WebSocket connection.

### Root Cause

The WebSocket message handler only tried to parse `app_mention` events and logged everything else as unmatched.

### Solution

Added proper handling for different Slack WebSocket message types in `bot/index.ts` (lines 65-105):

```typescript
ws.onmessage = async ({ data }) => {
const parsed = JSON.parse(data)
let handled = false;

// 1. Handle "hello" message (connection acknowledgment)
if (parsed.type === 'hello') {
console.log('[Slack WebSocket] Connection acknowledged:', {...});
handled = true;
}

// 2. Handle "disconnect" message
if (parsed.type === 'disconnect') {
console.log('[Slack WebSocket] Disconnect message:', parsed.reason);
handled = true;
}

// 3. Handle "events_api" messages with app_mention events
if (parsed.type === 'events_api' && parsed.payload?.event) {
// Parse and process app_mention events
handled = await zAppMentionEvent.parseAsync(...)...
}

// Log only truly unhandled messages
if (!handled) {
console.log('MSG_NOT_MATCHED: ' + JSON.stringify(data));
}
}
```

### Verification

Created test script `/tmp/test_hello_msg.ts`:

```bash
$ bun /tmp/test_hello_msg.ts
[Slack WebSocket] Connection acknowledged: { connections: 1, host: "applink-6" }
Result: ✅ Handled
```

## Files Modified

- `bot/index.ts`:
- Lines 35-49: Updated Zod schema for app_mention events
- Lines 65-105: Added WebSocket message type handlers
- Lines 117-126: Updated TypeScript interface

## References

- Slack Events API: https://api.slack.com/events/app_mention
- Slack WebSocket API: https://api.slack.com/apis/connections/socket
- The `client_msg_id` field is documented as optional for app_mention events
- Events with message unfurls include an `attachments` array
25 changes: 25 additions & 0 deletions bot/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
FROM pytorch/pytorch:latest

# requirements
RUN apt-get update -y && apt-get install -y git && pip install comfy-cli
RUN apt install curl -y

WORKDIR /ComfyUI

# install ComfyUI + Manager
RUN git clone https://github.com/comfyanonymous/ComfyUI /ComfyUI && \
pip install -r requirements.txt && \
cd custom_nodes && \
git clone https://github.com/Comfy-Org/ComfyUI-Manager && \
cd ComfyUI-Manager && \
pip install -r requirements.txt

# setup entrypoint script, which runs python main.py
COPY entry.sh /bin/comfyui
RUN chmod +x /bin/comfyui
ENTRYPOINT ["comfyui"]

# default command to run ComfyUI with CPU support and latest frontend version
# CMD ["--cpu", "--listen", "0.0.0.0", "--front-end-version", "Comfy-Org/ComfyUI_frontend@latest"]

EXPOSE 8188
31 changes: 31 additions & 0 deletions bot/IdleWaiter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* A utility class to wait for idle periods based on activity pings.
*
* @example
* const idleWaiter = new IdleWaiter();
*
* // Somewhere in your code, when activity occurs:
* idleWaiter.ping();
*
* // To wait for an idle period of 5 seconds:
* await idleWaiter.wait(5000);
* console.log('System has been idle for 5 seconds');
*/
export class IdleWaiter {
lastActivityTime = Date.now();
checkInterval = 100; // Default check interval in milliseconds

constructor() {
this.ping();
}

ping() {
this.lastActivityTime = Date.now();
return this;
}

async wait(ms: number) {
while (this.lastActivityTime >= Date.now() - ms)
await new Promise((resolve) => setTimeout(resolve, this.checkInterval));
}
}
Loading