v2: add Chat SDK channel adapters and skills for 11 platforms
Thin wrapper adapters + SKILL.md for Slack, Telegram, GitHub, Linear, Google Chat, Teams, WhatsApp Cloud API, Resend, Matrix, Webex, iMessage. All follow the same pattern as discord-v2.ts: readEnvFile → create*Adapter → createChatSdkBridge → registerChannelAdapter. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
20
src/channels/gchat-v2.ts
Normal file
20
src/channels/gchat-v2.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Google Chat channel adapter (v2) — uses Chat SDK bridge.
|
||||
* Self-registers on import.
|
||||
*/
|
||||
import { createGoogleChatAdapter } from '@chat-adapter/gchat';
|
||||
|
||||
import { readEnvFile } from '../env.js';
|
||||
import { createChatSdkBridge } from './chat-sdk-bridge.js';
|
||||
import { registerChannelAdapter } from './channel-registry.js';
|
||||
|
||||
registerChannelAdapter('gchat', {
|
||||
factory: () => {
|
||||
const env = readEnvFile(['GCHAT_CREDENTIALS']);
|
||||
if (!env.GCHAT_CREDENTIALS) return null;
|
||||
const gchatAdapter = createGoogleChatAdapter({
|
||||
credentials: JSON.parse(env.GCHAT_CREDENTIALS),
|
||||
});
|
||||
return createChatSdkBridge({ adapter: gchatAdapter, concurrency: 'concurrent' });
|
||||
},
|
||||
});
|
||||
22
src/channels/github-v2.ts
Normal file
22
src/channels/github-v2.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* GitHub channel adapter (v2) — uses Chat SDK bridge.
|
||||
* PR comment threads as conversations.
|
||||
* Self-registers on import.
|
||||
*/
|
||||
import { createGitHubAdapter } from '@chat-adapter/github';
|
||||
|
||||
import { readEnvFile } from '../env.js';
|
||||
import { createChatSdkBridge } from './chat-sdk-bridge.js';
|
||||
import { registerChannelAdapter } from './channel-registry.js';
|
||||
|
||||
registerChannelAdapter('github', {
|
||||
factory: () => {
|
||||
const env = readEnvFile(['GITHUB_TOKEN', 'GITHUB_WEBHOOK_SECRET']);
|
||||
if (!env.GITHUB_TOKEN) return null;
|
||||
const githubAdapter = createGitHubAdapter({
|
||||
token: env.GITHUB_TOKEN,
|
||||
webhookSecret: env.GITHUB_WEBHOOK_SECRET,
|
||||
});
|
||||
return createChatSdkBridge({ adapter: githubAdapter, concurrency: 'queue' });
|
||||
},
|
||||
});
|
||||
25
src/channels/imessage-v2.ts
Normal file
25
src/channels/imessage-v2.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* iMessage channel adapter (v2) — uses Chat SDK bridge.
|
||||
* Supports local mode (macOS Full Disk Access) and remote mode (Photon API).
|
||||
* Self-registers on import.
|
||||
*/
|
||||
import { createiMessageAdapter } from 'chat-adapter-imessage';
|
||||
|
||||
import { readEnvFile } from '../env.js';
|
||||
import { createChatSdkBridge } from './chat-sdk-bridge.js';
|
||||
import { registerChannelAdapter } from './channel-registry.js';
|
||||
|
||||
registerChannelAdapter('imessage', {
|
||||
factory: () => {
|
||||
const env = readEnvFile(['IMESSAGE_ENABLED', 'IMESSAGE_LOCAL', 'IMESSAGE_SERVER_URL', 'IMESSAGE_API_KEY']);
|
||||
const isLocal = env.IMESSAGE_LOCAL !== 'false';
|
||||
if (isLocal && !env.IMESSAGE_ENABLED) return null;
|
||||
if (!isLocal && !env.IMESSAGE_SERVER_URL) return null;
|
||||
const imessageAdapter = createiMessageAdapter({
|
||||
local: isLocal,
|
||||
serverUrl: env.IMESSAGE_SERVER_URL,
|
||||
apiKey: env.IMESSAGE_API_KEY,
|
||||
});
|
||||
return createChatSdkBridge({ adapter: imessageAdapter, concurrency: 'concurrent' });
|
||||
},
|
||||
});
|
||||
@@ -1,12 +1,42 @@
|
||||
// Channel self-registration barrel file.
|
||||
// Each import triggers the channel module's registerChannel() call.
|
||||
// Each import triggers the channel module's registerChannelAdapter() call.
|
||||
|
||||
// discord
|
||||
|
||||
// gmail
|
||||
// import './discord-v2.js';
|
||||
|
||||
// slack
|
||||
// import './slack-v2.js';
|
||||
|
||||
// telegram
|
||||
// import './telegram-v2.js';
|
||||
|
||||
// whatsapp
|
||||
// github
|
||||
// import './github-v2.js';
|
||||
|
||||
// linear
|
||||
// import './linear-v2.js';
|
||||
|
||||
// google chat
|
||||
// import './gchat-v2.js';
|
||||
|
||||
// microsoft teams
|
||||
// import './teams-v2.js';
|
||||
|
||||
// whatsapp cloud api
|
||||
// import './whatsapp-cloud-v2.js';
|
||||
|
||||
// resend (email)
|
||||
// import './resend-v2.js';
|
||||
|
||||
// matrix
|
||||
// import './matrix-v2.js';
|
||||
|
||||
// webex
|
||||
// import './webex-v2.js';
|
||||
|
||||
// imessage
|
||||
// import './imessage-v2.js';
|
||||
|
||||
// gmail (native, no Chat SDK)
|
||||
|
||||
// whatsapp baileys (native, no Chat SDK)
|
||||
|
||||
22
src/channels/linear-v2.ts
Normal file
22
src/channels/linear-v2.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Linear channel adapter (v2) — uses Chat SDK bridge.
|
||||
* Issue comment threads as conversations.
|
||||
* Self-registers on import.
|
||||
*/
|
||||
import { createLinearAdapter } from '@chat-adapter/linear';
|
||||
|
||||
import { readEnvFile } from '../env.js';
|
||||
import { createChatSdkBridge } from './chat-sdk-bridge.js';
|
||||
import { registerChannelAdapter } from './channel-registry.js';
|
||||
|
||||
registerChannelAdapter('linear', {
|
||||
factory: () => {
|
||||
const env = readEnvFile(['LINEAR_API_KEY', 'LINEAR_WEBHOOK_SECRET']);
|
||||
if (!env.LINEAR_API_KEY) return null;
|
||||
const linearAdapter = createLinearAdapter({
|
||||
apiKey: env.LINEAR_API_KEY,
|
||||
webhookSecret: env.LINEAR_WEBHOOK_SECRET,
|
||||
});
|
||||
return createChatSdkBridge({ adapter: linearAdapter, concurrency: 'queue' });
|
||||
},
|
||||
});
|
||||
23
src/channels/matrix-v2.ts
Normal file
23
src/channels/matrix-v2.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Matrix channel adapter (v2) — uses Chat SDK bridge.
|
||||
* Self-registers on import.
|
||||
*/
|
||||
import { createMatrixAdapter } from '@beeper/chat-adapter-matrix';
|
||||
|
||||
import { readEnvFile } from '../env.js';
|
||||
import { createChatSdkBridge } from './chat-sdk-bridge.js';
|
||||
import { registerChannelAdapter } from './channel-registry.js';
|
||||
|
||||
registerChannelAdapter('matrix', {
|
||||
factory: () => {
|
||||
const env = readEnvFile(['MATRIX_BASE_URL', 'MATRIX_ACCESS_TOKEN', 'MATRIX_USER_ID', 'MATRIX_BOT_USERNAME']);
|
||||
if (!env.MATRIX_BASE_URL) return null;
|
||||
// Matrix adapter reads from process.env directly
|
||||
process.env.MATRIX_BASE_URL = env.MATRIX_BASE_URL;
|
||||
if (env.MATRIX_ACCESS_TOKEN) process.env.MATRIX_ACCESS_TOKEN = env.MATRIX_ACCESS_TOKEN;
|
||||
if (env.MATRIX_USER_ID) process.env.MATRIX_USER_ID = env.MATRIX_USER_ID;
|
||||
if (env.MATRIX_BOT_USERNAME) process.env.MATRIX_BOT_USERNAME = env.MATRIX_BOT_USERNAME;
|
||||
const matrixAdapter = createMatrixAdapter();
|
||||
return createChatSdkBridge({ adapter: matrixAdapter, concurrency: 'concurrent' });
|
||||
},
|
||||
});
|
||||
23
src/channels/resend-v2.ts
Normal file
23
src/channels/resend-v2.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Resend (email) channel adapter (v2) — uses Chat SDK bridge.
|
||||
* Self-registers on import.
|
||||
*/
|
||||
import { createResendAdapter } from '@resend/chat-sdk-adapter';
|
||||
|
||||
import { readEnvFile } from '../env.js';
|
||||
import { createChatSdkBridge } from './chat-sdk-bridge.js';
|
||||
import { registerChannelAdapter } from './channel-registry.js';
|
||||
|
||||
registerChannelAdapter('resend', {
|
||||
factory: () => {
|
||||
const env = readEnvFile(['RESEND_API_KEY', 'RESEND_FROM_ADDRESS', 'RESEND_FROM_NAME', 'RESEND_WEBHOOK_SECRET']);
|
||||
if (!env.RESEND_API_KEY) return null;
|
||||
const resendAdapter = createResendAdapter({
|
||||
apiKey: env.RESEND_API_KEY,
|
||||
fromAddress: env.RESEND_FROM_ADDRESS,
|
||||
fromName: env.RESEND_FROM_NAME,
|
||||
webhookSecret: env.RESEND_WEBHOOK_SECRET,
|
||||
});
|
||||
return createChatSdkBridge({ adapter: resendAdapter, concurrency: 'queue' });
|
||||
},
|
||||
});
|
||||
21
src/channels/slack-v2.ts
Normal file
21
src/channels/slack-v2.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Slack channel adapter (v2) — uses Chat SDK bridge.
|
||||
* Self-registers on import.
|
||||
*/
|
||||
import { createSlackAdapter } from '@chat-adapter/slack';
|
||||
|
||||
import { readEnvFile } from '../env.js';
|
||||
import { createChatSdkBridge } from './chat-sdk-bridge.js';
|
||||
import { registerChannelAdapter } from './channel-registry.js';
|
||||
|
||||
registerChannelAdapter('slack', {
|
||||
factory: () => {
|
||||
const env = readEnvFile(['SLACK_BOT_TOKEN', 'SLACK_SIGNING_SECRET']);
|
||||
if (!env.SLACK_BOT_TOKEN) return null;
|
||||
const slackAdapter = createSlackAdapter({
|
||||
botToken: env.SLACK_BOT_TOKEN,
|
||||
signingSecret: env.SLACK_SIGNING_SECRET,
|
||||
});
|
||||
return createChatSdkBridge({ adapter: slackAdapter, concurrency: 'concurrent' });
|
||||
},
|
||||
});
|
||||
21
src/channels/teams-v2.ts
Normal file
21
src/channels/teams-v2.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Microsoft Teams channel adapter (v2) — uses Chat SDK bridge.
|
||||
* Self-registers on import.
|
||||
*/
|
||||
import { createTeamsAdapter } from '@chat-adapter/teams';
|
||||
|
||||
import { readEnvFile } from '../env.js';
|
||||
import { createChatSdkBridge } from './chat-sdk-bridge.js';
|
||||
import { registerChannelAdapter } from './channel-registry.js';
|
||||
|
||||
registerChannelAdapter('teams', {
|
||||
factory: () => {
|
||||
const env = readEnvFile(['TEAMS_APP_ID', 'TEAMS_APP_PASSWORD']);
|
||||
if (!env.TEAMS_APP_ID) return null;
|
||||
const teamsAdapter = createTeamsAdapter({
|
||||
appId: env.TEAMS_APP_ID,
|
||||
appPassword: env.TEAMS_APP_PASSWORD,
|
||||
});
|
||||
return createChatSdkBridge({ adapter: teamsAdapter, concurrency: 'concurrent' });
|
||||
},
|
||||
});
|
||||
21
src/channels/telegram-v2.ts
Normal file
21
src/channels/telegram-v2.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Telegram channel adapter (v2) — uses Chat SDK bridge.
|
||||
* Self-registers on import.
|
||||
*/
|
||||
import { createTelegramAdapter } from '@chat-adapter/telegram';
|
||||
|
||||
import { readEnvFile } from '../env.js';
|
||||
import { createChatSdkBridge } from './chat-sdk-bridge.js';
|
||||
import { registerChannelAdapter } from './channel-registry.js';
|
||||
|
||||
registerChannelAdapter('telegram', {
|
||||
factory: () => {
|
||||
const env = readEnvFile(['TELEGRAM_BOT_TOKEN']);
|
||||
if (!env.TELEGRAM_BOT_TOKEN) return null;
|
||||
const telegramAdapter = createTelegramAdapter({
|
||||
botToken: env.TELEGRAM_BOT_TOKEN,
|
||||
mode: 'polling',
|
||||
});
|
||||
return createChatSdkBridge({ adapter: telegramAdapter, concurrency: 'concurrent' });
|
||||
},
|
||||
});
|
||||
21
src/channels/webex-v2.ts
Normal file
21
src/channels/webex-v2.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Webex channel adapter (v2) — uses Chat SDK bridge.
|
||||
* Self-registers on import.
|
||||
*/
|
||||
import { createWebexAdapter } from '@bitbasti/chat-adapter-webex';
|
||||
|
||||
import { readEnvFile } from '../env.js';
|
||||
import { createChatSdkBridge } from './chat-sdk-bridge.js';
|
||||
import { registerChannelAdapter } from './channel-registry.js';
|
||||
|
||||
registerChannelAdapter('webex', {
|
||||
factory: () => {
|
||||
const env = readEnvFile(['WEBEX_BOT_TOKEN', 'WEBEX_WEBHOOK_SECRET']);
|
||||
if (!env.WEBEX_BOT_TOKEN) return null;
|
||||
const webexAdapter = createWebexAdapter({
|
||||
botToken: env.WEBEX_BOT_TOKEN,
|
||||
webhookSecret: env.WEBEX_WEBHOOK_SECRET,
|
||||
});
|
||||
return createChatSdkBridge({ adapter: webexAdapter, concurrency: 'concurrent' });
|
||||
},
|
||||
});
|
||||
24
src/channels/whatsapp-cloud-v2.ts
Normal file
24
src/channels/whatsapp-cloud-v2.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* WhatsApp Cloud API channel adapter (v2) — uses Chat SDK bridge.
|
||||
* Uses the official Meta WhatsApp Business Cloud API (not Baileys).
|
||||
* Self-registers on import.
|
||||
*/
|
||||
import { createWhatsAppAdapter } from '@chat-adapter/whatsapp';
|
||||
|
||||
import { readEnvFile } from '../env.js';
|
||||
import { createChatSdkBridge } from './chat-sdk-bridge.js';
|
||||
import { registerChannelAdapter } from './channel-registry.js';
|
||||
|
||||
registerChannelAdapter('whatsapp-cloud', {
|
||||
factory: () => {
|
||||
const env = readEnvFile(['WHATSAPP_ACCESS_TOKEN', 'WHATSAPP_PHONE_NUMBER_ID', 'WHATSAPP_APP_SECRET', 'WHATSAPP_VERIFY_TOKEN']);
|
||||
if (!env.WHATSAPP_ACCESS_TOKEN) return null;
|
||||
const whatsappAdapter = createWhatsAppAdapter({
|
||||
accessToken: env.WHATSAPP_ACCESS_TOKEN,
|
||||
phoneNumberId: env.WHATSAPP_PHONE_NUMBER_ID,
|
||||
appSecret: env.WHATSAPP_APP_SECRET,
|
||||
verifyToken: env.WHATSAPP_VERIFY_TOKEN,
|
||||
});
|
||||
return createChatSdkBridge({ adapter: whatsappAdapter, concurrency: 'concurrent' });
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user