一键导入
yaebal-deploy
Use when running a yaebal bot in production — long polling with @yaebal/runner vs webhooks with @yaebal/web, graceful shutdown, and error handling.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Use when running a yaebal bot in production — long polling with @yaebal/runner vs webhooks with @yaebal/web, graceful shutdown, and error handling.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
Use when building multi-step dialogs in a yaebal bot — choosing between scenes, conversation, and prompt, and wiring their persistence.
Use when writing or modifying a Telegram bot built on the yaebal framework — bot setup, handlers, filter queries, commands, and context typing.
Use when adding LLM features to a yaebal bot with @yaebal/ai — ctx.ai streaming replies, model adapters, conversation memory, and rate limits.
Use when writing a custom yaebal plugin — the Plugin<In, Out> contract, derive vs decorate, and typed plugin dependencies.
Use when a yaebal bot fails to compile, start, or respond — install-order type errors, ESM specifier errors, Telegram 400/409/429 responses.
Use when adding inline/reply keyboards or handling button presses in a yaebal bot — @yaebal/keyboard builders and @yaebal/callback-data typed payloads.
基于 SOC 职业分类
| name | yaebal-deploy |
| description | Use when running a yaebal bot in production — long polling with @yaebal/runner vs webhooks with @yaebal/web, graceful shutdown, and error handling. |
two transports. pick by hosting model:
bot.start() is fine for dev; use @yaebal/runner in production for concurrency.@yaebal/web.updates that share a chat id run strictly in order; unrelated chats run in parallel:
import { run } from "@yaebal/runner";
const handle = run(bot, {
concurrency: 50, // max parallel updates (default 50)
onError: (err, update) => console.error(update?.update_id, err),
});
process.once("SIGINT", () => handle.stop()); // graceful shutdown
process.once("SIGTERM", () => handle.stop());
(plain bot.start() processes updates sequentially; stop it with bot.stop().)
import { Bot } from "@yaebal/core";
import { webhook, serve, setWebhook, sequentialize, dedupe } from "@yaebal/web";
const bot = new Bot(process.env.BOT_TOKEN!, { botInfo: BOT_INFO }); // botInfo skips the getMe round-trip on edge
bot.use(sequentialize()); // per-chat ordering — before session/scenes/conversation
bot.use(dedupe()); // drop telegram's redelivered update_ids
// fetch-native runtimes (workers / deno deploy / vercel edge / hono / elysia)
export default { fetch: webhook(bot, { secretToken: process.env.WEBHOOK_SECRET }) };
// or a standalone node/bun/deno server
const server = await serve(bot, { port: 8080, secretToken: process.env.WEBHOOK_SECRET });
process.once("SIGINT", () => server.stop());
register the webhook once, from a separate deploy script — never at module top level:
await setWebhook(bot, "https://my-worker.workers.dev/", {
secretToken: process.env.WEBHOOK_SECRET,
dropPendingUpdates: true,
});
framework adapters exist for everything else: expressAdapter, fastifyAdapter,
koaAdapter, honoAdapter, elysiaAdapter, nextAdapter, svelteKitAdapter,
cloudflareAdapter, awsLambdaAdapter, gcfAdapter, azureAdapter. core also exports a
bare webhookCallback(bot, options) returning a (Request) => Promise<Response>.
import { autoRetry } from "@yaebal/again";
import { throttle } from "@yaebal/throttle";
bot.onError((error, ctx) => console.error(ctx.update.update_id, error)); // handler errors
bot.onPollingError((error) => console.error("poll failed", error)); // getUpdates failures
autoRetry(bot.api, { maxRetries: 5 }); // await 429 retry_after / transient failures
bot.install(throttle({ globalPerSec: 30 })); // stay under telegram's flood limits outbound
deleteWebhook(bot, { dropPendingUpdates: true }) from @yaebal/web.secretToken on webhooks and let the handler verify it (all adapters forward
it). optionally check isTelegramIp(...) as defence in depth.sequentialize() (and dedupe()) before
any state plugin, or per-chat session state can race.handle.stop() / server.stop() /
bot.stop()), let in-flight handlers finish, then exit. wire both SIGINT and SIGTERM.BOT_TOKEN, WEBHOOK_SECRET, api keys) come from the environment, never the repo.