feat(broker+cli): multi-tenant telegram bridge with 4 entry points
Some checks failed
CI / Lint (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Broker tests (Postgres) (push) Has been cancelled
CI / Docker build (linux/amd64) (push) Has been cancelled

- DB: mesh.telegram_bridge table + migration
- Broker: telegram-bridge.ts (Grammy bot + WS pool + routing)
- Broker: telegram-token.ts (JWT connect tokens)
- Broker: POST /tg/token endpoint + bridge boot on startup
- CLI: claudemesh connect/disconnect telegram commands
- Spec: docs/telegram-bridge-spec.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alejandro Gutiérrez
2026-04-09 10:03:11 +01:00
parent c914f2b7db
commit 126bbfeb2c
11 changed files with 2120 additions and 3 deletions

15
apps/telegram/Dockerfile Normal file
View File

@@ -0,0 +1,15 @@
# Telegram bridge for claudemesh
# Node 22 runtime with tsx for TypeScript execution
FROM node:22-slim
WORKDIR /app
COPY package.json ./
RUN npm install --omit=dev
COPY src/ ./src/
ENV NODE_ENV=production
CMD ["npx", "tsx", "src/index.ts"]

View File

@@ -2,7 +2,6 @@
"name": "@claudemesh/telegram",
"version": "0.1.0",
"private": true,
"type": "module",
"scripts": {
"start": "bun src/index.ts",
"dev": "bun --hot src/index.ts"
@@ -10,7 +9,9 @@
"dependencies": {
"grammy": "^1.35.0",
"ws": "^8.18.0",
"libsodium-wrappers": "^0.7.15"
"libsodium": "^0.7.15",
"libsodium-wrappers": "^0.7.15",
"tsx": "^4.19.0"
},
"devDependencies": {
"@types/ws": "^8.5.13",

View File

@@ -44,9 +44,22 @@ interface JoinedMesh {
}
function loadMeshConfig(): JoinedMesh[] {
// Support env-based config for Docker/VPS deployment
if (process.env.MESH_ID && process.env.MESH_MEMBER_ID && process.env.MESH_PUBKEY && process.env.MESH_SECRET_KEY) {
return [{
meshId: process.env.MESH_ID,
memberId: process.env.MESH_MEMBER_ID,
slug: process.env.MESH_SLUG ?? "mesh",
name: process.env.MESH_NAME ?? "mesh",
pubkey: process.env.MESH_PUBKEY,
secretKey: process.env.MESH_SECRET_KEY,
brokerUrl: process.env.MESH_BROKER_URL ?? "wss://ic.claudemesh.com/ws",
}];
}
// Fall back to config file
const path = join(CONFIG_DIR, "config.json");
if (!existsSync(path)) {
console.error(`No config at ${path} — run 'claudemesh join' first`);
console.error(`No config at ${path} set MESH_ID/MESH_MEMBER_ID/MESH_PUBKEY/MESH_SECRET_KEY env vars or run 'claudemesh join' first`);
process.exit(1);
}
const config = JSON.parse(readFileSync(path, "utf-8"));