mirror of
https://github.com/OpenRouterTeam/spawn.git
synced 2026-05-13 07:10:46 +00:00
fix: move channel setup to after gateway starts (#2590)
* fix: move Telegram/WhatsApp channel setup to after gateway starts OpenClaw's `channels add` and `channels login` commands require a running gateway. Previously, Telegram token configuration ran in setupOpenclawConfig (pre-gateway) using `openclaw config set`, causing the gateway to hang on startup when a token was present for a disabled-by-default plugin. Now: - Plugin enables stay in setupOpenclawConfig (pre-gateway) - Channel config (token add, QR login) runs in orchestrate.ts step 11c after the gateway is up, using `openclaw channels add/login` Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * security: use shellQuote instead of jsonEscape for Telegram token jsonEscape uses JSON.stringify which produces double-quoted strings that the shell interprets, creating a command injection vector. shellQuote wraps in single quotes, preventing shell interpretation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: fix biome export ordering in interactive.ts and manifest.ts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: L <6723574+louisgv@users.noreply.github.com>
This commit is contained in:
parent
39622b68ab
commit
06bbbcb2a4
2 changed files with 37 additions and 39 deletions
|
|
@ -9,7 +9,7 @@ import { join } from "node:path";
|
|||
import { getTmpDir } from "./paths";
|
||||
import { asyncTryCatch, asyncTryCatchIf, isOperationalError, tryCatchIf } from "./result.js";
|
||||
import { getErrorMessage } from "./type-guards";
|
||||
import { Err, jsonEscape, logError, logInfo, logStep, logWarn, Ok, prompt, shellQuote, withRetry } from "./ui";
|
||||
import { Err, jsonEscape, logError, logInfo, logStep, logWarn, Ok, shellQuote, withRetry } from "./ui";
|
||||
|
||||
/**
|
||||
* Wrap an SSH-based async operation into a Result for use with withRetry.
|
||||
|
|
@ -393,39 +393,8 @@ async function setupOpenclawConfig(
|
|||
logWarn("Gateway token re-assertion failed (non-fatal) — dashboard may show Unauthorized");
|
||||
}
|
||||
|
||||
// Telegram channel setup — check env var first, then prompt interactively
|
||||
if (enabledSteps?.has("telegram")) {
|
||||
logStep("Setting up Telegram...");
|
||||
const envToken = process.env.TELEGRAM_BOT_TOKEN;
|
||||
if (!envToken) {
|
||||
logInfo("To get a bot token:");
|
||||
logInfo(" 1. Open Telegram and search for @BotFather");
|
||||
logInfo(" 2. Send /newbot and follow the prompts");
|
||||
logInfo(" 3. Copy the token (looks like 123456:ABC-DEF...)");
|
||||
logInfo(" Press Enter to skip if you don't have one yet.");
|
||||
}
|
||||
const trimmedToken = envToken?.trim() || (await prompt("Telegram bot token: ")).trim();
|
||||
|
||||
if (trimmedToken) {
|
||||
const escapedBotToken = shellQuote(trimmedToken);
|
||||
const telegramResult = await asyncTryCatchIf(isOperationalError, () =>
|
||||
runner.runServer(
|
||||
"export PATH=$HOME/.npm-global/bin:$HOME/.bun/bin:$HOME/.local/bin:$PATH; " +
|
||||
`openclaw config set channels.telegram.botToken ${escapedBotToken}`,
|
||||
),
|
||||
);
|
||||
if (telegramResult.ok) {
|
||||
logInfo("Telegram bot token configured");
|
||||
} else {
|
||||
logWarn("Telegram config failed — set it up via the web dashboard after launch");
|
||||
}
|
||||
} else {
|
||||
logInfo("No token entered — set up Telegram via the web dashboard after launch");
|
||||
}
|
||||
}
|
||||
|
||||
// WhatsApp — QR code scanning happens interactively in orchestrate.ts
|
||||
// after the gateway starts and tunnel is set up. No config needed here.
|
||||
// Channel configuration (Telegram token, WhatsApp QR) happens in orchestrate.ts
|
||||
// AFTER the gateway starts — openclaw channels commands need a running gateway.
|
||||
|
||||
// Write USER.md bootstrap file — guides users to the web dashboard for
|
||||
// visual tasks like WhatsApp QR code scanning that don't work in the TUI.
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ import {
|
|||
logWarn,
|
||||
openBrowser,
|
||||
prepareStdinForHandoff,
|
||||
prompt,
|
||||
shellQuote,
|
||||
validateModelId,
|
||||
withRetry,
|
||||
} from "./ui";
|
||||
|
|
@ -291,15 +293,42 @@ export async function runOrchestration(
|
|||
}
|
||||
}
|
||||
|
||||
// 11c. Interactive channel login (WhatsApp QR scan, Telegram bot link)
|
||||
// Runs before the TUI so users can link messaging channels during setup.
|
||||
// 11c. Channel setup (runs after gateway is up so openclaw commands work)
|
||||
const ocPath = "export PATH=$HOME/.npm-global/bin:$HOME/.bun/bin:$HOME/.local/bin:$PATH";
|
||||
|
||||
if (enabledSteps?.has("telegram")) {
|
||||
logStep("Setting up Telegram...");
|
||||
const envToken = process.env.TELEGRAM_BOT_TOKEN;
|
||||
if (!envToken) {
|
||||
logInfo("To get a bot token:");
|
||||
logInfo(" 1. Open Telegram and search for @BotFather");
|
||||
logInfo(" 2. Send /newbot and follow the prompts");
|
||||
logInfo(" 3. Copy the token (looks like 123456:ABC-DEF...)");
|
||||
logInfo(" Press Enter to skip if you don't have one yet.");
|
||||
}
|
||||
const trimmedToken = envToken?.trim() || (await prompt("Telegram bot token: ")).trim();
|
||||
if (trimmedToken) {
|
||||
const escaped = shellQuote(trimmedToken);
|
||||
const result = await asyncTryCatchIf(isOperationalError, () =>
|
||||
cloud.runner.runServer(
|
||||
`source ~/.spawnrc 2>/dev/null; ${ocPath}; openclaw channels add --channel telegram --token ${escaped}`,
|
||||
),
|
||||
);
|
||||
if (result.ok) {
|
||||
logInfo("Telegram channel added");
|
||||
} else {
|
||||
logWarn("Telegram setup failed — configure it via the web dashboard after launch");
|
||||
}
|
||||
} else {
|
||||
logInfo("No token entered — set up Telegram via the web dashboard after launch");
|
||||
}
|
||||
}
|
||||
|
||||
if (enabledSteps?.has("whatsapp")) {
|
||||
logStep("Linking WhatsApp — scan the QR code with your phone...");
|
||||
logInfo("Open WhatsApp > Settings > Linked Devices > Link a Device");
|
||||
process.stderr.write("\n");
|
||||
const whatsappCmd =
|
||||
"source ~/.spawnrc 2>/dev/null; export PATH=$HOME/.npm-global/bin:$HOME/.bun/bin:$HOME/.local/bin:$PATH; " +
|
||||
"openclaw channels login --channel whatsapp";
|
||||
const whatsappCmd = `source ~/.spawnrc 2>/dev/null; ${ocPath}; openclaw channels login --channel whatsapp`;
|
||||
prepareStdinForHandoff();
|
||||
await cloud.interactiveSession(whatsappCmd);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue