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

121
package-lock.json generated
View file

@ -8,7 +8,9 @@
"name": "@qwen-code/qwen-code",
"version": "0.13.0",
"workspaces": [
"packages/*"
"packages/*",
"packages/channels/base",
"packages/channels/telegram"
],
"dependencies": {
"@testing-library/dom": "^10.4.1",
@ -2990,6 +2992,14 @@
"integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==",
"license": "BSD-3-Clause"
},
"node_modules/@qwen-code/channel-base": {
"resolved": "packages/channels/base",
"link": true
},
"node_modules/@qwen-code/channel-telegram": {
"resolved": "packages/channels/telegram",
"link": true
},
"node_modules/@qwen-code/qwen-code": {
"resolved": "packages/cli",
"link": true
@ -3961,6 +3971,12 @@
"node": ">= 10.16.0 < 11 || >= 11.8.0 < 12 || >= 12.0.0"
}
},
"node_modules/@telegraf/types": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/@telegraf/types/-/types-7.1.0.tgz",
"integrity": "sha512-kGevOIbpMcIlCDeorKGpwZmdH7kHbqlk/Yj6dEpJMKEQw5lk0KVQY0OLXaCswy8GqlIVLd5625OB+rAntP9xVw==",
"license": "MIT"
},
"node_modules/@testing-library/dom": {
"version": "10.4.1",
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz",
@ -6739,6 +6755,22 @@
"ieee754": "^1.1.13"
}
},
"node_modules/buffer-alloc": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
"integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
"license": "MIT",
"dependencies": {
"buffer-alloc-unsafe": "^1.1.0",
"buffer-fill": "^1.0.0"
}
},
"node_modules/buffer-alloc-unsafe": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
"integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==",
"license": "MIT"
},
"node_modules/buffer-crc32": {
"version": "0.2.13",
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
@ -6754,6 +6786,12 @@
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
"license": "BSD-3-Clause"
},
"node_modules/buffer-fill": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
"integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==",
"license": "MIT"
},
"node_modules/bundle-name": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz",
@ -12954,6 +12992,15 @@
"integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==",
"license": "MIT"
},
"node_modules/mri": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
"integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
"license": "MIT",
"engines": {
"node": ">=4"
}
},
"node_modules/mrmime": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz",
@ -13889,6 +13936,15 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/p-timeout": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-4.1.0.tgz",
"integrity": "sha512-+/wmHtzJuWii1sXn3HCuH/FTwGhrp4tmJTxSKJbfS+vkipci6osxXM5mY0jUiRzWKMTgUT8l7HFbeSwZAynqHw==",
"license": "MIT",
"engines": {
"node": ">=10"
}
},
"node_modules/package-json": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/package-json/-/package-json-10.0.1.tgz",
@ -15609,6 +15665,15 @@
],
"license": "MIT"
},
"node_modules/safe-compare": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/safe-compare/-/safe-compare-1.1.4.tgz",
"integrity": "sha512-b9wZ986HHCo/HbKrRpBJb2kqXMK9CEWIE1egeEvZsYn69ay3kdfl9nG3RyOcR+jInTDf7a86WQ1d4VJX7goSSQ==",
"license": "MIT",
"dependencies": {
"buffer-alloc": "^1.2.0"
}
},
"node_modules/safe-push-apply": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
@ -15650,6 +15715,15 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"license": "MIT"
},
"node_modules/sandwich-stream": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/sandwich-stream/-/sandwich-stream-2.0.2.tgz",
"integrity": "sha512-jLYV0DORrzY3xaz/S9ydJL6Iz7essZeAfnAavsJ+zsJGZ1MOnsS52yRjU3uF3pJa/lla7+wisp//fxOwOH8SKQ==",
"license": "Apache-2.0",
"engines": {
"node": ">= 0.10"
}
},
"node_modules/sax": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
@ -16933,6 +17007,28 @@
"node": ">=6"
}
},
"node_modules/telegraf": {
"version": "4.16.3",
"resolved": "https://registry.npmjs.org/telegraf/-/telegraf-4.16.3.tgz",
"integrity": "sha512-yjEu2NwkHlXu0OARWoNhJlIjX09dRktiMQFsM678BAH/PEPVwctzL67+tvXqLCRQQvm3SDtki2saGO9hLlz68w==",
"license": "MIT",
"dependencies": {
"@telegraf/types": "^7.1.0",
"abort-controller": "^3.0.0",
"debug": "^4.3.4",
"mri": "^1.2.0",
"node-fetch": "^2.7.0",
"p-timeout": "^4.1.0",
"safe-compare": "^1.1.4",
"sandwich-stream": "^2.0.2"
},
"bin": {
"telegraf": "lib/cli.mjs"
},
"engines": {
"node": "^12.20.0 || >=14.13.1"
}
},
"node_modules/terminal-link": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-4.0.0.tgz",
@ -18798,6 +18894,27 @@
"url": "https://github.com/sponsors/colinhacks"
}
},
"packages/channels/base": {
"name": "@qwen-code/channel-base",
"version": "0.1.0",
"dependencies": {
"@agentclientprotocol/sdk": "^0.14.1"
},
"devDependencies": {
"typescript": "^5.0.0"
}
},
"packages/channels/telegram": {
"name": "@qwen-code/channel-telegram",
"version": "0.1.0",
"dependencies": {
"@qwen-code/channel-base": "file:../base",
"telegraf": "^4.16.0"
},
"devDependencies": {
"typescript": "^5.0.0"
}
},
"packages/cli": {
"name": "@qwen-code/qwen-code",
"version": "0.13.0",
@ -18806,6 +18923,8 @@
"@google/genai": "1.30.0",
"@iarna/toml": "^2.2.5",
"@modelcontextprotocol/sdk": "^1.25.1",
"@qwen-code/channel-base": "file:../channels/base",
"@qwen-code/channel-telegram": "file:../channels/telegram",
"@qwen-code/qwen-code-core": "file:../core",
"@qwen-code/web-templates": "file:../web-templates",
"@types/update-notifier": "^6.0.8",