opencode-telegram-bot 1.0.9 → 1.1.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/README.md +53 -1
- package/dist/app.d.ts +28 -14
- package/dist/index.js +2423 -642
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -112,10 +112,26 @@ These are handled directly by the Telegram bot:
|
|
|
112
112
|
| `/model` | Show current model and usage hints |
|
|
113
113
|
| `/model <keyword>` | Search models by keyword |
|
|
114
114
|
| `/model default` | Reset to the default model |
|
|
115
|
+
| `/agent` | Show current agent and switch (plan, build, ...) |
|
|
116
|
+
| `/agent <name>` | Switch directly to a named agent |
|
|
115
117
|
| `/usage` | Show token and cost usage for this session |
|
|
116
118
|
| `/help` | Show available commands |
|
|
117
119
|
|
|
118
|
-
|
|
120
|
+
### Interactive Questions
|
|
121
|
+
|
|
122
|
+
When the OpenCode agent asks a question (e.g. to clarify intent or pick from options), the bot forwards it to Telegram as **inline keyboard buttons**. Tap an option to answer, or tap **Dismiss** to reject the question.
|
|
123
|
+
|
|
124
|
+
If the bot restarts while a question is pending, it automatically re-sends the question buttons on startup so the session is not left stuck.
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
Agent: Which area do you want to focus on?
|
|
128
|
+
[Code review] [Bug fix] [New feature] [Dismiss]
|
|
129
|
+
|
|
130
|
+
You: [tap "Bug fix"]
|
|
131
|
+
Bot: Answered: Bug fix
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
The bot also registers these commands in Telegram's command menu (the `/` button), plus any OpenCode server commands discovered at startup.
|
|
119
135
|
|
|
120
136
|
### Verbose Mode
|
|
121
137
|
|
|
@@ -163,6 +179,33 @@ Other commands:
|
|
|
163
179
|
- `/model` shows the current model and usage hints
|
|
164
180
|
- `/model default` resets to the server default
|
|
165
181
|
|
|
182
|
+
### Agent Switching
|
|
183
|
+
|
|
184
|
+
OpenCode supports multiple agents: **build** (default, full edit access), **plan** (read-only analysis), and others. Use `/agent` to see and switch between them:
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
You: /agent
|
|
188
|
+
Bot: Current agent: build
|
|
189
|
+
|
|
190
|
+
Available agents:
|
|
191
|
+
- build (active) -- The default agent
|
|
192
|
+
- plan -- Plan mode. Disallows all edit tools.
|
|
193
|
+
- general -- General-purpose agent
|
|
194
|
+
- explore -- Codebase explorer
|
|
195
|
+
|
|
196
|
+
[build] [plan] [general] [explore]
|
|
197
|
+
|
|
198
|
+
You: [tap "plan"]
|
|
199
|
+
(button message is deleted)
|
|
200
|
+
Bot: Agent: plan | Model: claude-opus-4 | Verbose: off [pinned]
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Pinned Status Message
|
|
204
|
+
|
|
205
|
+
A pinned message at the top of the chat shows the current agent, model, and verbose mode. It updates automatically when any of these change — via `/agent`, `/model`, or `/verbose`. The pinned message is the only confirmation; no separate reply is sent.
|
|
206
|
+
|
|
207
|
+
Agent, model, and verbose selections are per-chat and persist across bot restarts.
|
|
208
|
+
|
|
166
209
|
## Usage
|
|
167
210
|
|
|
168
211
|
Use `/usage` to see the current session's token counts and estimated cost:
|
|
@@ -250,6 +293,15 @@ Sessions survive bot restarts. The bot saves the chat-to-session mapping to `ses
|
|
|
250
293
|
|
|
251
294
|
This means you can restart the bot (or even delete `sessions.json`) and it will reconnect to existing sessions automatically.
|
|
252
295
|
|
|
296
|
+
## Resilience
|
|
297
|
+
|
|
298
|
+
The bot is designed to survive restarts and failures:
|
|
299
|
+
|
|
300
|
+
- **Drop pending updates** -- On startup, stale Telegram updates are discarded so old button clicks and messages from a previous run are not replayed.
|
|
301
|
+
- **Pending question recovery** -- If the bot restarts while the agent is waiting for a question answer, the question is re-sent to Telegram on startup so the session can be unblocked.
|
|
302
|
+
- **Global error handler** -- Unhandled errors in Telegram update handlers are logged instead of crashing the process.
|
|
303
|
+
- **Handler timeout** -- Telegraf's handler timeout is set to 10 minutes (up from 90 seconds) to accommodate long-running LLM responses.
|
|
304
|
+
|
|
253
305
|
## Environment Variables
|
|
254
306
|
|
|
255
307
|
| Variable | Required | Description |
|
package/dist/app.d.ts
CHANGED
|
@@ -1,25 +1,33 @@
|
|
|
1
1
|
interface OpencodeClientLike {
|
|
2
2
|
session: {
|
|
3
|
-
list: (options?: any) => Promise<any>;
|
|
4
|
-
create: (
|
|
5
|
-
update: (
|
|
6
|
-
delete: (
|
|
7
|
-
get: (
|
|
8
|
-
messages: (
|
|
9
|
-
command: (
|
|
10
|
-
promptAsync: (
|
|
3
|
+
list: (params?: any, options?: any) => Promise<any>;
|
|
4
|
+
create: (params: any, options?: any) => Promise<any>;
|
|
5
|
+
update: (params: any, options?: any) => Promise<any>;
|
|
6
|
+
delete: (params: any, options?: any) => Promise<any>;
|
|
7
|
+
get: (params: any, options?: any) => Promise<any>;
|
|
8
|
+
messages: (params: any, options?: any) => Promise<any>;
|
|
9
|
+
command: (params: any, options?: any) => Promise<any>;
|
|
10
|
+
promptAsync: (params: any, options?: any) => Promise<any>;
|
|
11
11
|
};
|
|
12
12
|
command: {
|
|
13
|
-
list: (options?: any) => Promise<any>;
|
|
13
|
+
list: (params?: any, options?: any) => Promise<any>;
|
|
14
14
|
};
|
|
15
15
|
provider: {
|
|
16
|
-
list: (options?: any) => Promise<any>;
|
|
16
|
+
list: (params?: any, options?: any) => Promise<any>;
|
|
17
17
|
};
|
|
18
18
|
path: {
|
|
19
|
-
get: (options?: any) => Promise<any>;
|
|
19
|
+
get: (params?: any, options?: any) => Promise<any>;
|
|
20
20
|
};
|
|
21
21
|
event: {
|
|
22
|
-
subscribe: (options?: any) => Promise<any>;
|
|
22
|
+
subscribe: (params?: any, options?: any) => Promise<any>;
|
|
23
|
+
};
|
|
24
|
+
question: {
|
|
25
|
+
list: (params?: any, options?: any) => Promise<any>;
|
|
26
|
+
reply: (params: any, options?: any) => Promise<any>;
|
|
27
|
+
reject: (params: any, options?: any) => Promise<any>;
|
|
28
|
+
};
|
|
29
|
+
app: {
|
|
30
|
+
agents: (params?: any, options?: any) => Promise<any>;
|
|
23
31
|
};
|
|
24
32
|
}
|
|
25
33
|
interface StartOptions {
|
|
@@ -32,15 +40,18 @@ interface StartOptions {
|
|
|
32
40
|
}
|
|
33
41
|
interface TelegramBot {
|
|
34
42
|
use: (fn: (ctx: any, next: () => Promise<void>) => Promise<void> | void) => void;
|
|
43
|
+
catch: (fn: (err: unknown, ctx: any) => void) => void;
|
|
35
44
|
start: (fn: (ctx: any) => void | Promise<void>) => void;
|
|
36
45
|
help: (fn: (ctx: any) => void | Promise<void>) => void;
|
|
37
46
|
command: (command: string, fn: (ctx: any) => void | Promise<void>) => void;
|
|
38
47
|
on: (event: string, fn: (ctx: any) => void | Promise<void>) => void;
|
|
39
48
|
action: (trigger: string | RegExp, fn: (ctx: any) => void | Promise<void>) => void;
|
|
40
|
-
launch: (
|
|
49
|
+
launch: (options?: {
|
|
50
|
+
dropPendingUpdates?: boolean;
|
|
51
|
+
}) => Promise<void>;
|
|
41
52
|
stop: (reason?: string) => void;
|
|
42
53
|
telegram: {
|
|
43
|
-
sendMessage: (chatId: number, text: string, options?: Record<string, unknown>) => Promise<
|
|
54
|
+
sendMessage: (chatId: number, text: string, options?: Record<string, unknown>) => Promise<any>;
|
|
44
55
|
deleteMessage: (chatId: number, messageId: number) => Promise<void>;
|
|
45
56
|
sendDocument: (chatId: number, file: {
|
|
46
57
|
source: Buffer;
|
|
@@ -53,6 +64,9 @@ interface TelegramBot {
|
|
|
53
64
|
command: string;
|
|
54
65
|
description: string;
|
|
55
66
|
}>) => Promise<unknown>;
|
|
67
|
+
pinChatMessage: (chatId: number, messageId: number, extra?: Record<string, unknown>) => Promise<void>;
|
|
68
|
+
unpinChatMessage: (chatId: number, messageId?: number) => Promise<void>;
|
|
69
|
+
editMessageText: (chatId: number | undefined, messageId: number | undefined, inlineMessageId: string | undefined, text: string, extra?: Record<string, unknown>) => Promise<void>;
|
|
56
70
|
};
|
|
57
71
|
}
|
|
58
72
|
export declare function startTelegram(options: StartOptions): Promise<TelegramBot>;
|