@4via6/relay 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 (99) hide show
  1. package/.env.example +50 -0
  2. package/README.md +253 -0
  3. package/dist/auth.d.ts +3 -0
  4. package/dist/auth.js +32 -0
  5. package/dist/auth.js.map +1 -0
  6. package/dist/bot.d.ts +2 -0
  7. package/dist/bot.js +14 -0
  8. package/dist/bot.js.map +1 -0
  9. package/dist/cli.d.ts +2 -0
  10. package/dist/cli.js +3 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/commands/admin.d.ts +2 -0
  13. package/dist/commands/admin.js +420 -0
  14. package/dist/commands/admin.js.map +1 -0
  15. package/dist/commands/chat.d.ts +2 -0
  16. package/dist/commands/chat.js +80 -0
  17. package/dist/commands/chat.js.map +1 -0
  18. package/dist/commands/files.d.ts +2 -0
  19. package/dist/commands/files.js +162 -0
  20. package/dist/commands/files.js.map +1 -0
  21. package/dist/commands/history.d.ts +2 -0
  22. package/dist/commands/history.js +152 -0
  23. package/dist/commands/history.js.map +1 -0
  24. package/dist/commands/index.d.ts +2 -0
  25. package/dist/commands/index.js +21 -0
  26. package/dist/commands/index.js.map +1 -0
  27. package/dist/commands/mcp.d.ts +2 -0
  28. package/dist/commands/mcp.js +105 -0
  29. package/dist/commands/mcp.js.map +1 -0
  30. package/dist/commands/media.d.ts +2 -0
  31. package/dist/commands/media.js +248 -0
  32. package/dist/commands/media.js.map +1 -0
  33. package/dist/commands/monitor.d.ts +2 -0
  34. package/dist/commands/monitor.js +136 -0
  35. package/dist/commands/monitor.js.map +1 -0
  36. package/dist/commands/session.d.ts +2 -0
  37. package/dist/commands/session.js +114 -0
  38. package/dist/commands/session.js.map +1 -0
  39. package/dist/commands/shell.d.ts +2 -0
  40. package/dist/commands/shell.js +90 -0
  41. package/dist/commands/shell.js.map +1 -0
  42. package/dist/index.d.ts +1 -0
  43. package/dist/index.js +82 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/providers/claude.d.ts +52 -0
  46. package/dist/providers/claude.js +449 -0
  47. package/dist/providers/claude.js.map +1 -0
  48. package/dist/providers/codex.d.ts +45 -0
  49. package/dist/providers/codex.js +400 -0
  50. package/dist/providers/codex.js.map +1 -0
  51. package/dist/providers/index.d.ts +6 -0
  52. package/dist/providers/index.js +40 -0
  53. package/dist/providers/index.js.map +1 -0
  54. package/dist/providers/opencode.d.ts +40 -0
  55. package/dist/providers/opencode.js +498 -0
  56. package/dist/providers/opencode.js.map +1 -0
  57. package/dist/providers/types.d.ts +173 -0
  58. package/dist/providers/types.js +6 -0
  59. package/dist/providers/types.js.map +1 -0
  60. package/dist/session.d.ts +10 -0
  61. package/dist/session.js +65 -0
  62. package/dist/session.js.map +1 -0
  63. package/dist/utils/chunker.d.ts +1 -0
  64. package/dist/utils/chunker.js +24 -0
  65. package/dist/utils/chunker.js.map +1 -0
  66. package/dist/utils/errors.d.ts +12 -0
  67. package/dist/utils/errors.js +85 -0
  68. package/dist/utils/errors.js.map +1 -0
  69. package/dist/utils/files.d.ts +15 -0
  70. package/dist/utils/files.js +81 -0
  71. package/dist/utils/files.js.map +1 -0
  72. package/dist/utils/html.d.ts +4 -0
  73. package/dist/utils/html.js +10 -0
  74. package/dist/utils/html.js.map +1 -0
  75. package/dist/utils/media.d.ts +15 -0
  76. package/dist/utils/media.js +103 -0
  77. package/dist/utils/media.js.map +1 -0
  78. package/dist/utils/store.d.ts +15 -0
  79. package/dist/utils/store.js +44 -0
  80. package/dist/utils/store.js.map +1 -0
  81. package/dist/utils/stream.d.ts +21 -0
  82. package/dist/utils/stream.js +149 -0
  83. package/dist/utils/stream.js.map +1 -0
  84. package/dist/utils/stt.d.ts +7 -0
  85. package/dist/utils/stt.js +118 -0
  86. package/dist/utils/stt.js.map +1 -0
  87. package/dist/utils/system-prompt.d.ts +5 -0
  88. package/dist/utils/system-prompt.js +64 -0
  89. package/dist/utils/system-prompt.js.map +1 -0
  90. package/dist/utils/timeout.d.ts +2 -0
  91. package/dist/utils/timeout.js +18 -0
  92. package/dist/utils/timeout.js.map +1 -0
  93. package/docs/commands.md +351 -0
  94. package/docs/configuration.md +160 -0
  95. package/docs/features.md +443 -0
  96. package/docs/getting-started.md +102 -0
  97. package/docs/providers.md +236 -0
  98. package/docs/troubleshooting.md +287 -0
  99. package/package.json +54 -0
@@ -0,0 +1,420 @@
1
+ import { InputFile } from "grammy";
2
+ import { getProvider, getProviderName } from "../providers/index.js";
3
+ import { setSelectedModel, getSelectedModel } from "../session.js";
4
+ import { chunkMessage } from "../utils/chunker.js";
5
+ import { getSttProvider } from "../utils/stt.js";
6
+ import { isStreamingEnabled } from "../utils/stream.js";
7
+ import { getSystemPrompt, reloadSystemPrompt, isUsingCustomPrompt } from "../utils/system-prompt.js";
8
+ import { formatCatchError } from "../utils/errors.js";
9
+ import { escapeHtml } from "../utils/html.js";
10
+ export function registerAdminCommands(bot) {
11
+ bot.command("health", async (ctx) => {
12
+ try {
13
+ const provider = getProvider();
14
+ const health = await provider.getHealth();
15
+ const streaming = isStreamingEnabled() ? "Enabled" : "Disabled";
16
+ const sttProvider = getSttProvider();
17
+ const stt = sttProvider ? `${sttProvider}` : "Not configured";
18
+ const prompt = getSystemPrompt();
19
+ const promptSource = isUsingCustomPrompt() ? "Custom" : "Default";
20
+ const model = getSelectedModel();
21
+ const modelStr = model
22
+ ? `${model.providerID}/${model.modelID}`
23
+ : health.model ?? "Server default";
24
+ // Check reasoning capability for current model
25
+ let reasoningBadge = "";
26
+ try {
27
+ const models = await provider.listModels();
28
+ const activeModel = model
29
+ ? models.find(m => m.id === model.modelID && m.provider === model.providerID)
30
+ : models.find(m => m.active);
31
+ if (activeModel?.reasoning) {
32
+ reasoningBadge = " [reasoning]";
33
+ }
34
+ }
35
+ catch {
36
+ // Ignore — optional info
37
+ }
38
+ let text = `<b>Server Status</b>\n\n` +
39
+ `<b>Provider:</b> <code>${health.provider}</code>\n` +
40
+ `<b>Status:</b> ${health.status}\n` +
41
+ `<b>Model:</b> <code>${modelStr}</code>${reasoningBadge}\n` +
42
+ `<b>Streaming:</b> ${streaming}\n` +
43
+ `<b>Voice STT:</b> ${stt}\n` +
44
+ `<b>System Prompt:</b> ${promptSource} (${prompt.length} chars)`;
45
+ if (health.project) {
46
+ text += `\n\n<b>Project:</b> <code>${escapeHtml(health.project)}</code>`;
47
+ }
48
+ if (health.branch) {
49
+ text += `\n<b>Branch:</b> <code>${escapeHtml(health.branch)}</code>`;
50
+ }
51
+ if (health.extra) {
52
+ for (const [key, value] of Object.entries(health.extra)) {
53
+ text += `\n<b>${escapeHtml(key)}:</b> <code>${escapeHtml(value)}</code>`;
54
+ }
55
+ }
56
+ await ctx.reply(text, { parse_mode: "HTML" });
57
+ }
58
+ catch (err) {
59
+ await ctx.reply(formatCatchError(err, "checking server health"), { parse_mode: "HTML" });
60
+ }
61
+ });
62
+ bot.command("config", async (ctx) => {
63
+ try {
64
+ const provider = getProvider();
65
+ const config = await provider.getConfig();
66
+ await sendJsonResponse(ctx, config, "config.json");
67
+ }
68
+ catch (err) {
69
+ await ctx.reply(formatCatchError(err, "fetching config"), { parse_mode: "HTML" });
70
+ }
71
+ });
72
+ bot.command("providers", async (ctx) => {
73
+ try {
74
+ const provider = getProvider();
75
+ const providers = await provider.getProviders();
76
+ await sendJsonResponse(ctx, providers, "providers.json");
77
+ }
78
+ catch (err) {
79
+ await ctx.reply(formatCatchError(err, "fetching providers"), { parse_mode: "HTML" });
80
+ }
81
+ });
82
+ bot.command("agents", async (ctx) => {
83
+ try {
84
+ const provider = getProvider();
85
+ const agents = await provider.getAgents();
86
+ if (agents === null) {
87
+ await ctx.reply(`Agent listing is not supported by the ${provider.name} provider.`);
88
+ return;
89
+ }
90
+ if (agents.length === 0) {
91
+ await ctx.reply("No agents available.");
92
+ return;
93
+ }
94
+ await sendJsonResponse(ctx, agents, "agents.json");
95
+ }
96
+ catch (err) {
97
+ await ctx.reply(formatCatchError(err, "listing agents"), { parse_mode: "HTML" });
98
+ }
99
+ });
100
+ bot.command("project", async (ctx) => {
101
+ try {
102
+ const provider = getProvider();
103
+ const proj = await provider.getProjectInfo();
104
+ if (!proj) {
105
+ await ctx.reply(`Project info is not available for the ${provider.name} provider.`);
106
+ return;
107
+ }
108
+ let text = `<b>Project Info</b>\n\n`;
109
+ if (proj.id)
110
+ text += `<b>ID:</b> <code>${escapeHtml(proj.id)}</code>\n`;
111
+ if (proj.worktree)
112
+ text += `<b>Worktree:</b> <code>${escapeHtml(proj.worktree)}</code>\n`;
113
+ if (proj.vcs)
114
+ text += `<b>VCS:</b> ${escapeHtml(proj.vcs)}\n`;
115
+ if (proj.branch)
116
+ text += `<b>Branch:</b> <code>${escapeHtml(proj.branch)}</code>\n`;
117
+ if (proj.directory)
118
+ text += `<b>Directory:</b> <code>${escapeHtml(proj.directory)}</code>\n`;
119
+ await ctx.reply(text, { parse_mode: "HTML" });
120
+ }
121
+ catch (err) {
122
+ await ctx.reply(formatCatchError(err, "fetching project info"), { parse_mode: "HTML" });
123
+ }
124
+ });
125
+ bot.command("git", async (ctx) => {
126
+ try {
127
+ const provider = getProvider();
128
+ // Use provider's file status and project info for git data
129
+ const [projectInfo, fileStatus] = await Promise.all([
130
+ provider.getProjectInfo(),
131
+ provider.getFileStatus(),
132
+ ]);
133
+ if (!projectInfo?.branch && fileStatus === null) {
134
+ await ctx.reply(`Git info is not directly available for the ${provider.name} provider.`);
135
+ return;
136
+ }
137
+ let text = `<b>Git Info</b>\n\n` +
138
+ `<b>Branch:</b> <code>${escapeHtml(projectInfo?.branch ?? "unknown")}</code>\n`;
139
+ if (fileStatus === null) {
140
+ text += `<b>Status:</b> Not available`;
141
+ }
142
+ else if (fileStatus.length === 0) {
143
+ text += `<b>Status:</b> Clean working tree`;
144
+ }
145
+ else {
146
+ text += `<b>Changed files:</b> ${fileStatus.length}\n\n`;
147
+ text += fileStatus
148
+ .slice(0, 30)
149
+ .map((f) => `<code>${escapeHtml(f.status)}</code> ${escapeHtml(f.path)}`)
150
+ .join("\n");
151
+ if (fileStatus.length > 30) {
152
+ text += `\n\n<i>...and ${fileStatus.length - 30} more</i>`;
153
+ }
154
+ }
155
+ const chunks = chunkMessage(text);
156
+ for (const chunk of chunks) {
157
+ await ctx.reply(chunk, { parse_mode: "HTML" });
158
+ }
159
+ }
160
+ catch (err) {
161
+ await ctx.reply(formatCatchError(err, "fetching git info"), { parse_mode: "HTML" });
162
+ }
163
+ });
164
+ bot.command("tools", async (ctx) => {
165
+ try {
166
+ const provider = getProvider();
167
+ const ids = await provider.getTools();
168
+ if (ids === null) {
169
+ await ctx.reply(`Tool listing is not supported by the ${provider.name} provider.`);
170
+ return;
171
+ }
172
+ if (ids.length === 0) {
173
+ await ctx.reply("No tools available.");
174
+ return;
175
+ }
176
+ const text = `<b>Available Tools</b> (${ids.length})\n\n` +
177
+ ids.map((id) => `<code>${escapeHtml(id)}</code>`).join("\n");
178
+ const chunks = chunkMessage(text);
179
+ for (const chunk of chunks) {
180
+ await ctx.reply(chunk, { parse_mode: "HTML" });
181
+ }
182
+ }
183
+ catch (err) {
184
+ await ctx.reply(formatCatchError(err, "listing tools"), { parse_mode: "HTML" });
185
+ }
186
+ });
187
+ bot.command("models", async (ctx) => {
188
+ try {
189
+ const provider = getProvider();
190
+ const models = await provider.listModels();
191
+ const selected = getSelectedModel();
192
+ if (models.length === 0) {
193
+ await ctx.reply("No models available.");
194
+ return;
195
+ }
196
+ // Mark the active model
197
+ for (const m of models) {
198
+ if (selected && selected.providerID === m.provider && selected.modelID === m.id) {
199
+ m.active = true;
200
+ }
201
+ }
202
+ // Group by provider
203
+ const grouped = new Map();
204
+ for (const m of models) {
205
+ const list = grouped.get(m.provider) ?? [];
206
+ list.push(m);
207
+ grouped.set(m.provider, list);
208
+ }
209
+ let text = `<b>Available Models</b>\n`;
210
+ for (const [provId, provModels] of grouped) {
211
+ text += `\n<b>${escapeHtml(provId)}</b>\n`;
212
+ for (const m of provModels) {
213
+ const badges = [];
214
+ if (m.reasoning)
215
+ badges.push("reasoning");
216
+ if (m.attachment)
217
+ badges.push("vision");
218
+ if (m.active)
219
+ badges.push("active");
220
+ const badgeStr = badges.length > 0 ? " " + badges.map(b => `[${b}]`).join(" ") : "";
221
+ text += ` <code>${escapeHtml(m.id)}</code>${badgeStr}\n`;
222
+ }
223
+ }
224
+ text += `\n<i>Use /model provider/model to switch</i>`;
225
+ const chunks = chunkMessage(text);
226
+ for (const chunk of chunks) {
227
+ await ctx.reply(chunk, { parse_mode: "HTML" });
228
+ }
229
+ }
230
+ catch (err) {
231
+ await ctx.reply(formatCatchError(err, "listing models"), { parse_mode: "HTML" });
232
+ }
233
+ });
234
+ bot.command("model", async (ctx) => {
235
+ const input = ctx.match?.trim();
236
+ if (!input) {
237
+ const current = getSelectedModel();
238
+ if (current) {
239
+ // Try to show capabilities for the current model
240
+ let capStr = "";
241
+ try {
242
+ const provider = getProvider();
243
+ const models = await provider.listModels();
244
+ const match = models.find(m => m.id === current.modelID && m.provider === current.providerID);
245
+ if (match) {
246
+ const caps = [];
247
+ if (match.reasoning)
248
+ caps.push("reasoning");
249
+ if (match.attachment)
250
+ caps.push("vision");
251
+ capStr = caps.length > 0 ? `\n<b>Capabilities:</b> ${caps.join(", ")}` : "";
252
+ }
253
+ }
254
+ catch {
255
+ // Ignore — capabilities are optional info
256
+ }
257
+ await ctx.reply(`<b>Current model:</b> <code>${current.providerID}/${current.modelID}</code>${capStr}\n\n<i>Use /models to list available models</i>`, { parse_mode: "HTML" });
258
+ }
259
+ else {
260
+ await ctx.reply(`No model set — using server default.\n\n<b>Usage:</b> <code>/model provider/model</code>\n<i>Use /models to list available models</i>`, { parse_mode: "HTML" });
261
+ }
262
+ return;
263
+ }
264
+ // Try partial match if no "/" in input
265
+ if (!input.includes("/")) {
266
+ try {
267
+ const provider = getProvider();
268
+ const models = await provider.listModels();
269
+ const match = models.find(m => m.id === input || m.id.includes(input) || m.name.toLowerCase().includes(input.toLowerCase()));
270
+ if (match) {
271
+ setSelectedModel(match.provider, match.id);
272
+ const caps = [];
273
+ if (match.reasoning)
274
+ caps.push("reasoning");
275
+ if (match.attachment)
276
+ caps.push("vision");
277
+ const capStr = caps.length > 0 ? `\n<b>Capabilities:</b> ${caps.join(", ")}` : "";
278
+ await ctx.reply(`Model set to <code>${match.provider}/${match.id}</code>${capStr}`, { parse_mode: "HTML" });
279
+ return;
280
+ }
281
+ }
282
+ catch {
283
+ // Fall through to usage message
284
+ }
285
+ await ctx.reply(`<b>Usage:</b> <code>/model provider/model</code>\n<b>Example:</b> <code>/model anthropic/claude-sonnet-4-20250514</code>\n\n<i>Use /models to list available models</i>`, { parse_mode: "HTML" });
286
+ return;
287
+ }
288
+ const parts = input.split("/");
289
+ const providerID = parts[0];
290
+ const modelID = parts.slice(1).join("/");
291
+ setSelectedModel(providerID, modelID);
292
+ // Show capabilities if available
293
+ let capStr = "";
294
+ try {
295
+ const provider = getProvider();
296
+ const models = await provider.listModels();
297
+ const match = models.find(m => m.id === modelID && m.provider === providerID);
298
+ if (match) {
299
+ const caps = [];
300
+ if (match.reasoning)
301
+ caps.push("reasoning");
302
+ if (match.attachment)
303
+ caps.push("vision");
304
+ capStr = caps.length > 0 ? `\n<b>Capabilities:</b> ${caps.join(", ")}` : "";
305
+ }
306
+ }
307
+ catch {
308
+ // Ignore
309
+ }
310
+ await ctx.reply(`Model set to <code>${providerID}/${modelID}</code>${capStr}`, { parse_mode: "HTML" });
311
+ });
312
+ bot.command("system", async (ctx) => {
313
+ const action = ctx.match?.trim();
314
+ if (action === "reload") {
315
+ const prompt = reloadSystemPrompt();
316
+ const source = isUsingCustomPrompt() ? "Custom file" : "Default";
317
+ await ctx.reply(`System prompt reloaded.\n<b>Source:</b> ${source} | <b>Length:</b> ${prompt.length} chars`, { parse_mode: "HTML" });
318
+ return;
319
+ }
320
+ const prompt = getSystemPrompt();
321
+ const source = isUsingCustomPrompt() ? "Custom (skill.md)" : "Default (built-in)";
322
+ const escaped = escapeHtml(prompt.length > 500 ? prompt.slice(0, 500) + "\n\n...(truncated)" : prompt);
323
+ await ctx.reply(`<b>System Prompt</b>\n` +
324
+ `<b>Source:</b> ${source} | <b>Length:</b> ${prompt.length} chars\n\n` +
325
+ `<pre>${escaped}</pre>`, { parse_mode: "HTML" });
326
+ });
327
+ bot.command("start", async (ctx) => {
328
+ const providerName = getProviderName();
329
+ await ctx.reply(`Hey! Send me a message and I'll pass it to the AI.\n\n` +
330
+ `Provider: ${providerName}\n\n` +
331
+ `You can also send voice notes, photos, or files.\n\n` +
332
+ `Type /help to see all commands.`);
333
+ });
334
+ bot.command("help", async (ctx) => {
335
+ const providerName = getProviderName();
336
+ const isOpencode = providerName === "opencode";
337
+ let text = `<b>Relay</b> — ${providerName} provider\n\n` +
338
+ `<b>Chat</b>\n` +
339
+ `Just send any text, voice, photo, or file\n\n` +
340
+ `<b>Sessions</b>\n` +
341
+ `/new — New session\n` +
342
+ `/sessions — List sessions\n` +
343
+ `/switch <code>id</code> — Switch session\n` +
344
+ `/delete <code>id</code> — Delete session\n` +
345
+ `/current — Active session\n` +
346
+ `/fork <code>[messageId]</code> — Fork session\n\n`;
347
+ if (isOpencode) {
348
+ text +=
349
+ `<b>Monitor</b>\n` +
350
+ `/todo — AI task checklist\n` +
351
+ `/diff — Session code changes\n` +
352
+ `/diff full — Download full diff\n\n`;
353
+ }
354
+ text +=
355
+ `<b>Files</b>\n` +
356
+ `/read <code>path</code> — Read file\n` +
357
+ `/find <code>query</code> — Find files\n` +
358
+ `/search <code>pattern</code> — Search in files\n` +
359
+ `/symbols <code>query</code> — Find symbols\n` +
360
+ `/status — Git status\n\n` +
361
+ `<b>History</b>\n` +
362
+ `/history — Conversation history\n` +
363
+ `/summarize — Summarize session\n` +
364
+ `/revert — Undo last change\n` +
365
+ `/abort — Cancel operation\n` +
366
+ `/share — Share session\n\n` +
367
+ `<b>Shell</b>\n` +
368
+ `/shell <code>cmd</code> — Run command\n`;
369
+ if (isOpencode) {
370
+ text +=
371
+ `/cmd <code>command</code> — OpenCode command\n` +
372
+ `/commands — List available commands\n\n`;
373
+ }
374
+ else {
375
+ text += `\n`;
376
+ }
377
+ const provider = getProvider();
378
+ if (provider.capabilities.mcp) {
379
+ text +=
380
+ `<b>MCP</b>\n` +
381
+ `/mcp — MCP server status\n` +
382
+ `/mcp add <code>name</code> local <code>cmd</code> — Add local MCP\n` +
383
+ `/mcp add <code>name</code> remote <code>url</code> — Add remote MCP\n` +
384
+ `/mcp remove <code>name</code> — Remove MCP server\n\n`;
385
+ }
386
+ text +=
387
+ `<b>Settings</b>\n` +
388
+ `/model <code>provider/model</code> — Change model\n` +
389
+ `/models — List available models\n` +
390
+ `/system — View system prompt\n` +
391
+ `/system reload — Reload prompt\n` +
392
+ `/health — Server status\n` +
393
+ `/config — Show config\n` +
394
+ `/providers — List providers\n` +
395
+ `/agents — List agents\n` +
396
+ `/tools — Available tools\n` +
397
+ `/project — Project info\n` +
398
+ `/git — Git branch + status`;
399
+ await ctx.reply(text, { parse_mode: "HTML" });
400
+ });
401
+ }
402
+ async function sendJsonResponse(ctx, data, filename) {
403
+ const json = JSON.stringify(data, null, 2);
404
+ if (json.length > 3500) {
405
+ const buffer = Buffer.from(json, "utf-8");
406
+ await ctx.replyWithDocument(new InputFile(buffer, filename));
407
+ return;
408
+ }
409
+ const text = "```json\n" + json + "\n```";
410
+ const chunks = chunkMessage(text);
411
+ for (const chunk of chunks) {
412
+ try {
413
+ await ctx.reply(chunk, { parse_mode: "Markdown" });
414
+ }
415
+ catch {
416
+ await ctx.reply(chunk);
417
+ }
418
+ }
419
+ }
420
+ //# sourceMappingURL=admin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin.js","sourceRoot":"","sources":["../../src/commands/admin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { Bot } from "grammy";
2
+ export declare function registerChat(bot: Bot): void;
@@ -0,0 +1,80 @@
1
+ import { getProvider } from "../providers/index.js";
2
+ import { getOrCreateSession, getSelectedModel } from "../session.js";
3
+ import { chunkMessage } from "../utils/chunker.js";
4
+ import { isStreamingEnabled, streamPrompt } from "../utils/stream.js";
5
+ import { getSystemPrompt } from "../utils/system-prompt.js";
6
+ import { formatCatchError, EMPTY_RESPONSE_MSG } from "../utils/errors.js";
7
+ import { withTimeout, getPromptTimeout } from "../utils/timeout.js";
8
+ import { extractFileParts, sendResponseFiles } from "../utils/files.js";
9
+ import { InputFile } from "grammy";
10
+ const MAX_INPUT_LENGTH = 32_000;
11
+ export function registerChat(bot) {
12
+ bot.on("message:text", async (ctx) => {
13
+ const text = ctx.message.text;
14
+ if (text.startsWith("/"))
15
+ return;
16
+ if (text.length > MAX_INPUT_LENGTH) {
17
+ await ctx.reply(`Message too long (${text.toLocaleString().length} chars). ` +
18
+ `Maximum is ${MAX_INPUT_LENGTH.toLocaleString()} characters. ` +
19
+ `Send the content as a file instead.`);
20
+ return;
21
+ }
22
+ try {
23
+ const sessionId = await getOrCreateSession();
24
+ const model = getSelectedModel();
25
+ const system = getSystemPrompt();
26
+ const provider = getProvider();
27
+ // Streaming: use provider's promptStream if available
28
+ if (isStreamingEnabled() && provider.promptStream) {
29
+ const parts = [{ type: "text", text }];
30
+ await streamPrompt({ ctx, sessionId, parts, model, system });
31
+ return;
32
+ }
33
+ // Keep typing indicator active while waiting for response
34
+ const typingInterval = setInterval(() => {
35
+ ctx.replyWithChatAction("typing").catch(() => { });
36
+ }, 4000);
37
+ await ctx.replyWithChatAction("typing");
38
+ try {
39
+ const result = await withTimeout(provider.prompt(sessionId, text, {
40
+ parts: [{ type: "text", text }],
41
+ ...(model && { model }),
42
+ system,
43
+ }), getPromptTimeout(), "Prompt");
44
+ if (!result.text.trim() || result.text === "(empty response)") {
45
+ await ctx.reply(EMPTY_RESPONSE_MSG, { parse_mode: "HTML" });
46
+ return;
47
+ }
48
+ await sendResponse(ctx, result.text);
49
+ // Send any file attachments from the response
50
+ const files = extractFileParts(result.parts ?? []);
51
+ if (files.length > 0) {
52
+ await sendResponseFiles(ctx, files);
53
+ }
54
+ }
55
+ finally {
56
+ clearInterval(typingInterval);
57
+ }
58
+ }
59
+ catch (err) {
60
+ await ctx.reply(formatCatchError(err, "sending message"), { parse_mode: "HTML" });
61
+ }
62
+ });
63
+ }
64
+ async function sendResponse(ctx, text) {
65
+ if (text.length > 20000) {
66
+ const buffer = Buffer.from(text, "utf-8");
67
+ await ctx.replyWithDocument(new InputFile(buffer, "response.txt"));
68
+ return;
69
+ }
70
+ const chunks = chunkMessage(text);
71
+ for (const chunk of chunks) {
72
+ try {
73
+ await ctx.reply(chunk, { parse_mode: "Markdown" });
74
+ }
75
+ catch {
76
+ await ctx.reply(chunk);
77
+ }
78
+ }
79
+ }
80
+ //# sourceMappingURL=chat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat.js","sourceRoot":"","sources":["../../src/commands/chat.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { Bot } from "grammy";
2
+ export declare function registerFileCommands(bot: Bot): void;