Skip to content
Open
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
5 changes: 5 additions & 0 deletions .changeset/add-linq-adapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@chat-adapter/linq": minor
---

Add Linq adapter for iMessage, SMS, and RCS messaging via the Linq Partner API
73 changes: 37 additions & 36 deletions apps/docs/content/docs/adapters/index.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Overview
description: Platform-specific adapters for Slack, Teams, Google Chat, Discord, Telegram, GitHub, and Linear.
description: Platform-specific adapters for Slack, Teams, Google Chat, Discord, Telegram, GitHub, Linear, and Linq.
type: overview
prerequisites:
- /docs/getting-started
Expand All @@ -12,50 +12,50 @@ Adapters handle webhook verification, message parsing, and API calls for each pl

### Messaging

| Feature | [Slack](/docs/adapters/slack) | [Teams](/docs/adapters/teams) | [Google Chat](/docs/adapters/gchat) | [Discord](/docs/adapters/discord) | [Telegram](/docs/adapters/telegram) | [GitHub](/docs/adapters/github) | [Linear](/docs/adapters/linear) |
|---------|-------|-------|-------------|---------|---------|--------|--------|
| Post message | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Edit message | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Delete message | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| File uploads | ✅ | ✅ | ❌ | ✅ | ⚠️ Single file | ❌ | ❌ |
| Streaming | ✅ Native | ⚠️ Post+Edit | ⚠️ Post+Edit | ⚠️ Post+Edit | ⚠️ Post+Edit | ❌ | ❌ |
| Feature | [Slack](/docs/adapters/slack) | [Teams](/docs/adapters/teams) | [Google Chat](/docs/adapters/gchat) | [Discord](/docs/adapters/discord) | [Telegram](/docs/adapters/telegram) | [GitHub](/docs/adapters/github) | [Linear](/docs/adapters/linear) | [Linq](/docs/adapters/linq) |
|---------|-------|-------|-------------|---------|---------|--------|--------|------|
| Post message | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Edit message | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Delete message | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| File uploads | ✅ | ✅ | ❌ | ✅ | ⚠️ Single file | ❌ | ❌ | ✅ |
| Streaming | ✅ Native | ⚠️ Post+Edit | ⚠️ Post+Edit | ⚠️ Post+Edit | ⚠️ Post+Edit | ❌ | ❌ | ⚠️ Post+Edit |

### Rich content

| Feature | Slack | Teams | Google Chat | Discord | Telegram | GitHub | Linear |
|---------|-------|-------|-------------|---------|----------|--------|--------|
| Card format | Block Kit | Adaptive Cards | Google Chat Cards | Embeds | Markdown + inline keyboard buttons | GFM Markdown | Markdown |
| Buttons | ✅ | ✅ | ✅ | ✅ | ⚠️ Inline keyboard callbacks | ❌ | ❌ |
| Link buttons | ✅ | ✅ | ✅ | ✅ | ⚠️ Inline keyboard URLs | ❌ | ❌ |
| Select menus | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ |
| Tables | ✅ Block Kit | ✅ GFM | ⚠️ ASCII | ✅ GFM | ⚠️ ASCII | ✅ GFM | ✅ GFM |
| Fields | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Images in cards | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ |
| Modals | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Feature | Slack | Teams | Google Chat | Discord | Telegram | GitHub | Linear | Linq |
|---------|-------|-------|-------------|---------|----------|--------|--------|------|
| Card format | Block Kit | Adaptive Cards | Google Chat Cards | Embeds | Markdown + inline keyboard buttons | GFM Markdown | Markdown | Text fallback |
| Buttons | ✅ | ✅ | ✅ | ✅ | ⚠️ Inline keyboard callbacks | ❌ | ❌ | ❌ |
| Link buttons | ✅ | ✅ | ✅ | ✅ | ⚠️ Inline keyboard URLs | ❌ | ❌ | ❌ |
| Select menus | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Tables | ✅ Block Kit | ✅ GFM | ⚠️ ASCII | ✅ GFM | ⚠️ ASCII | ✅ GFM | ✅ GFM | ⚠️ ASCII |
| Fields | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Images in cards | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ |
| Modals | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |

### Conversations

| Feature | Slack | Teams | Google Chat | Discord | Telegram | GitHub | Linear |
|---------|-------|-------|-------------|---------|----------|--------|--------|
| Slash commands | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ |
| Mentions | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Add reactions | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Remove reactions | ✅ | ❌ | ✅ | ✅ | ✅ | ⚠️ | ⚠️ |
| Typing indicator | ❌ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ |
| DMs | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| Ephemeral messages | ✅ Native | ❌ | ✅ Native | ❌ | ❌ | ❌ | ❌ |
| Feature | Slack | Teams | Google Chat | Discord | Telegram | GitHub | Linear | Linq |
|---------|-------|-------|-------------|---------|----------|--------|--------|------|
| Slash commands | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ |
| Mentions | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Add reactions | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Remove reactions | ✅ | ❌ | ✅ | ✅ | ✅ | ⚠️ | ⚠️ | ✅ |
| Typing indicator | ❌ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
| DMs | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ |
| Ephemeral messages | ✅ Native | ❌ | ✅ Native | ❌ | ❌ | ❌ | ❌ | ❌ |

### Message history

| Feature | Slack | Teams | Google Chat | Discord | Telegram | GitHub | Linear |
|---------|-------|-------|-------------|---------|----------|--------|--------|
| Fetch messages | ✅ | ✅ | ✅ | ✅ | ⚠️ Cached | ✅ | ✅ |
| Fetch single message | ✅ | ❌ | ❌ | ❌ | ⚠️ Cached | ❌ | ❌ |
| Fetch thread info | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Fetch channel messages | ✅ | ✅ | ✅ | ✅ | ⚠️ Cached | ✅ | ❌ |
| List threads | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ |
| Fetch channel info | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
| Post channel message | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| Feature | Slack | Teams | Google Chat | Discord | Telegram | GitHub | Linear | Linq |
|---------|-------|-------|-------------|---------|----------|--------|--------|------|
| Fetch messages | ✅ | ✅ | ✅ | ✅ | ⚠️ Cached | ✅ | ✅ | ✅ |
| Fetch single message | ✅ | ❌ | ❌ | ❌ | ⚠️ Cached | ❌ | ❌ | ✅ |
| Fetch thread info | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Fetch channel messages | ✅ | ✅ | ✅ | ✅ | ⚠️ Cached | ✅ | ❌ | ✅ |
| List threads | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ |
| Fetch channel info | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ |
| Post channel message | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ |

<Callout type="info">
⚠️ indicates partial support — the feature works with limitations. See individual adapter pages for details.
Expand All @@ -72,6 +72,7 @@ Adapters handle webhook verification, message parsing, and API calls for each pl
| [Telegram](/docs/adapters/telegram) | `@chat-adapter/telegram` |
| [GitHub](/docs/adapters/github) | `@chat-adapter/github` |
| [Linear](/docs/adapters/linear) | `@chat-adapter/linear` |
| [Linq](/docs/adapters/linq) | `@chat-adapter/linq` |

## Community adapters

Expand Down
116 changes: 116 additions & 0 deletions apps/docs/content/docs/adapters/linq.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
---
title: Linq
description: Configure the Linq adapter for iMessage, SMS, and RCS messaging via the Linq API.
type: integration
prerequisites:
- /docs/getting-started
---

## Installation

```sh title="Terminal"
pnpm add @chat-adapter/linq
```

## Usage

The adapter auto-detects `LINQ_API_TOKEN`, `LINQ_SIGNING_SECRET`, and `LINQ_PHONE_NUMBER` from environment variables:

```typescript title="lib/bot.ts" lineNumbers
import { Chat } from "chat";
import { createLinqAdapter } from "@chat-adapter/linq";

const bot = new Chat({
userName: "mybot",
adapters: {
linq: createLinqAdapter(),
},
});

bot.onNewMention(async (thread, message) => {
await thread.post(`You said: ${message.text}`);
});
```

## Webhook route

```typescript title="app/api/webhooks/linq/route.ts" lineNumbers
import { bot } from "@/lib/bot";

export async function POST(request: Request): Promise<Response> {
return bot.webhooks.linq(request);
}
```

Configure this URL as your webhook endpoint in the Linq partner dashboard.

## Configuration

All options are auto-detected from environment variables when not provided.

| Option | Required | Description |
|--------|----------|-------------|
| `apiToken` | No* | Linq API token. Auto-detected from `LINQ_API_TOKEN` |
| `signingSecret` | No | Webhook signing secret for signature verification. Auto-detected from `LINQ_SIGNING_SECRET` |
| `phoneNumber` | No | Bot phone number, required for `openDM` and `listThreads`. Auto-detected from `LINQ_PHONE_NUMBER` |
| `userName` | No | Bot display name (defaults to `"bot"`) |
| `logger` | No | Logger instance (defaults to `ConsoleLogger("info")`) |

*`apiToken` is required — either via config or `LINQ_API_TOKEN` env var.

## Environment variables

```bash title=".env.local"
LINQ_API_TOKEN=...
LINQ_SIGNING_SECRET=... # Optional, for webhook signature verification
LINQ_PHONE_NUMBER=... # Required for openDM and listThreads
```

## Webhook verification

When `signingSecret` is configured, the adapter verifies incoming webhooks using HMAC-SHA256 signatures. It checks the `x-webhook-signature` and `x-webhook-timestamp` headers and rejects requests with timestamps older than 5 minutes.

## Features

| Feature | Supported |
|---------|-----------|
| Mentions | Yes (all inbound messages treated as mentions) |
| Reactions (add/remove) | Yes |
| Cards | Text fallback |
| Modals | No |
| Slash commands | No |
| Streaming | Post+Edit fallback |
| DMs | Yes |
| Ephemeral messages | No |
| File uploads | Yes |
| Typing indicator | Yes |
| Message history | Yes |
| Fetch single message | Yes |
| List threads | Yes (requires `phoneNumber`) |

## Reactions

Linq supports a fixed set of reaction types that map to standard emoji names:

| Linq reaction | Emoji name |
|---------------|------------|
| `love` | `heart` |
| `like` | `thumbsup` |
| `dislike` | `thumbsdown` |
| `laugh` | `laughing` |
| `emphasize` | `exclamation` |
| `question` | `question` |

Reactions not in this list are sent as custom emoji.

## Thread ID format

Linq thread IDs follow the pattern `linq:{chatId}`.

## Notes

- Linq is an SMS/iMessage/RCS gateway — messages are plain text. Markdown formatting (bold, italic, links) is stripped to plain text automatically.
- Tables render as ASCII art in code blocks.
- All inbound messages are treated as mentions since Linq chats are direct conversations.
- `openDM` and `listThreads` require the `phoneNumber` config option.
- The adapter uses the Linq Partner API v3.
3 changes: 2 additions & 1 deletion apps/docs/content/docs/adapters/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"discord",
"telegram",
"github",
"linear"
"linear",
"linq"
]
}
1 change: 1 addition & 0 deletions examples/nextjs-chat/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@chat-adapter/gchat": "workspace:*",
"@chat-adapter/github": "workspace:*",
"@chat-adapter/linear": "workspace:*",
"@chat-adapter/linq": "workspace:*",
"@chat-adapter/slack": "workspace:*",
"@chat-adapter/state-memory": "workspace:*",
"@chat-adapter/state-redis": "workspace:*",
Expand Down
23 changes: 23 additions & 0 deletions examples/nextjs-chat/src/lib/adapters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from "@chat-adapter/gchat";
import { createGitHubAdapter, type GitHubAdapter } from "@chat-adapter/github";
import { createLinearAdapter, type LinearAdapter } from "@chat-adapter/linear";
import { createLinqAdapter, type LinqAdapter } from "@chat-adapter/linq";
import { createSlackAdapter, type SlackAdapter } from "@chat-adapter/slack";
import { createTeamsAdapter, type TeamsAdapter } from "@chat-adapter/teams";
import {
Expand All @@ -25,6 +26,7 @@ export interface Adapters {
gchat?: GoogleChatAdapter;
github?: GitHubAdapter;
linear?: LinearAdapter;
linq?: LinqAdapter;
slack?: SlackAdapter;
teams?: TeamsAdapter;
telegram?: TelegramAdapter;
Expand Down Expand Up @@ -86,6 +88,15 @@ const LINEAR_METHODS = [
"addReaction",
"fetchMessages",
];
const LINQ_METHODS = [
"postMessage",
"editMessage",
"deleteMessage",
"addReaction",
"removeReaction",
"startTyping",
"fetchMessages",
];
const TELEGRAM_METHODS = [
"postMessage",
"editMessage",
Expand Down Expand Up @@ -204,6 +215,18 @@ export function buildAdapters(): Adapters {
}
}

// Linq adapter (optional) - env vars: LINQ_API_TOKEN, LINQ_SIGNING_SECRET, LINQ_PHONE_NUMBER
if (process.env.LINQ_API_TOKEN) {
adapters.linq = withRecording(
createLinqAdapter({
userName: "Chat SDK Bot",
logger: logger.child("linq"),
}),
"linq",
LINQ_METHODS
);
}

// Telegram adapter (optional) - env vars: TELEGRAM_BOT_TOKEN
if (process.env.TELEGRAM_BOT_TOKEN) {
adapters.telegram = withRecording(
Expand Down
Loading