zardbot-telegram 1.0.0

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 (111) hide show
  1. package/.env.example +116 -0
  2. package/LICENSE +21 -0
  3. package/README.md +250 -0
  4. package/dist/agent/manager.js +88 -0
  5. package/dist/agent/types.js +26 -0
  6. package/dist/app/start-bot-app.js +49 -0
  7. package/dist/bot/commands/abort.js +121 -0
  8. package/dist/bot/commands/commands.js +480 -0
  9. package/dist/bot/commands/definitions.js +27 -0
  10. package/dist/bot/commands/help.js +10 -0
  11. package/dist/bot/commands/models.js +38 -0
  12. package/dist/bot/commands/new.js +70 -0
  13. package/dist/bot/commands/opencode-start.js +101 -0
  14. package/dist/bot/commands/opencode-stop.js +44 -0
  15. package/dist/bot/commands/projects.js +223 -0
  16. package/dist/bot/commands/rename.js +139 -0
  17. package/dist/bot/commands/sessions.js +351 -0
  18. package/dist/bot/commands/start.js +43 -0
  19. package/dist/bot/commands/status.js +95 -0
  20. package/dist/bot/commands/task.js +399 -0
  21. package/dist/bot/commands/tasklist.js +220 -0
  22. package/dist/bot/commands/voice.js +145 -0
  23. package/dist/bot/handlers/agent.js +118 -0
  24. package/dist/bot/handlers/context.js +100 -0
  25. package/dist/bot/handlers/document.js +65 -0
  26. package/dist/bot/handlers/inline-menu.js +119 -0
  27. package/dist/bot/handlers/model.js +143 -0
  28. package/dist/bot/handlers/permission.js +235 -0
  29. package/dist/bot/handlers/prompt.js +240 -0
  30. package/dist/bot/handlers/question.js +390 -0
  31. package/dist/bot/handlers/tts.js +89 -0
  32. package/dist/bot/handlers/variant.js +138 -0
  33. package/dist/bot/handlers/voice.js +173 -0
  34. package/dist/bot/index.js +977 -0
  35. package/dist/bot/message-patterns.js +4 -0
  36. package/dist/bot/middleware/auth.js +30 -0
  37. package/dist/bot/middleware/interaction-guard.js +95 -0
  38. package/dist/bot/middleware/unknown-command.js +22 -0
  39. package/dist/bot/streaming/response-streamer.js +286 -0
  40. package/dist/bot/streaming/tool-call-streamer.js +285 -0
  41. package/dist/bot/utils/busy-guard.js +15 -0
  42. package/dist/bot/utils/commands.js +21 -0
  43. package/dist/bot/utils/file-download.js +91 -0
  44. package/dist/bot/utils/finalize-assistant-response.js +52 -0
  45. package/dist/bot/utils/keyboard.js +69 -0
  46. package/dist/bot/utils/send-with-markdown-fallback.js +165 -0
  47. package/dist/bot/utils/telegram-text.js +28 -0
  48. package/dist/bot/utils/thinking-message.js +8 -0
  49. package/dist/cli/args.js +98 -0
  50. package/dist/cli.js +80 -0
  51. package/dist/config.js +97 -0
  52. package/dist/i18n/de.js +357 -0
  53. package/dist/i18n/en.js +357 -0
  54. package/dist/i18n/es.js +357 -0
  55. package/dist/i18n/fr.js +357 -0
  56. package/dist/i18n/index.js +109 -0
  57. package/dist/i18n/ru.js +357 -0
  58. package/dist/i18n/zh.js +357 -0
  59. package/dist/index.js +26 -0
  60. package/dist/interaction/busy.js +8 -0
  61. package/dist/interaction/cleanup.js +32 -0
  62. package/dist/interaction/guard.js +140 -0
  63. package/dist/interaction/manager.js +106 -0
  64. package/dist/interaction/types.js +1 -0
  65. package/dist/keyboard/manager.js +172 -0
  66. package/dist/keyboard/types.js +1 -0
  67. package/dist/model/capabilities.js +62 -0
  68. package/dist/model/context-limit.js +57 -0
  69. package/dist/model/manager.js +259 -0
  70. package/dist/model/types.js +24 -0
  71. package/dist/opencode/client.js +13 -0
  72. package/dist/opencode/events.js +140 -0
  73. package/dist/permission/manager.js +100 -0
  74. package/dist/permission/types.js +1 -0
  75. package/dist/pinned/format.js +29 -0
  76. package/dist/pinned/manager.js +682 -0
  77. package/dist/pinned/types.js +1 -0
  78. package/dist/process/manager.js +273 -0
  79. package/dist/process/types.js +1 -0
  80. package/dist/project/manager.js +88 -0
  81. package/dist/question/manager.js +176 -0
  82. package/dist/question/types.js +1 -0
  83. package/dist/rename/manager.js +53 -0
  84. package/dist/runtime/bootstrap.js +350 -0
  85. package/dist/runtime/mode.js +74 -0
  86. package/dist/runtime/paths.js +37 -0
  87. package/dist/scheduled-task/creation-manager.js +113 -0
  88. package/dist/scheduled-task/display.js +239 -0
  89. package/dist/scheduled-task/executor.js +87 -0
  90. package/dist/scheduled-task/foreground-state.js +32 -0
  91. package/dist/scheduled-task/next-run.js +207 -0
  92. package/dist/scheduled-task/runtime.js +368 -0
  93. package/dist/scheduled-task/schedule-parser.js +169 -0
  94. package/dist/scheduled-task/store.js +65 -0
  95. package/dist/scheduled-task/types.js +19 -0
  96. package/dist/session/cache-manager.js +455 -0
  97. package/dist/session/manager.js +10 -0
  98. package/dist/settings/manager.js +158 -0
  99. package/dist/stt/client.js +97 -0
  100. package/dist/summary/aggregator.js +1136 -0
  101. package/dist/summary/formatter.js +491 -0
  102. package/dist/summary/subagent-formatter.js +63 -0
  103. package/dist/summary/tool-message-batcher.js +90 -0
  104. package/dist/tts/client.js +130 -0
  105. package/dist/utils/error-format.js +29 -0
  106. package/dist/utils/logger.js +127 -0
  107. package/dist/utils/safe-background-task.js +33 -0
  108. package/dist/utils/telegram-rate-limit-retry.js +93 -0
  109. package/dist/variant/manager.js +103 -0
  110. package/dist/variant/types.js +1 -0
  111. package/package.json +79 -0
@@ -0,0 +1,97 @@
1
+ import { config } from "../config.js";
2
+ import { logger } from "../utils/logger.js";
3
+ import { execSync } from "node:child_process";
4
+ import { tmpdir } from "node:os";
5
+ import { join } from "node:path";
6
+ import { unlinkSync, writeFileSync, readFileSync } from "node:fs";
7
+ const STT_REQUEST_TIMEOUT_MS = 60_000;
8
+ function convertToWav(audioBuffer, filename) {
9
+ const ext = filename.split(".").pop()?.toLowerCase();
10
+ if (ext === "wav" || ext === "wave") {
11
+ return audioBuffer;
12
+ }
13
+ const inputPath = join(tmpdir(), `stt_input_${Date.now()}.${ext}`);
14
+ const outputPath = join(tmpdir(), `stt_output_${Date.now()}.wav`);
15
+ try {
16
+ writeFileSync(inputPath, audioBuffer);
17
+ execSync(`ffmpeg -y -i "${inputPath}" -ar 16000 -ac 1 -f wav "${outputPath}"`, {
18
+ stdio: "pipe",
19
+ });
20
+ return readFileSync(outputPath);
21
+ }
22
+ finally {
23
+ try {
24
+ unlinkSync(inputPath);
25
+ }
26
+ catch { }
27
+ try {
28
+ unlinkSync(outputPath);
29
+ }
30
+ catch { }
31
+ }
32
+ }
33
+ /**
34
+ * Returns true if STT is configured (API URL and API key are set).
35
+ */
36
+ export function isSttConfigured() {
37
+ return Boolean(config.stt.apiUrl && config.stt.apiKey);
38
+ }
39
+ /**
40
+ * Transcribes an audio buffer using a Whisper-compatible API (OpenAI / Groq / etc.).
41
+ *
42
+ * Sends a multipart/form-data POST to `{STT_API_URL}/audio/transcriptions`.
43
+ *
44
+ * @param audioBuffer - Raw audio file bytes (ogg, mp3, wav, m4a, webm, etc.)
45
+ * @param filename - Original filename with extension (used by the API to detect format)
46
+ * @returns Transcribed text
47
+ * @throws Error if STT is not configured, the request fails, or the response is invalid
48
+ */
49
+ export async function transcribeAudio(audioBufferInput, filename) {
50
+ if (!isSttConfigured()) {
51
+ throw new Error("STT is not configured: STT_API_URL and STT_API_KEY are required");
52
+ }
53
+ const url = `${config.stt.apiUrl}/audio/transcriptions`;
54
+ const audioBuffer = convertToWav(audioBufferInput, filename);
55
+ const wavFilename = filename.replace(/\.[^.]+$/, ".wav");
56
+ const formData = new FormData();
57
+ formData.append("file", new Blob([new Uint8Array(audioBuffer)]), wavFilename);
58
+ if (config.stt.model) {
59
+ formData.append("model", config.stt.model);
60
+ }
61
+ formData.append("response_format", "json");
62
+ if (config.stt.language) {
63
+ formData.append("language", config.stt.language);
64
+ }
65
+ logger.debug(`[STT] Sending transcription request: url=${url}, model=${config.stt.model}, filename=${filename}, size=${audioBuffer.length} bytes`);
66
+ const controller = new AbortController();
67
+ const timeout = setTimeout(() => controller.abort(), STT_REQUEST_TIMEOUT_MS);
68
+ try {
69
+ const response = await fetch(url, {
70
+ method: "POST",
71
+ headers: {
72
+ Authorization: `Bearer ${config.stt.apiKey}`,
73
+ },
74
+ body: formData,
75
+ signal: controller.signal,
76
+ });
77
+ if (!response.ok) {
78
+ const errorBody = await response.text().catch(() => "");
79
+ throw new Error(`STT API returned HTTP ${response.status}: ${errorBody || response.statusText}`);
80
+ }
81
+ const data = (await response.json());
82
+ if (typeof data.text !== "string") {
83
+ throw new Error("STT API response does not contain a text field");
84
+ }
85
+ logger.debug(`[STT] Transcription result: ${data.text.length} chars`);
86
+ return { text: data.text };
87
+ }
88
+ catch (err) {
89
+ if (err instanceof DOMException && err.name === "AbortError") {
90
+ throw new Error(`STT request timed out after ${STT_REQUEST_TIMEOUT_MS}ms`);
91
+ }
92
+ throw err;
93
+ }
94
+ finally {
95
+ clearTimeout(timeout);
96
+ }
97
+ }