opencode-tbot 0.1.12 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -115,8 +115,7 @@ Notes:
115
115
 
116
116
  ## Commands
117
117
 
118
- - `/start` show the welcome message and quick-start steps
119
- - `/help` show the full command reference and examples
118
+ - `/start` show a short welcome message and quick-start steps
120
119
  - `/status` show aggregated OpenCode health, path, LSP, and MCP status
121
120
  - `/new [title]` create a new OpenCode session
122
121
  - `/agents` or `/agent` list available agents and switch the active one
package/README.zh-CN.md CHANGED
@@ -115,8 +115,7 @@ npm uninstall opencode-tbot
115
115
 
116
116
  ## 命令
117
117
 
118
- - `/start` 显示欢迎信息和快速开始说明
119
- - `/help` 显示完整命令说明和示例
118
+ - `/start` 显示简短欢迎信息和快速开始说明
120
119
  - `/status` 显示 OpenCode 健康状态、路径、LSP 和 MCP 信息
121
120
  - `/new [title]` 创建新的 OpenCode 会话
122
121
  - `/agents` 或 `/agent` 列出可用 agent 并切换当前 agent
package/dist/plugin.js CHANGED
@@ -2414,7 +2414,6 @@ var SUPPORTED_BOT_LANGUAGES = ["en", "zh-CN"];
2414
2414
  var EN_BOT_COPY = {
2415
2415
  commands: {
2416
2416
  start: "Welcome and quick start",
2417
- help: "Show commands and examples",
2418
2417
  status: "Show system status",
2419
2418
  new: "Create a new session",
2420
2419
  agents: "View and switch agents",
@@ -2428,37 +2427,11 @@ var EN_BOT_COPY = {
2428
2427
  "",
2429
2428
  "Talk to your OpenCode server from Telegram.",
2430
2429
  "",
2431
- "## What you can send",
2432
- "- Text prompts",
2433
- "- Images with an optional caption",
2434
- "- Voice messages (requires OpenRouter voice transcription)",
2435
- "",
2436
2430
  "## Quick start",
2437
2431
  "1. Run `/status` to confirm the server is ready.",
2438
2432
  "2. Run `/new [title]` to create a fresh session.",
2439
- "3. Send a text, image, or voice message.",
2440
- "",
2441
- "Use `/help` to see the full command list and examples."
2442
- ] },
2443
- help: { lines: [
2444
- "# Help",
2445
- "",
2446
- "Use this bot to chat with OpenCode from Telegram.",
2447
2433
  "",
2448
- "## Commands",
2449
- "- `/status` Check server, workspace, MCP, and LSP status",
2450
- "- `/new [title]` Create a new session",
2451
- "- `/sessions` View, switch, or rename sessions",
2452
- "- `/agents` View and switch agents",
2453
- "- `/model` View and switch models and reasoning levels",
2454
- "- `/language` Switch the bot display language",
2455
- "- `/cancel` Cancel session rename or abort the running request",
2456
- "",
2457
- "## Examples",
2458
- "- `/new bug triage`",
2459
- "- Send a plain text message directly",
2460
- "- Send an image with a caption",
2461
- "- Send a voice message if OpenRouter voice transcription is configured"
2434
+ "Send a text, image, or voice message directly."
2462
2435
  ] },
2463
2436
  systemStatus: { title: "System Status" },
2464
2437
  common: {
@@ -2650,7 +2623,6 @@ var EN_BOT_COPY = {
2650
2623
  var ZH_CN_BOT_COPY = {
2651
2624
  commands: {
2652
2625
  start: "查看欢迎与快速开始",
2653
- help: "查看命令说明与示例",
2654
2626
  status: "查看系统状态",
2655
2627
  new: "新建会话",
2656
2628
  agents: "查看并切换代理",
@@ -2664,37 +2636,11 @@ var ZH_CN_BOT_COPY = {
2664
2636
  "",
2665
2637
  "通过 Telegram 直接和 OpenCode 服务对话。",
2666
2638
  "",
2667
- "## 支持的输入",
2668
- "- 文本消息",
2669
- "- 图片 (可附带 caption)",
2670
- "- 语音消息 (需先配置 OpenRouter 语音转写)",
2671
- "",
2672
2639
  "## 快速开始",
2673
2640
  "1. 先运行 `/status` 确认服务状态正常。",
2674
2641
  "2. 运行 `/new [title]` 创建一个新会话。",
2675
- "3. 直接发送文本、图片或语音消息。",
2676
- "",
2677
- "更多命令和示例请查看 `/help`。"
2678
- ] },
2679
- help: { lines: [
2680
- "# 帮助",
2681
2642
  "",
2682
- "使用这个机器人可以通过 Telegram 与 OpenCode 对话。",
2683
- "",
2684
- "## 命令",
2685
- "- `/status` 查看服务、工作区、MCP 和 LSP 状态",
2686
- "- `/new [title]` 创建一个新会话",
2687
- "- `/sessions` 查看、切换或重命名会话",
2688
- "- `/agents` 查看并切换代理",
2689
- "- `/model` 查看并切换模型与推理级别",
2690
- "- `/language` 切换机器人的显示语言",
2691
- "- `/cancel` 取消会话重命名或中止当前请求",
2692
- "",
2693
- "## 示例",
2694
- "- `/new bug triage`",
2695
- "- 直接发送一条文本消息",
2696
- "- 发送一张带 caption 的图片",
2697
- "- 如果已配置 OpenRouter 语音转写,直接发送语音消息"
2643
+ "直接发送文本、图片或语音消息即可。"
2698
2644
  ] },
2699
2645
  systemStatus: { title: "系统状态" },
2700
2646
  common: {
@@ -2908,10 +2854,6 @@ function getTelegramCommands(language = "en") {
2908
2854
  command: "start",
2909
2855
  description: copy.commands.start
2910
2856
  },
2911
- {
2912
- command: "help",
2913
- description: copy.commands.help
2914
- },
2915
2857
  {
2916
2858
  command: "status",
2917
2859
  description: copy.commands.status
@@ -3744,6 +3686,112 @@ function registerCancelCommand(bot, dependencies) {
3744
3686
  });
3745
3687
  }
3746
3688
  //#endregion
3689
+ //#region src/bot/commands/language.ts
3690
+ async function handleLanguageCommand(ctx, dependencies) {
3691
+ const language = await getChatLanguage(dependencies.sessionRepo, ctx.chat.id);
3692
+ const copy = await getChatCopy(dependencies.sessionRepo, ctx.chat.id);
3693
+ try {
3694
+ await syncTelegramCommandsForChat(ctx.api, ctx.chat.id, language);
3695
+ await ctx.reply(presentLanguageMessage(language, copy), { reply_markup: buildLanguageKeyboard(language, copy) });
3696
+ } catch (error) {
3697
+ dependencies.logger.error({ error }, "failed to show language options");
3698
+ await ctx.reply(presentError(error, copy));
3699
+ }
3700
+ }
3701
+ async function switchLanguageForChat(api, chatId, language, dependencies) {
3702
+ const currentCopy = await getChatCopy(dependencies.sessionRepo, chatId);
3703
+ if (!isBotLanguage(language)) return {
3704
+ found: false,
3705
+ copy: currentCopy
3706
+ };
3707
+ await setChatLanguage(dependencies.sessionRepo, chatId, language);
3708
+ await syncTelegramCommandsForChat(api, chatId, language);
3709
+ return {
3710
+ found: true,
3711
+ copy: await getChatCopy(dependencies.sessionRepo, chatId),
3712
+ language
3713
+ };
3714
+ }
3715
+ async function presentLanguageSwitchForChat(chatId, api, language, dependencies) {
3716
+ const result = await switchLanguageForChat(api, chatId, language, dependencies);
3717
+ if (!result.found) return {
3718
+ found: false,
3719
+ copy: result.copy,
3720
+ text: result.copy.language.expired,
3721
+ keyboard: buildLanguageKeyboard(await getChatLanguage(dependencies.sessionRepo, chatId), result.copy)
3722
+ };
3723
+ return {
3724
+ found: true,
3725
+ copy: result.copy,
3726
+ text: presentLanguageSwitchMessage(result.language, result.copy),
3727
+ keyboard: buildLanguageKeyboard(result.language, result.copy)
3728
+ };
3729
+ }
3730
+ function registerLanguageCommand(bot, dependencies) {
3731
+ bot.command("language", async (ctx) => {
3732
+ await handleLanguageCommand(ctx, dependencies);
3733
+ });
3734
+ }
3735
+ //#endregion
3736
+ //#region src/bot/commands/models.ts
3737
+ async function handleModelsCommand(ctx, dependencies) {
3738
+ const copy = await getChatCopy(dependencies.sessionRepo, ctx.chat.id);
3739
+ try {
3740
+ const result = await dependencies.listModelsUseCase.execute({ chatId: ctx.chat.id });
3741
+ if (result.models.length === 0) {
3742
+ await ctx.reply(copy.models.none);
3743
+ return;
3744
+ }
3745
+ const { keyboard, page } = buildModelsKeyboard(result.models, 0, copy);
3746
+ await ctx.reply(presentModelsMessage({
3747
+ currentModelId: result.currentModelId,
3748
+ currentModelProviderId: result.currentModelProviderId,
3749
+ currentModelVariant: result.currentModelVariant,
3750
+ models: result.models,
3751
+ page: page.page
3752
+ }, copy), { reply_markup: keyboard });
3753
+ } catch (error) {
3754
+ dependencies.logger.error({ error }, "failed to list models");
3755
+ await ctx.reply(presentError(error, copy));
3756
+ }
3757
+ }
3758
+ function registerModelsCommand(bot, dependencies) {
3759
+ bot.command(["model", "models"], async (ctx) => {
3760
+ await handleModelsCommand(ctx, dependencies);
3761
+ });
3762
+ }
3763
+ //#endregion
3764
+ //#region src/bot/commands/new.ts
3765
+ async function handleNewCommand(ctx, dependencies) {
3766
+ const copy = await getChatCopy(dependencies.sessionRepo, ctx.chat.id);
3767
+ try {
3768
+ const title = extractSessionTitle(ctx);
3769
+ const result = await dependencies.createSessionUseCase.execute({
3770
+ chatId: ctx.chat.id,
3771
+ title
3772
+ });
3773
+ await ctx.reply(presentSessionCreatedMessage(result.session, copy));
3774
+ } catch (error) {
3775
+ dependencies.logger.error({ error }, "failed to create new session");
3776
+ await ctx.reply(presentError(error, copy));
3777
+ }
3778
+ }
3779
+ function registerNewCommand(bot, dependencies) {
3780
+ bot.command("new", async (ctx) => {
3781
+ await handleNewCommand(ctx, dependencies);
3782
+ });
3783
+ }
3784
+ function extractSessionTitle(ctx) {
3785
+ if (typeof ctx.match === "string") {
3786
+ const title = ctx.match.trim();
3787
+ return title ? title : null;
3788
+ }
3789
+ const messageText = ctx.message?.text?.trim();
3790
+ if (!messageText) return null;
3791
+ const title = messageText.match(/^\/new(?:@\S+)?(?:\s+([\s\S]*))?$/i)?.[1]?.trim();
3792
+ return title ? title : null;
3793
+ }
3794
+ //#endregion
3747
3795
  //#region src/services/telegram/telegram-format.ts
3748
3796
  var MAX_TELEGRAM_MESSAGE_LENGTH = 4096;
3749
3797
  var TRUNCATED_SUFFIX = "...";
@@ -4077,142 +4125,6 @@ function escapeLinkDestination(url) {
4077
4125
  return url.replace(/\\/g, "\\\\").replace(/\)/g, "\\)").replace(/\(/g, "\\(");
4078
4126
  }
4079
4127
  //#endregion
4080
- //#region src/bot/presenters/static.presenter.ts
4081
- function presentStartMarkdownMessage(copy = BOT_COPY) {
4082
- return copy.start.lines.join("\n");
4083
- }
4084
- function presentHelpMarkdownMessage(copy = BOT_COPY) {
4085
- return copy.help.lines.join("\n");
4086
- }
4087
- //#endregion
4088
- //#region src/bot/commands/help.ts
4089
- async function handleHelpCommand(ctx, dependencies) {
4090
- const copy = await getChatCopy(dependencies.sessionRepo, ctx.chat?.id);
4091
- const reply = buildTelegramStaticReply(presentHelpMarkdownMessage(copy));
4092
- try {
4093
- await ctx.reply(reply.preferred.text, reply.preferred.options);
4094
- } catch (error) {
4095
- if (reply.preferred.options) {
4096
- dependencies.logger.error({ error }, "failed to send help markdown reply, falling back to plain text");
4097
- await ctx.reply(reply.fallback.text);
4098
- return;
4099
- }
4100
- dependencies.logger.error({ error }, "failed to show help message");
4101
- await ctx.reply(presentError(error, copy));
4102
- }
4103
- }
4104
- function registerHelpCommand(bot, dependencies) {
4105
- bot.command("help", async (ctx) => {
4106
- await handleHelpCommand(ctx, dependencies);
4107
- });
4108
- }
4109
- //#endregion
4110
- //#region src/bot/commands/language.ts
4111
- async function handleLanguageCommand(ctx, dependencies) {
4112
- const language = await getChatLanguage(dependencies.sessionRepo, ctx.chat.id);
4113
- const copy = await getChatCopy(dependencies.sessionRepo, ctx.chat.id);
4114
- try {
4115
- await syncTelegramCommandsForChat(ctx.api, ctx.chat.id, language);
4116
- await ctx.reply(presentLanguageMessage(language, copy), { reply_markup: buildLanguageKeyboard(language, copy) });
4117
- } catch (error) {
4118
- dependencies.logger.error({ error }, "failed to show language options");
4119
- await ctx.reply(presentError(error, copy));
4120
- }
4121
- }
4122
- async function switchLanguageForChat(api, chatId, language, dependencies) {
4123
- const currentCopy = await getChatCopy(dependencies.sessionRepo, chatId);
4124
- if (!isBotLanguage(language)) return {
4125
- found: false,
4126
- copy: currentCopy
4127
- };
4128
- await setChatLanguage(dependencies.sessionRepo, chatId, language);
4129
- await syncTelegramCommandsForChat(api, chatId, language);
4130
- return {
4131
- found: true,
4132
- copy: await getChatCopy(dependencies.sessionRepo, chatId),
4133
- language
4134
- };
4135
- }
4136
- async function presentLanguageSwitchForChat(chatId, api, language, dependencies) {
4137
- const result = await switchLanguageForChat(api, chatId, language, dependencies);
4138
- if (!result.found) return {
4139
- found: false,
4140
- copy: result.copy,
4141
- text: result.copy.language.expired,
4142
- keyboard: buildLanguageKeyboard(await getChatLanguage(dependencies.sessionRepo, chatId), result.copy)
4143
- };
4144
- return {
4145
- found: true,
4146
- copy: result.copy,
4147
- text: presentLanguageSwitchMessage(result.language, result.copy),
4148
- keyboard: buildLanguageKeyboard(result.language, result.copy)
4149
- };
4150
- }
4151
- function registerLanguageCommand(bot, dependencies) {
4152
- bot.command("language", async (ctx) => {
4153
- await handleLanguageCommand(ctx, dependencies);
4154
- });
4155
- }
4156
- //#endregion
4157
- //#region src/bot/commands/models.ts
4158
- async function handleModelsCommand(ctx, dependencies) {
4159
- const copy = await getChatCopy(dependencies.sessionRepo, ctx.chat.id);
4160
- try {
4161
- const result = await dependencies.listModelsUseCase.execute({ chatId: ctx.chat.id });
4162
- if (result.models.length === 0) {
4163
- await ctx.reply(copy.models.none);
4164
- return;
4165
- }
4166
- const { keyboard, page } = buildModelsKeyboard(result.models, 0, copy);
4167
- await ctx.reply(presentModelsMessage({
4168
- currentModelId: result.currentModelId,
4169
- currentModelProviderId: result.currentModelProviderId,
4170
- currentModelVariant: result.currentModelVariant,
4171
- models: result.models,
4172
- page: page.page
4173
- }, copy), { reply_markup: keyboard });
4174
- } catch (error) {
4175
- dependencies.logger.error({ error }, "failed to list models");
4176
- await ctx.reply(presentError(error, copy));
4177
- }
4178
- }
4179
- function registerModelsCommand(bot, dependencies) {
4180
- bot.command(["model", "models"], async (ctx) => {
4181
- await handleModelsCommand(ctx, dependencies);
4182
- });
4183
- }
4184
- //#endregion
4185
- //#region src/bot/commands/new.ts
4186
- async function handleNewCommand(ctx, dependencies) {
4187
- const copy = await getChatCopy(dependencies.sessionRepo, ctx.chat.id);
4188
- try {
4189
- const title = extractSessionTitle(ctx);
4190
- const result = await dependencies.createSessionUseCase.execute({
4191
- chatId: ctx.chat.id,
4192
- title
4193
- });
4194
- await ctx.reply(presentSessionCreatedMessage(result.session, copy));
4195
- } catch (error) {
4196
- dependencies.logger.error({ error }, "failed to create new session");
4197
- await ctx.reply(presentError(error, copy));
4198
- }
4199
- }
4200
- function registerNewCommand(bot, dependencies) {
4201
- bot.command("new", async (ctx) => {
4202
- await handleNewCommand(ctx, dependencies);
4203
- });
4204
- }
4205
- function extractSessionTitle(ctx) {
4206
- if (typeof ctx.match === "string") {
4207
- const title = ctx.match.trim();
4208
- return title ? title : null;
4209
- }
4210
- const messageText = ctx.message?.text?.trim();
4211
- if (!messageText) return null;
4212
- const title = messageText.match(/^\/new(?:@\S+)?(?:\s+([\s\S]*))?$/i)?.[1]?.trim();
4213
- return title ? title : null;
4214
- }
4215
- //#endregion
4216
4128
  //#region src/bot/commands/status.ts
4217
4129
  async function handleStatusCommand(ctx, dependencies) {
4218
4130
  const copy = await getChatCopy(dependencies.sessionRepo, ctx.chat?.id);
@@ -4253,6 +4165,11 @@ function registerSessionsCommand(bot, dependencies) {
4253
4165
  });
4254
4166
  }
4255
4167
  //#endregion
4168
+ //#region src/bot/presenters/static.presenter.ts
4169
+ function presentStartMarkdownMessage(copy = BOT_COPY) {
4170
+ return copy.start.lines.join("\n");
4171
+ }
4172
+ //#endregion
4256
4173
  //#region src/bot/commands/start.ts
4257
4174
  async function handleStartCommand(ctx, dependencies) {
4258
4175
  const copy = await getChatCopy(dependencies.sessionRepo, ctx.chat?.id);
@@ -4769,7 +4686,6 @@ function registerBot(bot, container, options) {
4769
4686
  bot.use(createLoggingMiddleware(container.logger));
4770
4687
  bot.use(createAuthMiddleware(options.telegramAllowedChatIds));
4771
4688
  registerStartCommand(bot, container);
4772
- registerHelpCommand(bot, container);
4773
4689
  registerStatusCommand(bot, container);
4774
4690
  registerNewCommand(bot, container);
4775
4691
  registerAgentsCommand(bot, container);