@grinev/opencode-telegram-bot 0.21.0 → 0.21.2

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.
Files changed (182) hide show
  1. package/.env.example +18 -2
  2. package/README.md +21 -8
  3. package/dist/app/{start-bot-app.js → bootstrap/start-bot-app.js} +16 -15
  4. package/dist/{bot/utils/assistant-run-footer.js → app/formatters/assistant-run-footer-formatter.js} +1 -1
  5. package/dist/{summary → app/formatters}/subagent-formatter.js +8 -3
  6. package/dist/{summary/formatter.js → app/formatters/summary-formatter.js} +4 -132
  7. package/dist/{summary → app/formatters}/tool-message-batcher.js +1 -1
  8. package/dist/{bot/assistant-run-state.js → app/managers/assistant-run-state-manager.js} +1 -1
  9. package/dist/{attach/manager.js → app/managers/attach-manager.js} +1 -1
  10. package/dist/{background-session/tracker.js → app/managers/background-session-manager.js} +2 -2
  11. package/dist/{scheduled-task/foreground-state.js → app/managers/foreground-session-state-manager.js} +1 -1
  12. package/dist/{interaction/manager.js → app/managers/interaction-manager.js} +31 -1
  13. package/dist/{permission/manager.js → app/managers/permission-manager.js} +1 -1
  14. package/dist/{question/manager.js → app/managers/question-manager.js} +1 -1
  15. package/dist/{rename/manager.js → app/managers/rename-manager.js} +1 -1
  16. package/dist/{scheduled-task/creation-manager.js → app/managers/scheduled-task-creation-manager.js} +2 -2
  17. package/dist/{summary/aggregator.js → app/managers/summary-aggregation-manager.js} +3 -3
  18. package/dist/{agent/manager.js → app/services/agent-selection-service.js} +4 -5
  19. package/dist/{attach/service.js → app/services/attach-service.js} +23 -44
  20. package/dist/{bot/utils/busy-reconciliation.js → app/services/busy-reconciliation-service.js} +12 -7
  21. package/dist/app/services/command-catalog-service.js +21 -0
  22. package/dist/{bot/utils/external-user-input.js → app/services/external-user-input-service.js} +4 -19
  23. package/dist/app/services/file-browser-service.js +265 -0
  24. package/dist/{bot/utils/file-download.js → app/services/file-download-service.js} +14 -28
  25. package/dist/app/services/mcp-catalog-service.js +79 -0
  26. package/dist/app/services/message-history-service.js +81 -0
  27. package/dist/{model/capabilities.js → app/services/model-capabilities-service.js} +2 -2
  28. package/dist/{model/context-limit.js → app/services/model-context-limit-service.js} +4 -4
  29. package/dist/{model/manager.js → app/services/model-selection-service.js} +4 -4
  30. package/dist/{project/manager.js → app/services/project-service.js} +3 -3
  31. package/dist/app/services/project-switch-service.js +39 -0
  32. package/dist/{bot/utils/busy-guard.js → app/services/run-control-service.js} +3 -14
  33. package/dist/{scheduled-task/executor.js → app/services/scheduled-task-executor-service.js} +5 -5
  34. package/dist/{scheduled-task/runtime.js → app/services/scheduled-task-runtime-service.js} +17 -56
  35. package/dist/{scheduled-task/schedule-parser.js → app/services/scheduled-task-schedule-parser-service.js} +3 -3
  36. package/dist/{scheduled-task/session-ignore.js → app/services/scheduled-task-session-ignore-service.js} +1 -1
  37. package/dist/{session/cache-manager.js → app/services/session-cache-service.js} +3 -3
  38. package/dist/{session/manager.js → app/services/session-service.js} +1 -1
  39. package/dist/app/services/skills-catalog-service.js +21 -0
  40. package/dist/{stt/client.js → app/services/stt-service.js} +2 -2
  41. package/dist/{tts/client.js → app/services/tts-service.js} +68 -5
  42. package/dist/{variant/manager.js → app/services/variant-selection-service.js} +3 -3
  43. package/dist/{scheduled-task/store.js → app/stores/scheduled-task-store.js} +3 -3
  44. package/dist/{settings/manager.js → app/stores/settings-store.js} +3 -3
  45. package/dist/app/types/worktree.js +1 -0
  46. package/dist/bot/{handlers/agent.js → callbacks/agent-selection-callback-handler.js} +8 -57
  47. package/dist/bot/callbacks/callback-router.js +110 -0
  48. package/dist/bot/{commands/commands.js → callbacks/command-catalog-callback-handler.js} +17 -197
  49. package/dist/bot/{handlers/context.js → callbacks/context-control-callback-handler.js} +3 -32
  50. package/dist/bot/callbacks/file-browser-callback-handler.js +219 -0
  51. package/dist/bot/callbacks/inline-menu-cancel-callback-handler.js +32 -0
  52. package/dist/bot/{commands/mcps.js → callbacks/mcp-catalog-callback-handler.js} +7 -172
  53. package/dist/bot/{commands/messages.js → callbacks/message-history-callback-handler.js} +17 -248
  54. package/dist/bot/{handlers/model.js → callbacks/model-selection-callback-handler.js} +10 -71
  55. package/dist/bot/callbacks/permission-callback-handler.js +114 -0
  56. package/dist/bot/callbacks/project-callback-handler.js +79 -0
  57. package/dist/bot/callbacks/question-callback-handler.js +159 -0
  58. package/dist/bot/{commands/rename.js → callbacks/rename-callback-handler.js} +6 -34
  59. package/dist/bot/{commands/tasklist.js → callbacks/scheduled-task-callback-handler.js} +83 -68
  60. package/dist/bot/{commands/sessions.js → callbacks/session-callback-handler.js} +19 -158
  61. package/dist/bot/{commands/skills.js → callbacks/skills-catalog-callback-handler.js} +8 -188
  62. package/dist/bot/{handlers/variant.js → callbacks/variant-selection-callback-handler.js} +7 -69
  63. package/dist/bot/callbacks/worktree-callback-handler.js +97 -0
  64. package/dist/bot/commands/{abort.js → abort-command.js} +6 -6
  65. package/dist/bot/commands/command-catalog-command.js +42 -0
  66. package/dist/bot/commands/{detach.js → detach-command.js} +8 -8
  67. package/dist/bot/commands/ls-command.js +48 -0
  68. package/dist/bot/commands/mcp-catalog-command.js +39 -0
  69. package/dist/bot/commands/messages-command.js +59 -0
  70. package/dist/bot/commands/{new.js → new-command.js} +12 -11
  71. package/dist/bot/commands/open-command.js +45 -0
  72. package/dist/bot/commands/{opencode-start.js → opencode-start-command.js} +1 -1
  73. package/dist/bot/commands/{opencode-stop.js → opencode-stop-command.js} +1 -1
  74. package/dist/bot/commands/projects-command.js +32 -0
  75. package/dist/bot/commands/rename-command.js +33 -0
  76. package/dist/bot/commands/sessions-command.js +42 -0
  77. package/dist/bot/commands/skills-catalog-command.js +42 -0
  78. package/dist/bot/commands/{start.js → start-command.js} +12 -12
  79. package/dist/bot/commands/{status.js → status-command.js} +9 -9
  80. package/dist/bot/commands/{task.js → task-command.js} +9 -81
  81. package/dist/bot/commands/tasklist-command.js +40 -0
  82. package/dist/bot/commands/{tts.js → tts-command.js} +2 -2
  83. package/dist/bot/commands/worktree-command.js +47 -0
  84. package/dist/bot/handlers/{document.js → document-handler.js} +3 -3
  85. package/dist/bot/handlers/{media-group.js → media-group-handler.js} +3 -3
  86. package/dist/bot/handlers/photo-handler.js +44 -0
  87. package/dist/bot/handlers/prompt.js +16 -16
  88. package/dist/bot/handlers/text-message-handler.js +61 -0
  89. package/dist/bot/handlers/tts-response-handler.js +29 -0
  90. package/dist/bot/handlers/{voice.js → voice-handler.js} +2 -2
  91. package/dist/bot/index.js +27 -1130
  92. package/dist/{keyboard/manager.js → bot/keyboards/keyboard-manager.js} +6 -6
  93. package/dist/bot/keyboards/keyboard-types.js +1 -0
  94. package/dist/bot/{utils/keyboard.js → keyboards/main-reply-keyboard.js} +2 -2
  95. package/dist/bot/menus/agent-selection-menu.js +54 -0
  96. package/dist/bot/menus/command-catalog-menu.js +101 -0
  97. package/dist/bot/menus/context-control-menu.js +33 -0
  98. package/dist/bot/menus/file-browser-menu.js +265 -0
  99. package/dist/bot/{handlers → menus}/inline-menu.js +4 -33
  100. package/dist/bot/menus/mcp-catalog-menu.js +97 -0
  101. package/dist/bot/menus/message-history-menu.js +107 -0
  102. package/dist/bot/menus/model-selection-menu.js +66 -0
  103. package/dist/bot/menus/permission-menu.js +116 -0
  104. package/dist/bot/{commands/projects.js → menus/project-selection-menu.js} +5 -105
  105. package/dist/bot/{handlers/question.js → menus/question-menu.js} +10 -166
  106. package/dist/bot/menus/rename-menu.js +6 -0
  107. package/dist/bot/menus/scheduled-task-menu.js +42 -0
  108. package/dist/bot/menus/session-selection-menu.js +115 -0
  109. package/dist/bot/menus/skills-catalog-menu.js +99 -0
  110. package/dist/bot/menus/variant-selection-menu.js +67 -0
  111. package/dist/bot/menus/worktree-selection-menu.js +76 -0
  112. package/dist/bot/{utils → messages}/assistant-rendering.js +2 -2
  113. package/dist/bot/messages/busy-blocked-renderer.js +11 -0
  114. package/dist/bot/messages/external-user-input-notification.js +22 -0
  115. package/dist/bot/messages/scheduled-task-delivery.js +63 -0
  116. package/dist/bot/{utils → messages}/send-downloaded-file.js +1 -1
  117. package/dist/bot/messages/summary-message-formatter.js +130 -0
  118. package/dist/bot/{utils → messages}/telegram-text.js +60 -0
  119. package/dist/{interaction/guard.js → bot/middleware/interaction-guard-decision.js} +11 -4
  120. package/dist/bot/middleware/interaction-guard.js +2 -2
  121. package/dist/bot/middleware/unknown-command.js +1 -1
  122. package/dist/{pinned/format.js → bot/pinned/pinned-message-format.js} +1 -2
  123. package/dist/{pinned/manager.js → bot/pinned/pinned-message-manager.js} +10 -10
  124. package/dist/bot/pinned/pinned-message-types.js +1 -0
  125. package/dist/{summary → bot/render}/markdown-to-telegram-v2.js +2 -2
  126. package/dist/bot/render/types.js +1 -0
  127. package/dist/bot/routers/command-router.js +73 -0
  128. package/dist/bot/routers/message-router.js +150 -0
  129. package/dist/bot/services/attach-presentation.js +40 -0
  130. package/dist/bot/services/event-subscription-service.js +842 -0
  131. package/dist/bot/services/project-switch-presentation.js +26 -0
  132. package/dist/bot/streaming/response-streamer.js +18 -2
  133. package/dist/cli.js +4 -4
  134. package/dist/config.js +21 -3
  135. package/dist/i18n/ar.js +491 -0
  136. package/dist/i18n/index.js +7 -0
  137. package/dist/index.js +1 -1
  138. package/dist/opencode/ready-refresh.js +2 -2
  139. package/dist/{service → runtime/service}/manager.js +2 -2
  140. package/dist/runtime/service/types.js +1 -0
  141. package/package.json +1 -1
  142. package/dist/bot/commands/ls.js +0 -445
  143. package/dist/bot/commands/open.js +0 -319
  144. package/dist/bot/commands/worktree.js +0 -201
  145. package/dist/bot/handlers/permission.js +0 -235
  146. package/dist/bot/utils/browser-roots.js +0 -140
  147. package/dist/bot/utils/file-tree.js +0 -92
  148. package/dist/bot/utils/send-tts-response.js +0 -37
  149. package/dist/bot/utils/switch-project.js +0 -45
  150. package/dist/bot/utils/telegram-file-url.js +0 -11
  151. package/dist/interaction/busy.js +0 -8
  152. package/dist/interaction/cleanup.js +0 -32
  153. /package/dist/{scheduled-task/display.js → app/formatters/scheduled-task-display-formatter.js} +0 -0
  154. /package/dist/{bot/utils/abort-error-suppression.js → app/managers/abort-suppression-manager.js} +0 -0
  155. /package/dist/{external-input/suppression.js → app/managers/external-input-suppression-manager.js} +0 -0
  156. /package/dist/{scheduled-task/next-run.js → app/services/scheduled-task-next-run-service.js} +0 -0
  157. /package/dist/{git/worktree.js → app/services/worktree-service.js} +0 -0
  158. /package/dist/{agent/types.js → app/types/agent.js} +0 -0
  159. /package/dist/{interaction/types.js → app/types/interaction.js} +0 -0
  160. /package/dist/{model/types.js → app/types/model.js} +0 -0
  161. /package/dist/{keyboard/types.js → app/types/permission.js} +0 -0
  162. /package/dist/{permission/types.js → app/types/project.js} +0 -0
  163. /package/dist/{pinned/types.js → app/types/question.js} +0 -0
  164. /package/dist/{scheduled-task/types.js → app/types/scheduled-task.js} +0 -0
  165. /package/dist/{question/types.js → app/types/session.js} +0 -0
  166. /package/dist/{service/types.js → app/types/settings.js} +0 -0
  167. /package/dist/{telegram/render/types.js → app/types/summary.js} +0 -0
  168. /package/dist/{variant/types.js → app/types/variant.js} +0 -0
  169. /package/dist/bot/commands/{help.js → help-command.js} +0 -0
  170. /package/dist/bot/{utils → messages}/send-with-markdown-fallback.js +0 -0
  171. /package/dist/bot/{utils → messages}/thinking-message.js +0 -0
  172. /package/dist/{telegram → bot}/render/block-fallback.js +0 -0
  173. /package/dist/{telegram → bot}/render/block-parser.js +0 -0
  174. /package/dist/{telegram → bot}/render/block-renderer.js +0 -0
  175. /package/dist/{telegram → bot}/render/chunker.js +0 -0
  176. /package/dist/{telegram → bot}/render/inline-renderer.js +0 -0
  177. /package/dist/{telegram → bot}/render/markdown-normalizer.js +0 -0
  178. /package/dist/{telegram → bot}/render/pipeline.js +0 -0
  179. /package/dist/{telegram → bot}/render/validator.js +0 -0
  180. /package/dist/bot/{utils/commands.js → routers/command-utils.js} +0 -0
  181. /package/dist/bot/{utils → streaming}/finalize-assistant-response.js +0 -0
  182. /package/dist/{service/runtime.js → runtime/service/env.js} +0 -0
@@ -0,0 +1,26 @@
1
+ import { keyboardManager } from "../keyboards/keyboard-manager.js";
2
+ import { createMainKeyboard } from "../keyboards/main-reply-keyboard.js";
3
+ import { pinnedMessageManager } from "../pinned/pinned-message-manager.js";
4
+ export function createProjectSwitchPresentation() {
5
+ return {
6
+ async clearPinnedMessage() {
7
+ await pinnedMessageManager.clear();
8
+ },
9
+ initializeKeyboard(ctx) {
10
+ if (ctx.chat) {
11
+ keyboardManager.initialize(ctx.api, ctx.chat.id);
12
+ }
13
+ },
14
+ async refreshContextLimit() {
15
+ await pinnedMessageManager.refreshContextLimit();
16
+ return pinnedMessageManager.getContextLimit();
17
+ },
18
+ updateKeyboardContext(contextInfo) {
19
+ keyboardManager.updateContext(contextInfo.tokensUsed, contextInfo.tokensLimit);
20
+ },
21
+ updateKeyboardAgent(agent) {
22
+ keyboardManager.updateAgent(agent);
23
+ },
24
+ createMainKeyboard,
25
+ };
26
+ }
@@ -56,12 +56,14 @@ export class ResponseStreamer {
56
56
  sendPart;
57
57
  editPart;
58
58
  deleteText;
59
+ completePart;
59
60
  states = new Map();
60
61
  constructor(options) {
61
62
  this.throttleMs = Math.max(0, Math.floor(options.throttleMs));
62
63
  this.sendPart = options.sendPart;
63
64
  this.editPart = options.editPart;
64
65
  this.deleteText = options.deleteText;
66
+ this.completePart = options.completePart;
65
67
  }
66
68
  enqueue(sessionId, messageId, payload) {
67
69
  const normalizedPayload = normalizePayload(payload);
@@ -105,8 +107,22 @@ export class ResponseStreamer {
105
107
  let synced = true;
106
108
  if (options?.flushFinal !== false) {
107
109
  synced = await this.enqueueTask(state, () => this.flushState(state, "complete"));
108
- if (!synced && state.isBroken) {
109
- await this.cleanupBrokenStream(state, "final_sync_failed_cleanup");
110
+ }
111
+ if (synced && this.completePart && state.latestPayload) {
112
+ try {
113
+ const realMessageIds = [];
114
+ for (const part of state.latestPayload.parts) {
115
+ if (!part.text) {
116
+ continue;
117
+ }
118
+ const result = await this.completePart(part, state.latestPayload.sendOptions);
119
+ realMessageIds.push(result.messageId);
120
+ }
121
+ state.telegramMessageIds = realMessageIds;
122
+ }
123
+ catch (error) {
124
+ logger.error(`[ResponseStreamer] Failed to persist draft message: session=${sessionId}, message=${messageId}`, error);
125
+ synced = false;
110
126
  }
111
127
  }
112
128
  const messageIds = [...state.telegramMessageIds];
package/dist/cli.js CHANGED
@@ -81,7 +81,7 @@ async function runStartCommand(mode, daemon) {
81
81
  const { ensureRuntimeConfigForStart } = await import("./runtime/bootstrap.js");
82
82
  await ensureRuntimeConfigForStart();
83
83
  if (daemon) {
84
- const { startBotDaemon } = await import("./service/manager.js");
84
+ const { startBotDaemon } = await import("./runtime/service/manager.js");
85
85
  const result = await startBotDaemon(modeResult.mode);
86
86
  const cleanupMessage = formatServiceCleanupMessage(result.cleanupReason);
87
87
  const runtimePaths = getRuntimePaths();
@@ -115,7 +115,7 @@ async function runStartCommand(mode, daemon) {
115
115
  }
116
116
  const { initializeLogger } = await import("./utils/logger.js");
117
117
  await initializeLogger();
118
- const { startBotApp } = await import("./app/start-bot-app.js");
118
+ const { startBotApp } = await import("./app/bootstrap/start-bot-app.js");
119
119
  await startBotApp();
120
120
  return EXIT_SUCCESS;
121
121
  }
@@ -129,7 +129,7 @@ async function runConfigCommand() {
129
129
  }
130
130
  async function runStatusCommand() {
131
131
  setRuntimeMode("installed");
132
- const { getBotServiceStatus } = await import("./service/manager.js");
132
+ const { getBotServiceStatus } = await import("./runtime/service/manager.js");
133
133
  const runtimePaths = getRuntimePaths();
134
134
  const status = await getBotServiceStatus();
135
135
  writeOptionalLine(formatServiceCleanupMessage(status.cleanupReason));
@@ -150,7 +150,7 @@ async function runStatusCommand() {
150
150
  }
151
151
  async function runStopCommand() {
152
152
  setRuntimeMode("installed");
153
- const { stopBotDaemon } = await import("./service/manager.js");
153
+ const { stopBotDaemon } = await import("./runtime/service/manager.js");
154
154
  const result = await stopBotDaemon();
155
155
  writeOptionalLine(formatServiceCleanupMessage(result.cleanupReason));
156
156
  if (!result.success) {
package/dist/config.js CHANGED
@@ -39,6 +39,17 @@ function getOptionalBooleanEnvVar(key, defaultValue) {
39
39
  }
40
40
  return defaultValue;
41
41
  }
42
+ function getOptionalStreamingModeEnvVar(key, defaultValue) {
43
+ const value = getEnvVar(key, false);
44
+ if (!value) {
45
+ return defaultValue;
46
+ }
47
+ const normalized = value.trim().toLowerCase();
48
+ if (normalized === "edit" || normalized === "draft") {
49
+ return normalized;
50
+ }
51
+ return defaultValue;
52
+ }
42
53
  function getOptionalMessageFormatModeEnvVar(key, defaultValue) {
43
54
  const value = getEnvVar(key, false);
44
55
  if (!value) {
@@ -50,7 +61,7 @@ function getOptionalMessageFormatModeEnvVar(key, defaultValue) {
50
61
  }
51
62
  return defaultValue;
52
63
  }
53
- const VALID_TTS_PROVIDERS = ["openai", "google"];
64
+ const VALID_TTS_PROVIDERS = ["openai", "google", "elevenlabs"];
54
65
  function getOptionalTtsProviderEnvVar(key, defaultValue) {
55
66
  const value = getEnvVar(key, false);
56
67
  if (!value) {
@@ -110,7 +121,9 @@ export const config = {
110
121
  commandsListLimit: getOptionalPositiveIntEnvVar("COMMANDS_LIST_LIMIT", 10),
111
122
  taskLimit: getOptionalPositiveIntEnvVar("TASK_LIMIT", 10),
112
123
  scheduledTaskExecutionTimeoutMinutes: getOptionalPositiveIntEnvVar("SCHEDULED_TASK_EXECUTION_TIMEOUT_MINUTES", 120),
124
+ scheduledTaskNotificationsSilent: getOptionalBooleanEnvVar("SCHEDULED_TASK_DISABLE_NOTIFICATION", false),
113
125
  responseStreamThrottleMs: getOptionalPositiveIntEnvVar("RESPONSE_STREAM_THROTTLE_MS", 1000),
126
+ responseStreamingMode: getOptionalStreamingModeEnvVar("RESPONSE_STREAMING_MODE", "edit"),
114
127
  bashToolDisplayMaxLength: getOptionalPositiveIntEnvVar("BASH_TOOL_DISPLAY_MAX_LENGTH", 128),
115
128
  locale: getOptionalLocaleEnvVar("BOT_LOCALE", "en"),
116
129
  hideThinkingMessages: getOptionalBooleanEnvVar("HIDE_THINKING_MESSAGES", false),
@@ -134,12 +147,17 @@ export const config = {
134
147
  },
135
148
  tts: (() => {
136
149
  const provider = getOptionalTtsProviderEnvVar("TTS_PROVIDER", "openai");
137
- const defaultVoice = provider === "google" ? "en-US-Studio-O" : "alloy";
150
+ const defaultVoice = provider === "google"
151
+ ? "en-US-Studio-O"
152
+ : provider === "elevenlabs"
153
+ ? "21m00Tcm4TlvDq8ikWAM"
154
+ : "alloy";
155
+ const defaultModel = provider === "elevenlabs" ? "eleven_flash_v2_5" : "gpt-4o-mini-tts";
138
156
  return {
139
157
  apiUrl: getEnvVar("TTS_API_URL", false),
140
158
  apiKey: getEnvVar("TTS_API_KEY", false),
141
159
  provider,
142
- model: getEnvVar("TTS_MODEL", false) || "gpt-4o-mini-tts",
160
+ model: getEnvVar("TTS_MODEL", false) || defaultModel,
143
161
  voice: getEnvVar("TTS_VOICE", false) || defaultVoice,
144
162
  };
145
163
  })(),