feat(setup): optional Telegram wiring in setup:auto

After cli-agent, prompt the user to connect a messaging app. For now
only Telegram is offered; "skip" falls through to the existing CLI
flow.

setup/add-telegram.sh runs the scriptable half of /add-telegram: fetch
the channels branch, copy the adapter + pair-telegram files, append
the self-registration import, install @chat-adapter/telegram@4.26.0
(pinned to match the skill), rebuild, collect TELEGRAM_BOT_TOKEN via
silent paste, write .env + data/env/env, and kick the service so the
new adapter is live. Idempotent throughout.

setup:auto then runs the existing `pair-telegram` step with
--intent main. The step emits the 4-digit code in its status stream,
which is already forwarded to stdout by runStep.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gavrielc
2026-04-22 00:04:14 +03:00
parent c87cd250b2
commit 9c7e1d02af
3 changed files with 178 additions and 3 deletions

134
setup/add-telegram.sh Executable file
View File

@@ -0,0 +1,134 @@
#!/usr/bin/env bash
set -euo pipefail
# Install the Telegram adapter (Phase A of the /add-telegram skill), collect
# the bot token, write .env + data/env/env, and restart the service so the
# new adapter is live. Idempotent.
#
# Pair-telegram (the interactive code-sending step) is run separately by the
# caller (setup/auto.ts) so it can stream status blocks to the user.
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$PROJECT_ROOT"
# Keep in sync with .claude/skills/add-telegram/SKILL.md.
ADAPTER_VERSION="@chat-adapter/telegram@4.26.0"
CHANNELS_BRANCH="origin/channels"
need_install() {
[[ ! -f src/channels/telegram.ts ]] && return 0
[[ ! -f setup/pair-telegram.ts ]] && return 0
! grep -q "^import './telegram.js';" src/channels/index.ts 2>/dev/null && return 0
return 1
}
if need_install; then
echo "[add-telegram] Fetching channels branch…"
git fetch origin channels >/dev/null 2>&1
echo "[add-telegram] Copying adapter files from $CHANNELS_BRANCH"
for f in \
src/channels/telegram.ts \
src/channels/telegram-pairing.ts \
src/channels/telegram-pairing.test.ts \
src/channels/telegram-markdown-sanitize.ts \
src/channels/telegram-markdown-sanitize.test.ts \
setup/pair-telegram.ts
do
git show "$CHANNELS_BRANCH:$f" > "$f"
done
# Append self-registration import if missing.
if ! grep -q "^import './telegram.js';" src/channels/index.ts; then
echo "import './telegram.js';" >> src/channels/index.ts
fi
# Register pair-telegram step if not already in the STEPS map.
# Uses node (not sed) since sed's in-place + escape semantics differ
# between BSD (macOS) and GNU.
node -e '
const fs = require("fs");
const p = "setup/index.ts";
let s = fs.readFileSync(p, "utf-8");
if (!s.includes("\047pair-telegram\047")) {
s = s.replace(
/(register: \(\) => import\(\x27\.\/register\.js\x27\),)/,
"$1\n \x27pair-telegram\x27: () => import(\x27./pair-telegram.js\x27),"
);
fs.writeFileSync(p, s);
}
'
echo "[add-telegram] Installing $ADAPTER_VERSION"
pnpm install "$ADAPTER_VERSION"
echo "[add-telegram] Building…"
pnpm run build >/dev/null
else
echo "[add-telegram] Adapter files already installed — skipping install phase."
fi
# Token collection.
if grep -q '^TELEGRAM_BOT_TOKEN=.' .env 2>/dev/null; then
echo "[add-telegram] TELEGRAM_BOT_TOKEN already set in .env — skipping token prompt."
else
cat <<'EOF'
── Create a Telegram bot ──────────────────────────────────────
1. Open Telegram and message @BotFather
2. Send: /newbot
3. Follow the prompts (bot name, username ending in "bot")
4. Copy the token it gives you (format: <digits>:<chars>)
Optional but recommended for groups:
5. @BotFather → /mybots → your bot → Bot Settings → Group Privacy → OFF
EOF
echo "Paste your TELEGRAM_BOT_TOKEN and press Enter."
echo "Nothing will appear on the screen as you paste — that's intentional."
echo "Paste once, then just press Enter to submit."
read -r -s -p "> " TOKEN </dev/tty
echo
if [[ -z "$TOKEN" ]]; then
echo "[add-telegram] No token entered. Aborting." >&2
exit 1
fi
# Telegram bot tokens: <digits>:<35+ base64url-ish chars>.
if [[ ! "$TOKEN" =~ ^[0-9]+:[A-Za-z0-9_-]{35,}$ ]]; then
echo "[add-telegram] Token format looks wrong (expected <digits>:<chars>). Aborting." >&2
exit 1
fi
touch .env
if grep -q '^TELEGRAM_BOT_TOKEN=' .env; then
awk -v tok="$TOKEN" '/^TELEGRAM_BOT_TOKEN=/{print "TELEGRAM_BOT_TOKEN=" tok; next} {print}' \
.env > .env.tmp && mv .env.tmp .env
else
echo "TELEGRAM_BOT_TOKEN=$TOKEN" >> .env
fi
fi
# Container reads from data/env/env (the host mounts it).
mkdir -p data/env
cp .env data/env/env
echo "[add-telegram] Restarting service so the new adapter picks up the token…"
case "$(uname -s)" in
Darwin)
launchctl kickstart -k "gui/$(id -u)/com.nanoclaw" >/dev/null 2>&1 || true
;;
Linux)
systemctl --user restart nanoclaw >/dev/null 2>&1 \
|| sudo systemctl restart nanoclaw >/dev/null 2>&1 \
|| true
;;
esac
# Give the Telegram adapter a moment to finish starting before pair-telegram
# begins polling for the user's code message.
sleep 5
echo "[add-telegram] Install + credentials complete."