一键导入
yaebal-ai-features
Use when adding LLM features to a yaebal bot with @yaebal/ai — ctx.ai streaming replies, model adapters, conversation memory, and rate limits.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Use when adding LLM features to a yaebal bot with @yaebal/ai — ctx.ai streaming replies, model adapters, conversation memory, and rate limits.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
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 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 running a yaebal bot in production — long polling with @yaebal/runner vs webhooks with @yaebal/web, graceful shutdown, and error handling.
Use when adding inline/reply keyboards or handling button presses in a yaebal bot — @yaebal/keyboard builders and @yaebal/callback-data typed payloads.
| name | yaebal-ai-features |
| description | Use when adding LLM features to a yaebal bot with @yaebal/ai — ctx.ai streaming replies, model adapters, conversation memory, and rate limits. |
bot.install(ai({ model })) adds ctx.ai to every context: model calls flow through optional
per-user limits, conversation memory and a system prompt, and stream into the chat using
telegram's native draft animation where available.
import { createBot } from "yaebal";
import { ai, openaiCompatible, AiLimitError } from "@yaebal/ai";
const bot = createBot(process.env.BOT_TOKEN!).install(
ai({
model: openaiCompatible({ model: "gpt-4o-mini", apiKey: process.env.OPENAI_API_KEY }),
system: "you are a concise, friendly assistant.",
limits: { perUser: "20/h" },
parseMode: "MarkdownV2", // finalized messages only — see behavior below
}),
);
bot.on("message:text", async (ctx) => {
try {
await ctx.ai.replyStream(ctx.text);
} catch (error) {
if (error instanceof AiLimitError)
return ctx.reply(`slow down — try again in ${Math.ceil(error.retryAfterMs / 1000)}s`);
throw error;
}
});
bot.command("reset", async (ctx) => {
await ctx.ai.reset();
await ctx.send("forgotten.");
});
ctx.ai.replyStream(prompt, options?) — stream into the chat: in private chats via
sendMessageDraft (telegram's own "Thinking…" placeholder + animated draft, finalized as a
real message); in groups/channels via throttled editMessageText with a ▍ cursor. answers
past 4096 chars split at word boundaries and finalize message-by-message. returns
{ text, messages, mode: "draft" | "edit", ticks, aborted }.ctx.ai.reply(prompt, options?) — generate fully, then send (typing action kept alive
meanwhile); returns { text, usage?, messages }.ctx.ai.generate(prompt, options?) — run the model, return { text, usage }, send nothing.
does not write memory by default (opt in with { memory: true }).ctx.ai.stream(prompt, options?) — raw AsyncIterable<string> for custom rendering; reads
memory but never writes it.ctx.ai.history() / ctx.ai.reset() — read / forget this conversation's memory.ctx.ai.model — the resolved adapter (.id for logs).prompt is a string or an AiMessage[]; per-call options can override system, memory,
temperature, maxTokens, and pass an AbortSignal as signal.
openaiCompatible({ model: "llama3.2", baseUrl: "http://localhost:11434/v1" }); // any /chat/completions api
anthropicModel({ model: "claude-sonnet-5", apiKey: process.env.ANTHROPIC_API_KEY! });
ai({ model: anthropic("claude-sonnet-5") }); // a vercel ai sdk LanguageModel, auto-detected
// (or wrap explicitly: aiSdk(anthropic("...")))
customModel(async function* ({ messages }) { // anything that yields strings
yield "hello ";
yield "world";
});
openaiCompatible and anthropicModel are zero-dependency fetch adapters; the ai sdk bridge
lazy-loads the ai package only when used.
**bold can never 400 mid-stream. if telegram rejects the finished entities,
the text is resent plain instead of being lost. don't try to apply markup to previews.@yaebal/sklad StorageAdapter via memory: { storage } to persist across restarts, or
memory: false for stateless calls.limits.perUser budgets throw AiLimitError (with retryAfterMs) — catch it and
answer politely; don't let it hit the global error handler.streaming: intervalMs (500 draft / 1200 edit), drafts: false
to opt out of drafts in private chats, cursor ("" disables), maxLength.typing: false disables the typing action for non-streamed replies.