feat(channels): add Telegram channel integration with ACP bridge

Implements the channels infrastructure for connecting external messaging
platforms to Qwen Code via ACP. Phase 1 supports plain text round-trip:
Telegram user sends message -> AcpBridge -> qwen-code --acp -> response
back to Telegram.

New packages:
- @qwen-code/channel-base: AcpBridge, SessionRouter, SenderGate, ChannelBase
- @qwen-code/channel-telegram: TelegramAdapter using telegraf

CLI: `qwen channel start <name>` reads from settings.json channels config,
spawns ACP agent, connects to Telegram via polling.
This commit is contained in:
tanzhenxin 2026-03-24 04:49:01 +00:00
parent aebe889b31
commit 3eedc43238
18 changed files with 736 additions and 4 deletions

View file

@ -0,0 +1,37 @@
import type { SessionTarget } from './types.js';
import type { AcpBridge } from './AcpBridge.js';
export class SessionRouter {
private toSession: Map<string, string> = new Map(); // routing key → session ID
private toTarget: Map<string, SessionTarget> = new Map(); // session ID → target
private bridge: AcpBridge;
private cwd: string;
constructor(bridge: AcpBridge, cwd: string) {
this.bridge = bridge;
this.cwd = cwd;
}
async resolve(
channelName: string,
senderId: string,
chatId: string,
threadId?: string,
): Promise<string> {
const key = `${channelName}:${senderId}`;
const existing = this.toSession.get(key);
if (existing) {
return existing;
}
const sessionId = await this.bridge.newSession(this.cwd);
this.toSession.set(key, sessionId);
this.toTarget.set(sessionId, { channelName, senderId, chatId, threadId });
return sessionId;
}
getTarget(sessionId: string): SessionTarget | undefined {
return this.toTarget.get(sessionId);
}
}