Skip to content
Merged
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
48 changes: 42 additions & 6 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,27 @@ When adding/modifying channels:
3. Update onboarding wizard
4. Test with real account when possible

### Channel Adapter Structure

Each adapter has three files:

```
packages/channels/src/adapters/<channel>/
├── config.ts # Configuration types and defaults
├── adapter.ts # ChannelAdapter implementation
└── index.ts # Exports
```

### Implemented Adapters

| Channel | Library | Notes |
|---------|---------|-------|
| Telegram | grammY | Bot API, polling/webhook |
| Discord | discord.js | Gateway + REST API |
| WhatsApp | @whiskeysockets/baileys | QR-based auth, session persistence |
| Slack | @slack/bolt | Socket mode or HTTP |
| Signal | signal-cli | External daemon via JSON-RPC/SSE |

### Channel Pattern

```typescript
Expand All @@ -164,6 +185,16 @@ interface ChannelAdapter {
}
```

### Adding a New Channel

1. Create adapter directory with config.ts, adapter.ts, index.ts
2. Implement `ChannelAdapter` interface
3. Add pairing flow for DM security
4. Handle message chunking for platform limits
5. Export from `packages/channels/src/index.ts`
6. Add subpath export in package.json
7. Add documentation in `docs/channels/`

## Tool Development

Tools are exposed to Claude Agent SDK:
Expand Down Expand Up @@ -287,7 +318,7 @@ Finna is inspired by Clawdbot (MIT licensed). When implementing features:

### Clawdbot Reference Commit

**Current**: `b9098f34` (2025-01-26)
**Current**: `d34ae861` (2025-01-27)

When referencing Clawdbot code or patterns, always include the commit hash to track which version was analyzed. Update this when pulling new changes.

Expand Down Expand Up @@ -401,13 +432,18 @@ finna config set ... # Update value

## Reference Projects

- **Clawdbot** (`../clawdbot/`) at `b9098f34` - MIT licensed, primary reference
- **BB8** (`../bb8-assistant/`) - Task management patterns
- **Clawdbot** - MIT licensed, primary reference (see private CLAUDE.md for path)
- **Claude Agent SDK** - https://platform.claude.com/docs/en/agent-sdk/overview

## Current Status

**Phase**: Phase 1 - Foundation
**Phase**: Phase 1 - MVP (Milestone 1 in progress)

Completed specs:
- 002-gateway: WebSocket server, protocol, auth
- 003-channels: Telegram, Discord, WhatsApp, Slack, Signal adapters
- 004-tools-skills: Tool system, Claude SDK integration

Next: 008-cli (Basic commands) to complete Milestone 1

See `docs/architecture-analysis.md` for tech stack decisions.
See `tasks/001-clawdbot-analysis.md` for initial analysis.
See `specs/ROADMAP.md` for full status.
131 changes: 131 additions & 0 deletions docs/channels/discord.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
---
title: Discord
description: Connect Finna to Discord servers
---

# Discord

Status: **Stable** - Discord.js with full gateway support.

## Quick Setup

1. Create a Discord Application at [discord.com/developers](https://discord.com/developers/applications)
2. Go to Bot section and create a bot
3. Copy the bot token
4. Enable required intents (Message Content, Server Members)
5. Add bot to your server with appropriate permissions
6. Add to your Finna config:

```json
{
"channels": {
"discord": {
"enabled": true,
"botToken": "MTIz...",
"dmPolicy": "pairing",
"guilds": {
"YOUR_SERVER_ID": {
"enabled": true
}
}
}
}
}
```

## Configuration

```typescript
interface DiscordConfig {
botToken: string; // Required: Bot token
dmPolicy: DMPolicy; // 'pairing' | 'allowlist' | 'open' | 'disabled'
groupPolicy: GroupPolicy; // 'allowlist' | 'open' | 'disabled'
allowlist: string[]; // User IDs to auto-approve
allowBots?: boolean; // Process messages from other bots
textChunkLimit?: number; // Max chars per message (default: 2000)
guilds?: Record<string, GuildConfig>;
}

interface GuildConfig {
enabled: boolean;
channels?: Record<string, {
allow?: boolean;
requireMention?: boolean;
users?: string[];
}>;
}
```

## Features

| Feature | Supported |
|---------|-----------|
| DMs | Yes |
| Group DMs | Yes |
| Server channels | Yes |
| Threads | Yes |
| Reactions | Yes |
| Edit messages | Yes |
| Delete messages | Yes |
| Media | Yes |
| Slash commands | Planned |

## Required Intents

Enable these in the Discord Developer Portal:

- **Guilds** - Access server information
- **Guild Messages** - Receive messages in channels
- **Direct Messages** - Receive DMs
- **Message Content** - Read message text (privileged intent)

## Guild Configuration

Control which servers and channels the bot responds in:

```json
{
"guilds": {
"123456789": {
"enabled": true,
"channels": {
"987654321": {
"allow": true,
"requireMention": true
}
}
},
"*": {
"enabled": false
}
}
}
```

- Use `"*"` as wildcard for default behavior
- `requireMention: true` makes bot respond only when @mentioned

## Pairing Flow

Same as Telegram - users in DMs receive a pairing code to share with an admin for approval.

## Message Limits

Discord has a 2000 character limit per message. Long responses are automatically chunked:

- Splits at newlines when possible
- Falls back to spaces
- Never splits mid-word

## Troubleshooting

### Bot doesn't respond in servers

- Check guild is in `guilds` config with `enabled: true`
- Verify bot has "View Channel" and "Send Messages" permissions
- Check "Message Content Intent" is enabled

### Missing messages

- Enable "Message Content Intent" in Developer Portal
- This is a privileged intent required for reading message text
69 changes: 69 additions & 0 deletions docs/channels/overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
title: Chat Channels
description: Connect Finna to messaging platforms
---

# Chat Channels

Finna can connect to any chat platform you use. Each channel adapter handles platform-specific authentication, message formatting, and delivery.

## Supported Channels

| Channel | Status | Auth Method | Features |
|---------|--------|-------------|----------|
| [Telegram](/channels/telegram) | Stable | Bot Token | Groups, threads, media, reactions |
| [Discord](/channels/discord) | Stable | Bot Token | Servers, channels, DMs, threads |
| [WhatsApp](/channels/whatsapp) | Stable | QR Pairing | DMs, groups, media |
| [Slack](/channels/slack) | Stable | Bot Token | Workspaces, channels, DMs, threads |
| [Signal](/channels/signal) | Stable | signal-cli | Privacy-focused DMs and groups |

## Quick Start

The fastest way to get started is with **Telegram** - just create a bot token via BotFather and add it to your config:

```json
{
"channels": {
"telegram": {
"enabled": true,
"botToken": "123456:ABC-DEF...",
"dmPolicy": "pairing"
}
}
}
```

## Security Model

All channels support a security model with DM policies and allowlists:

- **pairing** (default): Unknown senders receive a pairing code to share with an admin
- **allowlist**: Only pre-approved senders can interact
- **open**: Anyone can send messages (use with caution)
- **disabled**: Channel ignores DMs entirely

Group policies work similarly but for group/channel contexts.

## Running Multiple Channels

Channels can run simultaneously. Finna routes messages to the correct channel based on where they originated:

```json
{
"channels": {
"telegram": { "enabled": true, "botToken": "..." },
"discord": { "enabled": true, "botToken": "..." },
"slack": { "enabled": true, "botToken": "..." }
}
}
```

## Session Routing

Each conversation gets a unique session key based on:
- Channel ID (telegram, discord, etc.)
- Chat type (dm, group, channel, thread)
- Chat ID (user ID, group ID, etc.)
- Thread ID (if applicable)

This ensures conversation context is preserved per-chat.
Loading
Loading