opencode-telegram-bridge 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.
- package/.env.example +9 -0
- package/README.md +62 -0
- package/bin/opencode-telegram-bridge.js +2 -0
- package/dist/bot.d.ts +7 -0
- package/dist/bot.d.ts.map +1 -0
- package/dist/bot.js +337 -0
- package/dist/bot.js.map +1 -0
- package/dist/config.d.ts +14 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +49 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/opencode.d.ts +38 -0
- package/dist/opencode.d.ts.map +1 -0
- package/dist/opencode.js +142 -0
- package/dist/opencode.js.map +1 -0
- package/dist/projects.d.ts +14 -0
- package/dist/projects.d.ts.map +1 -0
- package/dist/projects.js +74 -0
- package/dist/projects.js.map +1 -0
- package/dist/prompt-guard.d.ts +7 -0
- package/dist/prompt-guard.d.ts.map +1 -0
- package/dist/prompt-guard.js +47 -0
- package/dist/prompt-guard.js.map +1 -0
- package/dist/state.d.ts +10 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +56 -0
- package/dist/state.js.map +1 -0
- package/dist/storage.d.ts +8 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +16 -0
- package/dist/storage.js.map +1 -0
- package/dist/telegram.d.ts +3 -0
- package/dist/telegram.d.ts.map +1 -0
- package/dist/telegram.js +12 -0
- package/dist/telegram.js.map +1 -0
- package/docs/configuration.md +17 -0
- package/docs/index.md +8 -0
- package/docs/installation.md +42 -0
- package/docs/release.md +56 -0
- package/docs/systemd.md +42 -0
- package/docs/usage.md +20 -0
- package/package.json +52 -0
- package/systemd/opencode-telegram-bridge.env.example +7 -0
- package/systemd/opencode-telegram-bridge.service +14 -0
package/.env.example
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
TELEGRAM_BOT_TOKEN=your-telegram-bot-token
|
|
2
|
+
TELEGRAM_ALLOWED_USER_ID=your-telegram-user-id
|
|
3
|
+
TELEGRAM_HANDLER_TIMEOUT_MS=630000
|
|
4
|
+
|
|
5
|
+
# OpenCode server config
|
|
6
|
+
OPENCODE_SERVER_URL=http://127.0.0.1:4096
|
|
7
|
+
OPENCODE_SERVER_USERNAME=opencode
|
|
8
|
+
OPENCODE_SERVER_PASSWORD=
|
|
9
|
+
OPENCODE_PROMPT_TIMEOUT_MS=600000
|
package/README.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# OpenCode Telegram Bridge
|
|
2
|
+
|
|
3
|
+
Run a Telegram bot that forwards messages to an OpenCode backend and returns responses.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
- Node.js 18+
|
|
7
|
+
- OpenCode CLI installed and available on PATH
|
|
8
|
+
- OpenCode server running (`opencode serve`)
|
|
9
|
+
|
|
10
|
+
## Quickstart
|
|
11
|
+
1. Install dependencies:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
2. Create `.env` from the example:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
cp .env.example .env
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
3. Start OpenCode server in another terminal:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
opencode serve
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
4. Run the bot:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm run dev
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Install via npm
|
|
36
|
+
```bash
|
|
37
|
+
npm install -g opencode-telegram-bridge
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Run:
|
|
41
|
+
```bash
|
|
42
|
+
opencode-telegram-bridge
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
You still need OpenCode running separately:
|
|
46
|
+
```bash
|
|
47
|
+
opencode serve
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Docs
|
|
51
|
+
- `docs/index.md`
|
|
52
|
+
- `docs/installation.md`
|
|
53
|
+
- `docs/configuration.md`
|
|
54
|
+
- `docs/usage.md`
|
|
55
|
+
- `docs/systemd.md`
|
|
56
|
+
- `docs/release.md`
|
|
57
|
+
|
|
58
|
+
## Releases
|
|
59
|
+
This project uses Changesets. See `docs/release.md`.
|
|
60
|
+
|
|
61
|
+
## Notes
|
|
62
|
+
- Project aliases and chat project selection are stored in `~/.opencode-telegram-bridge/projects.db`.
|
package/dist/bot.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Telegraf } from "telegraf";
|
|
2
|
+
import type { BotConfig } from "./config.js";
|
|
3
|
+
import type { OpencodeBridge } from "./opencode.js";
|
|
4
|
+
import { type ProjectStore } from "./projects.js";
|
|
5
|
+
import type { ChatProjectStore } from "./state.js";
|
|
6
|
+
export declare const startBot: (config: BotConfig, opencode: OpencodeBridge, projects: ProjectStore, chatProjects: ChatProjectStore) => Telegraf<import("telegraf").Context<import("@telegraf/types").Update>>;
|
|
7
|
+
//# sourceMappingURL=bot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bot.d.ts","sourceRoot":"","sources":["../src/bot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,QAAQ,EAAE,MAAM,UAAU,CAAA;AAE3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAmB,MAAM,eAAe,CAAA;AAEpE,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,eAAe,CAAA;AACrE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AA8BlD,eAAO,MAAM,QAAQ,GACnB,QAAQ,SAAS,EACjB,UAAU,cAAc,EACxB,UAAU,YAAY,EACtB,cAAc,gBAAgB,2EAia/B,CAAA"}
|
package/dist/bot.js
ADDED
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
import { Markup, Telegraf } from "telegraf";
|
|
2
|
+
import { createPromptGuard } from "./prompt-guard.js";
|
|
3
|
+
import { HOME_PROJECT_ALIAS } from "./projects.js";
|
|
4
|
+
import { splitTelegramMessage } from "./telegram.js";
|
|
5
|
+
const isAuthorized = (user, allowedUserId) => user?.id === allowedUserId;
|
|
6
|
+
const formatUserLabel = (user) => {
|
|
7
|
+
if (!user) {
|
|
8
|
+
return "unknown";
|
|
9
|
+
}
|
|
10
|
+
if (user.username) {
|
|
11
|
+
return `${user.username} (${user.id ?? "unknown"})`;
|
|
12
|
+
}
|
|
13
|
+
return String(user.id ?? "unknown");
|
|
14
|
+
};
|
|
15
|
+
export const startBot = (config, opencode, projects, chatProjects) => {
|
|
16
|
+
const bot = new Telegraf(config.botToken, {
|
|
17
|
+
handlerTimeout: config.handlerTimeoutMs,
|
|
18
|
+
});
|
|
19
|
+
/*
|
|
20
|
+
* Telegraf wraps each update handler in a timeout. When that timeout fires,
|
|
21
|
+
* it logs an error but does not cancel the async handler. To avoid dangling
|
|
22
|
+
* prompts and a stuck in-flight lock, we enforce our own per-chat timeout
|
|
23
|
+
* and abort the OpenCode request when it exceeds the limit.
|
|
24
|
+
*/
|
|
25
|
+
const promptGuard = createPromptGuard(config.promptTimeoutMs);
|
|
26
|
+
const pendingPermissions = new Map();
|
|
27
|
+
const sendReply = async (chatId, replyToMessageId, text) => {
|
|
28
|
+
try {
|
|
29
|
+
const chunks = splitTelegramMessage(text);
|
|
30
|
+
for (const [index, chunk] of chunks.entries()) {
|
|
31
|
+
const replyParameters = index === 0 && replyToMessageId
|
|
32
|
+
? { reply_parameters: { message_id: replyToMessageId } }
|
|
33
|
+
: undefined;
|
|
34
|
+
await bot.telegram.sendMessage(chatId, chunk, replyParameters);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
console.error("Failed to send Telegram reply", error);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const buildPermissionSummary = (request) => {
|
|
42
|
+
const lines = ["OpenCode permission request", `Permission: ${request.permission}`];
|
|
43
|
+
if (request.patterns.length > 0) {
|
|
44
|
+
lines.push(`Patterns: ${request.patterns.join(", ")}`);
|
|
45
|
+
}
|
|
46
|
+
if (request.always.length > 0) {
|
|
47
|
+
lines.push(`Always scopes: ${request.always.join(", ")}`);
|
|
48
|
+
}
|
|
49
|
+
return lines.join("\n");
|
|
50
|
+
};
|
|
51
|
+
const buildPermissionKeyboard = (requestId, includeAlways) => {
|
|
52
|
+
const buttons = [
|
|
53
|
+
Markup.button.callback("Approve once", `perm:${requestId}:once`),
|
|
54
|
+
Markup.button.callback("Reject", `perm:${requestId}:reject`),
|
|
55
|
+
];
|
|
56
|
+
if (includeAlways) {
|
|
57
|
+
buttons.splice(1, 0, Markup.button.callback("Approve always", `perm:${requestId}:always`));
|
|
58
|
+
}
|
|
59
|
+
return Markup.inlineKeyboard([buttons]);
|
|
60
|
+
};
|
|
61
|
+
opencode.startPermissionEventStream({
|
|
62
|
+
onPermissionAsked: async ({ request, directory }) => {
|
|
63
|
+
const owner = opencode.getSessionOwner(request.sessionID);
|
|
64
|
+
if (!owner) {
|
|
65
|
+
console.warn("Permission request for unknown session", {
|
|
66
|
+
sessionId: request.sessionID,
|
|
67
|
+
requestId: request.id,
|
|
68
|
+
});
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const summary = buildPermissionSummary(request);
|
|
72
|
+
try {
|
|
73
|
+
const replyMarkup = buildPermissionKeyboard(request.id, request.always.length > 0);
|
|
74
|
+
const message = await bot.telegram.sendMessage(owner.chatId, summary, {
|
|
75
|
+
reply_markup: replyMarkup.reply_markup,
|
|
76
|
+
});
|
|
77
|
+
pendingPermissions.set(request.id, {
|
|
78
|
+
chatId: owner.chatId,
|
|
79
|
+
messageId: message.message_id,
|
|
80
|
+
directory,
|
|
81
|
+
summary,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
console.error("Failed to send permission request", error);
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
onError: (error) => {
|
|
89
|
+
console.error("OpenCode event stream error", error);
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
const getChatProjectAlias = (chatId) => chatProjects.getActiveAlias(chatId) ?? HOME_PROJECT_ALIAS;
|
|
93
|
+
const setChatProjectAlias = (chatId, alias) => {
|
|
94
|
+
chatProjects.setActiveAlias(chatId, alias);
|
|
95
|
+
};
|
|
96
|
+
const formatProjectList = (activeAlias) => {
|
|
97
|
+
const entries = projects.listProjects();
|
|
98
|
+
if (entries.length === 0) {
|
|
99
|
+
return "No projects configured.";
|
|
100
|
+
}
|
|
101
|
+
const lines = entries.map((entry) => {
|
|
102
|
+
const prefix = entry.alias === activeAlias ? "*" : " ";
|
|
103
|
+
return `${prefix} ${entry.alias}: ${entry.path}`;
|
|
104
|
+
});
|
|
105
|
+
return ["Projects (active marked with *):", ...lines].join("\n");
|
|
106
|
+
};
|
|
107
|
+
const isCommandMessage = (ctx) => ctx.message?.entities?.some((entity) => entity.type === "bot_command" && entity.offset === 0) ?? false;
|
|
108
|
+
bot.start(async (ctx) => {
|
|
109
|
+
if (!isAuthorized(ctx.from, config.allowedUserId)) {
|
|
110
|
+
await ctx.reply("Not authorized.");
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
await ctx.reply("Bot is online. Send me a message and I'll log it here.");
|
|
114
|
+
});
|
|
115
|
+
bot.command("project", async (ctx) => {
|
|
116
|
+
if (!isAuthorized(ctx.from, config.allowedUserId)) {
|
|
117
|
+
await ctx.reply("Not authorized.");
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const chatId = ctx.chat?.id;
|
|
121
|
+
if (!chatId) {
|
|
122
|
+
console.warn("Missing chat id for incoming project command");
|
|
123
|
+
await ctx.reply("Missing chat context.");
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const messageText = ctx.message?.text ?? "";
|
|
127
|
+
const parts = messageText.trim().split(/\s+/);
|
|
128
|
+
parts.shift();
|
|
129
|
+
const subcommand = parts[0] ?? "list";
|
|
130
|
+
const args = parts.slice(1);
|
|
131
|
+
try {
|
|
132
|
+
switch (subcommand) {
|
|
133
|
+
case "list": {
|
|
134
|
+
await ctx.reply(formatProjectList(getChatProjectAlias(chatId)));
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
case "current": {
|
|
138
|
+
const activeAlias = getChatProjectAlias(chatId);
|
|
139
|
+
const project = projects.getProject(activeAlias);
|
|
140
|
+
if (!project) {
|
|
141
|
+
throw new Error(`Project alias '${activeAlias}' not found`);
|
|
142
|
+
}
|
|
143
|
+
await ctx.reply(`${project.alias}: ${project.path}`);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
case "add": {
|
|
147
|
+
const alias = args[0];
|
|
148
|
+
const projectPath = args.slice(1).join(" ");
|
|
149
|
+
if (!alias) {
|
|
150
|
+
await ctx.reply("Usage: /project add <alias> <path>");
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const project = projects.addProject(alias, projectPath);
|
|
154
|
+
await ctx.reply(`Added ${project.alias}: ${project.path}`);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
case "remove": {
|
|
158
|
+
const alias = args[0];
|
|
159
|
+
if (!alias) {
|
|
160
|
+
await ctx.reply("Usage: /project remove <alias>");
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
projects.removeProject(alias);
|
|
164
|
+
if (getChatProjectAlias(chatId) === alias) {
|
|
165
|
+
setChatProjectAlias(chatId, HOME_PROJECT_ALIAS);
|
|
166
|
+
}
|
|
167
|
+
await ctx.reply(`Removed ${alias}`);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
case "set": {
|
|
171
|
+
const alias = args[0];
|
|
172
|
+
if (!alias) {
|
|
173
|
+
await ctx.reply("Usage: /project set <alias>");
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
const project = projects.getProject(alias);
|
|
177
|
+
if (!project) {
|
|
178
|
+
throw new Error(`Project alias '${alias}' not found`);
|
|
179
|
+
}
|
|
180
|
+
setChatProjectAlias(chatId, project.alias);
|
|
181
|
+
await ctx.reply(`Active project: ${project.alias}`);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
default: {
|
|
185
|
+
await ctx.reply("Usage: /project <list|current|add|remove|set> ...");
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
console.error("Failed to handle /project command", error);
|
|
191
|
+
const message = error instanceof Error
|
|
192
|
+
? error.message
|
|
193
|
+
: "Project command failed. Check server logs.";
|
|
194
|
+
await ctx.reply(message);
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
bot.command("reset", async (ctx) => {
|
|
198
|
+
if (!isAuthorized(ctx.from, config.allowedUserId)) {
|
|
199
|
+
await ctx.reply("Not authorized.");
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
const chatId = ctx.chat?.id;
|
|
203
|
+
if (!chatId) {
|
|
204
|
+
console.warn("Missing chat id for incoming reset command");
|
|
205
|
+
await ctx.reply("Missing chat context.");
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
const activeAlias = getChatProjectAlias(chatId);
|
|
209
|
+
const project = projects.getProject(activeAlias);
|
|
210
|
+
if (!project) {
|
|
211
|
+
console.error("Missing project for chat", { chatId, activeAlias });
|
|
212
|
+
await ctx.reply("Missing project configuration.");
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
const didReset = opencode.resetSession(chatId, project.path);
|
|
216
|
+
if (didReset) {
|
|
217
|
+
await ctx.reply(`Session reset for ${project.alias}.`);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
await ctx.reply(`No active session to reset for ${project.alias}.`);
|
|
221
|
+
});
|
|
222
|
+
bot.on("callback_query", async (ctx) => {
|
|
223
|
+
const callbackQuery = ctx.callbackQuery;
|
|
224
|
+
if (!callbackQuery || !("data" in callbackQuery)) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
const data = callbackQuery.data;
|
|
228
|
+
if (!data.startsWith("perm:")) {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
if (!isAuthorized(ctx.from, config.allowedUserId)) {
|
|
232
|
+
await ctx.answerCbQuery("Not authorized.");
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
const [, requestId, reply] = data.split(":");
|
|
236
|
+
if (!requestId || !reply) {
|
|
237
|
+
await ctx.answerCbQuery("Invalid permission response.");
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
const permissionReply = reply;
|
|
241
|
+
if (!["once", "always", "reject"].includes(permissionReply)) {
|
|
242
|
+
await ctx.answerCbQuery("Invalid permission response.");
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
const pending = pendingPermissions.get(requestId);
|
|
246
|
+
if (!pending) {
|
|
247
|
+
await ctx.answerCbQuery("Permission request not found.");
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
try {
|
|
251
|
+
await opencode.replyToPermission(requestId, permissionReply, pending.directory);
|
|
252
|
+
pendingPermissions.delete(requestId);
|
|
253
|
+
const decisionLabel = permissionReply === "reject"
|
|
254
|
+
? "Rejected"
|
|
255
|
+
: permissionReply === "always"
|
|
256
|
+
? "Approved (always)"
|
|
257
|
+
: "Approved (once)";
|
|
258
|
+
await bot.telegram.editMessageText(pending.chatId, pending.messageId, undefined, `${pending.summary}\nDecision: ${decisionLabel}`);
|
|
259
|
+
await ctx.answerCbQuery("Response sent.");
|
|
260
|
+
}
|
|
261
|
+
catch (error) {
|
|
262
|
+
console.error("Failed to reply to permission", error);
|
|
263
|
+
await ctx.answerCbQuery("Failed to send response.");
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
bot.on("text", (ctx) => {
|
|
267
|
+
if (!isAuthorized(ctx.from, config.allowedUserId)) {
|
|
268
|
+
void ctx.reply("Not authorized.");
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
if (isCommandMessage(ctx)) {
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
const text = ctx.message.text;
|
|
275
|
+
const userLabel = formatUserLabel(ctx.from);
|
|
276
|
+
const chatId = ctx.chat?.id;
|
|
277
|
+
const replyToMessageId = ctx.message.message_id;
|
|
278
|
+
if (!chatId) {
|
|
279
|
+
console.warn("Missing chat id for incoming message", { userLabel });
|
|
280
|
+
void ctx.reply("Missing chat context.");
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
const activeAlias = getChatProjectAlias(chatId);
|
|
284
|
+
const project = projects.getProject(activeAlias);
|
|
285
|
+
if (!project) {
|
|
286
|
+
console.error("Missing project for chat", { chatId, activeAlias });
|
|
287
|
+
void ctx.reply("Missing project configuration.");
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
console.log(`[telegram] ${userLabel}: ${text}`);
|
|
291
|
+
/*
|
|
292
|
+
* If we cannot start a prompt, we reply to the new message and ignore it.
|
|
293
|
+
* When a prompt times out, the guard clears the in-flight state so new
|
|
294
|
+
* messages can be accepted even if the original handler is still running.
|
|
295
|
+
*/
|
|
296
|
+
/*
|
|
297
|
+
* timedOut becomes true only if our prompt timeout fires. Telegraf's
|
|
298
|
+
* handler timeout does not stop background work, so we guard against
|
|
299
|
+
* late replies by checking this flag before responding.
|
|
300
|
+
*/
|
|
301
|
+
let timedOut = false;
|
|
302
|
+
const abortController = promptGuard.tryStart(chatId, () => {
|
|
303
|
+
timedOut = true;
|
|
304
|
+
void sendReply(chatId, replyToMessageId, "OpenCode request timed out. You can send a new message.");
|
|
305
|
+
});
|
|
306
|
+
if (!abortController) {
|
|
307
|
+
void sendReply(chatId, replyToMessageId, "Your previous message has not been replied to yet. This message will be ignored.");
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
void (async () => {
|
|
311
|
+
try {
|
|
312
|
+
const reply = await opencode.promptFromChat(chatId, text, project.path, { signal: abortController.signal });
|
|
313
|
+
if (!timedOut) {
|
|
314
|
+
await sendReply(chatId, replyToMessageId, reply);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
catch (error) {
|
|
318
|
+
console.error("Failed to send prompt to OpenCode", error);
|
|
319
|
+
if (!timedOut) {
|
|
320
|
+
await sendReply(chatId, replyToMessageId, "OpenCode error. Check server logs.");
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
finally {
|
|
324
|
+
promptGuard.finish(chatId);
|
|
325
|
+
}
|
|
326
|
+
})();
|
|
327
|
+
});
|
|
328
|
+
bot.catch((error, ctx) => {
|
|
329
|
+
console.error("Telegram bot error", {
|
|
330
|
+
error,
|
|
331
|
+
updateId: ctx.update.update_id,
|
|
332
|
+
});
|
|
333
|
+
});
|
|
334
|
+
bot.launch();
|
|
335
|
+
return bot;
|
|
336
|
+
};
|
|
337
|
+
//# sourceMappingURL=bot.js.map
|
package/dist/bot.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bot.js","sourceRoot":"","sources":["../src/bot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAI3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAE,kBAAkB,EAAqB,MAAM,eAAe,CAAA;AAErE,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AAcpD,MAAM,YAAY,GAAG,CAAC,IAA8B,EAAE,aAAqB,EAAE,EAAE,CAC7E,IAAI,EAAE,EAAE,KAAK,aAAa,CAAA;AAE5B,MAAM,eAAe,GAAG,CAAC,IAA8B,EAAE,EAAE;IACzD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,OAAO,GAAG,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,EAAE,IAAI,SAAS,GAAG,CAAA;IACrD,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,SAAS,CAAC,CAAA;AACrC,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,QAAQ,GAAG,CACtB,MAAiB,EACjB,QAAwB,EACxB,QAAsB,EACtB,YAA8B,EAC9B,EAAE;IACF,MAAM,GAAG,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE;QACxC,cAAc,EAAE,MAAM,CAAC,gBAAgB;KACxC,CAAC,CAAA;IACF;;;;;OAKG;IACH,MAAM,WAAW,GAAG,iBAAiB,CAAC,MAAM,CAAC,eAAe,CAAC,CAAA;IAC7D,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAA6B,CAAA;IAE/D,MAAM,SAAS,GAAG,KAAK,EACrB,MAAc,EACd,gBAAoC,EACpC,IAAY,EACZ,EAAE;QACF,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAA;YACzC,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;gBAC9C,MAAM,eAAe,GACnB,KAAK,KAAK,CAAC,IAAI,gBAAgB;oBAC7B,CAAC,CAAC,EAAE,gBAAgB,EAAE,EAAE,UAAU,EAAE,gBAAgB,EAAE,EAAE;oBACxD,CAAC,CAAC,SAAS,CAAA;gBACf,MAAM,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,MAAM,EAAE,KAAK,EAAE,eAAe,CAAC,CAAA;YAChE,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAA;QACvD,CAAC;IACH,CAAC,CAAA;IAED,MAAM,sBAAsB,GAAG,CAAC,OAI/B,EAAE,EAAE;QACH,MAAM,KAAK,GAAG,CAAC,6BAA6B,EAAE,eAAe,OAAO,CAAC,UAAU,EAAE,CAAC,CAAA;QAClF,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,KAAK,CAAC,IAAI,CAAC,aAAa,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACxD,CAAC;QACD,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,KAAK,CAAC,IAAI,CAAC,kBAAkB,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAC3D,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACzB,CAAC,CAAA;IAED,MAAM,uBAAuB,GAAG,CAC9B,SAAiB,EACjB,aAAsB,EACtB,EAAE;QACF,MAAM,OAAO,GAAG;YACd,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,EAAE,QAAQ,SAAS,OAAO,CAAC;YAChE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,SAAS,SAAS,CAAC;SAC7D,CAAA;QACD,IAAI,aAAa,EAAE,CAAC;YAClB,OAAO,CAAC,MAAM,CACZ,CAAC,EACD,CAAC,EACD,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,EAAE,QAAQ,SAAS,SAAS,CAAC,CACrE,CAAA;QACH,CAAC;QAED,OAAO,MAAM,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,CAAC,CAAA;IACzC,CAAC,CAAA;IAED,QAAQ,CAAC,0BAA0B,CAAC;QAClC,iBAAiB,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE;YAClD,MAAM,KAAK,GAAG,QAAQ,CAAC,eAAe,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;YACzD,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO,CAAC,IAAI,CAAC,wCAAwC,EAAE;oBACrD,SAAS,EAAE,OAAO,CAAC,SAAS;oBAC5B,SAAS,EAAE,OAAO,CAAC,EAAE;iBACtB,CAAC,CAAA;gBACF,OAAM;YACR,CAAC;YAED,MAAM,OAAO,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAA;YAC/C,IAAI,CAAC;gBACH,MAAM,WAAW,GAAG,uBAAuB,CACzC,OAAO,CAAC,EAAE,EACV,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAC1B,CAAA;gBACD,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;oBACpE,YAAY,EAAE,WAAW,CAAC,YAAY;iBACvC,CAAC,CAAA;gBACF,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE;oBACjC,MAAM,EAAE,KAAK,CAAC,MAAM;oBACpB,SAAS,EAAE,OAAO,CAAC,UAAU;oBAC7B,SAAS;oBACT,OAAO;iBACR,CAAC,CAAA;YACJ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAA;YAC3D,CAAC;QACH,CAAC;QACD,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACjB,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAA;QACrD,CAAC;KACF,CAAC,CAAA;IAEF,MAAM,mBAAmB,GAAG,CAAC,MAAc,EAAE,EAAE,CAC7C,YAAY,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,kBAAkB,CAAA;IAE3D,MAAM,mBAAmB,GAAG,CAAC,MAAc,EAAE,KAAa,EAAE,EAAE;QAC5D,YAAY,CAAC,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;IAC5C,CAAC,CAAA;IAED,MAAM,iBAAiB,GAAG,CAAC,WAAmB,EAAE,EAAE;QAChD,MAAM,OAAO,GAAG,QAAQ,CAAC,YAAY,EAAE,CAAA;QACvC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,yBAAyB,CAAA;QAClC,CAAC;QAED,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;YAClC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAA;YACtD,OAAO,GAAG,MAAM,IAAI,KAAK,CAAC,KAAK,KAAK,KAAK,CAAC,IAAI,EAAE,CAAA;QAClD,CAAC,CAAC,CAAA;QAEF,OAAO,CAAC,kCAAkC,EAAE,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAClE,CAAC,CAAA;IAED,MAAM,gBAAgB,GAAG,CAAC,GAAyE,EAAE,EAAE,CACrG,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,IAAI,CACzB,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,aAAa,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,CACjE,IAAI,KAAK,CAAA;IAEZ,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACtB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;YAClD,MAAM,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAA;YAClC,OAAM;QACR,CAAC;QAED,MAAM,GAAG,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAA;IAC3E,CAAC,CAAC,CAAA;IAEF,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QACnC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;YAClD,MAAM,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAA;YAClC,OAAM;QACR,CAAC;QAED,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,EAAE,CAAA;QAC3B,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAA;YAC5D,MAAM,GAAG,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAA;YACxC,OAAM;QACR,CAAC;QAED,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,EAAE,IAAI,IAAI,EAAE,CAAA;QAC3C,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;QAC7C,KAAK,CAAC,KAAK,EAAE,CAAA;QAEb,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,MAAM,CAAA;QACrC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QAE3B,IAAI,CAAC;YACH,QAAQ,UAAU,EAAE,CAAC;gBACnB,KAAK,MAAM,CAAC,CAAC,CAAC;oBACZ,MAAM,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;oBAC/D,OAAM;gBACR,CAAC;gBACD,KAAK,SAAS,CAAC,CAAC,CAAC;oBACf,MAAM,WAAW,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAA;oBAC/C,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,CAAA;oBAChD,IAAI,CAAC,OAAO,EAAE,CAAC;wBACb,MAAM,IAAI,KAAK,CAAC,kBAAkB,WAAW,aAAa,CAAC,CAAA;oBAC7D,CAAC;oBAED,MAAM,GAAG,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,KAAK,KAAK,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;oBACpD,OAAM;gBACR,CAAC;gBACD,KAAK,KAAK,CAAC,CAAC,CAAC;oBACX,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;oBACrB,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;oBAC3C,IAAI,CAAC,KAAK,EAAE,CAAC;wBACX,MAAM,GAAG,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAA;wBACrD,OAAM;oBACR,CAAC;oBAED,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,KAAK,EAAE,WAAW,CAAC,CAAA;oBACvD,MAAM,GAAG,CAAC,KAAK,CAAC,SAAS,OAAO,CAAC,KAAK,KAAK,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;oBAC1D,OAAM;gBACR,CAAC;gBACD,KAAK,QAAQ,CAAC,CAAC,CAAC;oBACd,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;oBACrB,IAAI,CAAC,KAAK,EAAE,CAAC;wBACX,MAAM,GAAG,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAA;wBACjD,OAAM;oBACR,CAAC;oBAED,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;oBAC7B,IAAI,mBAAmB,CAAC,MAAM,CAAC,KAAK,KAAK,EAAE,CAAC;wBAC1C,mBAAmB,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAA;oBACjD,CAAC;oBACD,MAAM,GAAG,CAAC,KAAK,CAAC,WAAW,KAAK,EAAE,CAAC,CAAA;oBACnC,OAAM;gBACR,CAAC;gBACD,KAAK,KAAK,CAAC,CAAC,CAAC;oBACX,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;oBACrB,IAAI,CAAC,KAAK,EAAE,CAAC;wBACX,MAAM,GAAG,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAA;wBAC9C,OAAM;oBACR,CAAC;oBAED,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;oBAC1C,IAAI,CAAC,OAAO,EAAE,CAAC;wBACb,MAAM,IAAI,KAAK,CAAC,kBAAkB,KAAK,aAAa,CAAC,CAAA;oBACvD,CAAC;oBAED,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,CAAA;oBAC1C,MAAM,GAAG,CAAC,KAAK,CAAC,mBAAmB,OAAO,CAAC,KAAK,EAAE,CAAC,CAAA;oBACnD,OAAM;gBACR,CAAC;gBACD,OAAO,CAAC,CAAC,CAAC;oBACR,MAAM,GAAG,CAAC,KAAK,CACb,mDAAmD,CACpD,CAAA;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAA;YACzD,MAAM,OAAO,GACX,KAAK,YAAY,KAAK;gBACpB,CAAC,CAAC,KAAK,CAAC,OAAO;gBACf,CAAC,CAAC,4CAA4C,CAAA;YAClD,MAAM,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QAC1B,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QACjC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;YAClD,MAAM,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAA;YAClC,OAAM;QACR,CAAC;QAED,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,EAAE,CAAA;QAC3B,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAA;YAC1D,MAAM,GAAG,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAA;YACxC,OAAM;QACR,CAAC;QAED,MAAM,WAAW,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAA;QAC/C,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,CAAA;QAChD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAA;YAClE,MAAM,GAAG,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAA;YACjD,OAAM;QACR,CAAC;QAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;QAC5D,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,GAAG,CAAC,KAAK,CAAC,qBAAqB,OAAO,CAAC,KAAK,GAAG,CAAC,CAAA;YACtD,OAAM;QACR,CAAC;QAED,MAAM,GAAG,CAAC,KAAK,CAAC,kCAAkC,OAAO,CAAC,KAAK,GAAG,CAAC,CAAA;IACrE,CAAC,CAAC,CAAA;IAEF,GAAG,CAAC,EAAE,CAAC,gBAAgB,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QACrC,MAAM,aAAa,GAAG,GAAG,CAAC,aAAa,CAAA;QACvC,IAAI,CAAC,aAAa,IAAI,CAAC,CAAC,MAAM,IAAI,aAAa,CAAC,EAAE,CAAC;YACjD,OAAM;QACR,CAAC;QAED,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,CAAA;QAC/B,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9B,OAAM;QACR,CAAC;QAED,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;YAClD,MAAM,GAAG,CAAC,aAAa,CAAC,iBAAiB,CAAC,CAAA;YAC1C,OAAM;QACR,CAAC;QAED,MAAM,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAC5C,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK,EAAE,CAAC;YACzB,MAAM,GAAG,CAAC,aAAa,CAAC,8BAA8B,CAAC,CAAA;YACvD,OAAM;QACR,CAAC;QAED,MAAM,eAAe,GAAG,KAAwB,CAAA;QAChD,IAAI,CAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAuB,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;YACnF,MAAM,GAAG,CAAC,aAAa,CAAC,8BAA8B,CAAC,CAAA;YACvD,OAAM;QACR,CAAC;QAED,MAAM,OAAO,GAAG,kBAAkB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;QACjD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,GAAG,CAAC,aAAa,CAAC,+BAA+B,CAAC,CAAA;YACxD,OAAM;QACR,CAAC;QAED,IAAI,CAAC;YACH,MAAM,QAAQ,CAAC,iBAAiB,CAC9B,SAAS,EACT,eAAe,EACf,OAAO,CAAC,SAAS,CAClB,CAAA;YACD,kBAAkB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;YACpC,MAAM,aAAa,GACjB,eAAe,KAAK,QAAQ;gBAC1B,CAAC,CAAC,UAAU;gBACZ,CAAC,CAAC,eAAe,KAAK,QAAQ;oBAC9B,CAAC,CAAC,mBAAmB;oBACrB,CAAC,CAAC,iBAAiB,CAAA;YACvB,MAAM,GAAG,CAAC,QAAQ,CAAC,eAAe,CAChC,OAAO,CAAC,MAAM,EACd,OAAO,CAAC,SAAS,EACjB,SAAS,EACT,GAAG,OAAO,CAAC,OAAO,eAAe,aAAa,EAAE,CACjD,CAAA;YACD,MAAM,GAAG,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAA;QAC3C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAA;YACrD,MAAM,GAAG,CAAC,aAAa,CAAC,0BAA0B,CAAC,CAAA;QACrD,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE;QACrB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;YAClD,KAAK,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAA;YACjC,OAAM;QACR,CAAC;QAED,IAAI,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,OAAM;QACR,CAAC;QAED,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAA;QAC7B,MAAM,SAAS,GAAG,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QAC3C,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,EAAE,CAAA;QAC3B,MAAM,gBAAgB,GAAG,GAAG,CAAC,OAAO,CAAC,UAAU,CAAA;QAE/C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,sCAAsC,EAAE,EAAE,SAAS,EAAE,CAAC,CAAA;YACnE,KAAK,GAAG,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAA;YACvC,OAAM;QACR,CAAC;QAED,MAAM,WAAW,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAA;QAC/C,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,CAAA;QAChD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAA;YAClE,KAAK,GAAG,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAA;YAChD,OAAM;QACR,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,cAAc,SAAS,KAAK,IAAI,EAAE,CAAC,CAAA;QAE/C;;;;WAIG;QACH;;;;WAIG;QACH,IAAI,QAAQ,GAAG,KAAK,CAAA;QACpB,MAAM,eAAe,GAAG,WAAW,CAAC,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE;YACxD,QAAQ,GAAG,IAAI,CAAA;YACf,KAAK,SAAS,CACZ,MAAM,EACN,gBAAgB,EAChB,yDAAyD,CAC1D,CAAA;QACH,CAAC,CAAC,CAAA;QAEF,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,KAAK,SAAS,CACZ,MAAM,EACN,gBAAgB,EAChB,kFAAkF,CACnF,CAAA;YACD,OAAM;QACR,CAAC;QAED,KAAK,CAAC,KAAK,IAAI,EAAE;YACf,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,cAAc,CACzC,MAAM,EACN,IAAI,EACJ,OAAO,CAAC,IAAI,EACZ,EAAE,MAAM,EAAE,eAAe,CAAC,MAAM,EAAE,CACnC,CAAA;gBACD,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACd,MAAM,SAAS,CAAC,MAAM,EAAE,gBAAgB,EAAE,KAAK,CAAC,CAAA;gBAClD,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAA;gBACzD,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACd,MAAM,SAAS,CACb,MAAM,EACN,gBAAgB,EAChB,oCAAoC,CACrC,CAAA;gBACH,CAAC;YACH,CAAC;oBAAS,CAAC;gBACT,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;YAC5B,CAAC;QACH,CAAC,CAAC,EAAE,CAAA;IACN,CAAC,CAAC,CAAA;IAEF,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACvB,OAAO,CAAC,KAAK,CAAC,oBAAoB,EAAE;YAClC,KAAK;YACL,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS;SAC/B,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,GAAG,CAAC,MAAM,EAAE,CAAA;IACZ,OAAO,GAAG,CAAA;AACZ,CAAC,CAAA"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type BotConfig = {
|
|
2
|
+
botToken: string;
|
|
3
|
+
allowedUserId: number;
|
|
4
|
+
opencode: OpencodeConfig;
|
|
5
|
+
handlerTimeoutMs: number;
|
|
6
|
+
promptTimeoutMs: number;
|
|
7
|
+
};
|
|
8
|
+
export type OpencodeConfig = {
|
|
9
|
+
serverUrl: string;
|
|
10
|
+
serverUsername: string;
|
|
11
|
+
serverPassword?: string;
|
|
12
|
+
};
|
|
13
|
+
export declare const loadConfig: () => BotConfig;
|
|
14
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,aAAa,EAAE,MAAM,CAAA;IACrB,QAAQ,EAAE,cAAc,CAAA;IACxB,gBAAgB,EAAE,MAAM,CAAA;IACxB,eAAe,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,MAAM,CAAA;IACjB,cAAc,EAAE,MAAM,CAAA;IACtB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAA;AA+BD,eAAO,MAAM,UAAU,QAAO,SAwC7B,CAAA"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const parseAllowedUserId = (rawValue) => {
|
|
2
|
+
if (!rawValue) {
|
|
3
|
+
throw new Error("Missing TELEGRAM_ALLOWED_USER_ID");
|
|
4
|
+
}
|
|
5
|
+
const parsedValue = Number(rawValue);
|
|
6
|
+
if (!Number.isInteger(parsedValue)) {
|
|
7
|
+
throw new Error("TELEGRAM_ALLOWED_USER_ID must be an integer");
|
|
8
|
+
}
|
|
9
|
+
return parsedValue;
|
|
10
|
+
};
|
|
11
|
+
const parseDurationMs = (rawValue, label) => {
|
|
12
|
+
if (!rawValue) {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
const parsedValue = Number(rawValue);
|
|
16
|
+
if (!Number.isFinite(parsedValue) || parsedValue < 0) {
|
|
17
|
+
throw new Error(`${label} must be a non-negative number`);
|
|
18
|
+
}
|
|
19
|
+
return parsedValue;
|
|
20
|
+
};
|
|
21
|
+
export const loadConfig = () => {
|
|
22
|
+
const botToken = process.env.TELEGRAM_BOT_TOKEN;
|
|
23
|
+
if (!botToken) {
|
|
24
|
+
throw new Error("Missing TELEGRAM_BOT_TOKEN");
|
|
25
|
+
}
|
|
26
|
+
const allowedUserId = parseAllowedUserId(process.env.TELEGRAM_ALLOWED_USER_ID);
|
|
27
|
+
const serverUrl = process.env.OPENCODE_SERVER_URL;
|
|
28
|
+
if (!serverUrl) {
|
|
29
|
+
throw new Error("Missing OPENCODE_SERVER_URL");
|
|
30
|
+
}
|
|
31
|
+
const opencode = {
|
|
32
|
+
serverUrl,
|
|
33
|
+
serverUsername: process.env.OPENCODE_SERVER_USERNAME ?? "opencode",
|
|
34
|
+
};
|
|
35
|
+
const serverPassword = process.env.OPENCODE_SERVER_PASSWORD;
|
|
36
|
+
if (serverPassword) {
|
|
37
|
+
opencode.serverPassword = serverPassword;
|
|
38
|
+
}
|
|
39
|
+
const promptTimeoutMs = parseDurationMs(process.env.OPENCODE_PROMPT_TIMEOUT_MS, "OPENCODE_PROMPT_TIMEOUT_MS") ?? 10 * 60 * 1000;
|
|
40
|
+
const handlerTimeoutMs = parseDurationMs(process.env.TELEGRAM_HANDLER_TIMEOUT_MS, "TELEGRAM_HANDLER_TIMEOUT_MS") ?? promptTimeoutMs + 30_000;
|
|
41
|
+
return {
|
|
42
|
+
botToken,
|
|
43
|
+
allowedUserId,
|
|
44
|
+
opencode,
|
|
45
|
+
handlerTimeoutMs,
|
|
46
|
+
promptTimeoutMs,
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAcA,MAAM,kBAAkB,GAAG,CAAC,QAA4B,EAAU,EAAE;IAClE,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAA;IACrD,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAA;IACpC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAA;IAChE,CAAC;IAED,OAAO,WAAW,CAAA;AACpB,CAAC,CAAA;AAED,MAAM,eAAe,GAAG,CACtB,QAA4B,EAC5B,KAAa,EACO,EAAE;IACtB,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAA;IACpC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,gCAAgC,CAAC,CAAA;IAC3D,CAAC;IAED,OAAO,WAAW,CAAA;AACpB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,GAAc,EAAE;IACxC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAA;IAC/C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAA;IAC/C,CAAC;IAED,MAAM,aAAa,GAAG,kBAAkB,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAA;IAC9E,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAA;IACjD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAA;IAChD,CAAC;IAED,MAAM,QAAQ,GAAmB;QAC/B,SAAS;QACT,cAAc,EAAE,OAAO,CAAC,GAAG,CAAC,wBAAwB,IAAI,UAAU;KACnE,CAAA;IAED,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAA;IAC3D,IAAI,cAAc,EAAE,CAAC;QACnB,QAAQ,CAAC,cAAc,GAAG,cAAc,CAAA;IAC1C,CAAC;IAED,MAAM,eAAe,GACnB,eAAe,CACb,OAAO,CAAC,GAAG,CAAC,0BAA0B,EACtC,4BAA4B,CAC7B,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;IACrB,MAAM,gBAAgB,GACpB,eAAe,CACb,OAAO,CAAC,GAAG,CAAC,2BAA2B,EACvC,6BAA6B,CAC9B,IAAI,eAAe,GAAG,MAAM,CAAA;IAE/B,OAAO;QACL,QAAQ;QACR,aAAa;QACb,QAAQ;QACR,gBAAgB;QAChB,eAAe;KAChB,CAAA;AACH,CAAC,CAAA"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import "dotenv/config";
|
|
2
|
+
import { loadConfig } from "./config.js";
|
|
3
|
+
import { startBot } from "./bot.js";
|
|
4
|
+
import { createOpencodeBridge } from "./opencode.js";
|
|
5
|
+
import { createProjectStore } from "./projects.js";
|
|
6
|
+
import { createChatProjectStore, createPersistentSessionStore } from "./state.js";
|
|
7
|
+
const config = loadConfig();
|
|
8
|
+
const sessionStore = createPersistentSessionStore();
|
|
9
|
+
const opencode = createOpencodeBridge(config.opencode, { sessionStore });
|
|
10
|
+
const projects = createProjectStore();
|
|
11
|
+
const chatProjects = createChatProjectStore();
|
|
12
|
+
const bot = startBot(config, opencode, projects, chatProjects);
|
|
13
|
+
process.once("SIGINT", () => bot.stop("SIGINT"));
|
|
14
|
+
process.once("SIGTERM", () => bot.stop("SIGTERM"));
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAA;AAEtB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AACnC,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAClD,OAAO,EAAE,sBAAsB,EAAE,4BAA4B,EAAE,MAAM,YAAY,CAAA;AAEjF,MAAM,MAAM,GAAG,UAAU,EAAE,CAAA;AAC3B,MAAM,YAAY,GAAG,4BAA4B,EAAE,CAAA;AACnD,MAAM,QAAQ,GAAG,oBAAoB,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,YAAY,EAAE,CAAC,CAAA;AACxE,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAA;AACrC,MAAM,YAAY,GAAG,sBAAsB,EAAE,CAAA;AAC7C,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAA;AAE9D,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAA;AAChD,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { PermissionRequest } from "@opencode-ai/sdk/v2";
|
|
2
|
+
import type { OpencodeConfig } from "./config.js";
|
|
3
|
+
export type OpencodeBridge = {
|
|
4
|
+
promptFromChat: (chatId: number, text: string, projectDir: string, options?: PromptOptions) => Promise<string>;
|
|
5
|
+
resetSession: (chatId: number, projectDir: string) => boolean;
|
|
6
|
+
getSessionOwner: (sessionId: string) => SessionOwner | null;
|
|
7
|
+
replyToPermission: (requestId: string, reply: PermissionReply, directory?: string) => Promise<boolean>;
|
|
8
|
+
startPermissionEventStream: (handlers: PermissionEventHandlers) => {
|
|
9
|
+
stop: () => void;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
export type SessionStore = {
|
|
13
|
+
getSessionId: (chatId: number, projectDir: string) => string | undefined;
|
|
14
|
+
setSessionId: (chatId: number, projectDir: string, sessionId: string) => void;
|
|
15
|
+
clearSession: (chatId: number, projectDir: string) => boolean;
|
|
16
|
+
getSessionOwner: (sessionId: string) => SessionOwner | null;
|
|
17
|
+
};
|
|
18
|
+
export type OpencodeBridgeOptions = {
|
|
19
|
+
sessionStore?: SessionStore;
|
|
20
|
+
};
|
|
21
|
+
export type PromptOptions = {
|
|
22
|
+
signal?: AbortSignal;
|
|
23
|
+
};
|
|
24
|
+
export type PermissionReply = "once" | "always" | "reject";
|
|
25
|
+
export type SessionOwner = {
|
|
26
|
+
chatId: number;
|
|
27
|
+
projectDir: string;
|
|
28
|
+
};
|
|
29
|
+
export type PermissionEventHandlers = {
|
|
30
|
+
onPermissionAsked: (event: {
|
|
31
|
+
request: PermissionRequest;
|
|
32
|
+
directory: string;
|
|
33
|
+
}) => void | Promise<void>;
|
|
34
|
+
onError?: (error: unknown) => void;
|
|
35
|
+
};
|
|
36
|
+
export declare const createSessionStore: () => SessionStore;
|
|
37
|
+
export declare const createOpencodeBridge: (config: OpencodeConfig, options?: OpencodeBridgeOptions) => OpencodeBridge;
|
|
38
|
+
//# sourceMappingURL=opencode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opencode.d.ts","sourceRoot":"","sources":["../src/opencode.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAqB,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAE/E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEjD,MAAM,MAAM,cAAc,GAAG;IAC3B,cAAc,EAAE,CACd,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,aAAa,KACpB,OAAO,CAAC,MAAM,CAAC,CAAA;IACpB,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAA;IAC7D,eAAe,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,YAAY,GAAG,IAAI,CAAA;IAC3D,iBAAiB,EAAE,CACjB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,eAAe,EACtB,SAAS,CAAC,EAAE,MAAM,KACf,OAAO,CAAC,OAAO,CAAC,CAAA;IACrB,0BAA0B,EAAE,CAAC,QAAQ,EAAE,uBAAuB,KAAK;QACjE,IAAI,EAAE,MAAM,IAAI,CAAA;KACjB,CAAA;CACF,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAA;IACxE,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAA;IAC7E,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAA;IAC7D,eAAe,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,YAAY,GAAG,IAAI,CAAA;CAC5D,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,YAAY,CAAC,EAAE,YAAY,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAE1D,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,iBAAiB,EAAE,CAAC,KAAK,EAAE;QACzB,OAAO,EAAE,iBAAiB,CAAA;QAC1B,SAAS,EAAE,MAAM,CAAA;KAClB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;CACnC,CAAA;AA8BD,eAAO,MAAM,kBAAkB,QAAO,YA4BrC,CAAA;AAED,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,cAAc,EACtB,UAAS,qBAA0B,KAClC,cAyHF,CAAA"}
|