opencode-telegram-link 1.0.0-rc.1
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/LICENSE +21 -0
- package/README.md +464 -0
- package/container/broker.Dockerfile +30 -0
- package/container/entrypoint.sh +19 -0
- package/dist/broker/commands.d.ts +17 -0
- package/dist/broker/commands.d.ts.map +1 -0
- package/dist/broker/dashboard-html.d.ts +2 -0
- package/dist/broker/dashboard-html.d.ts.map +1 -0
- package/dist/broker/index.d.ts +3 -0
- package/dist/broker/index.d.ts.map +1 -0
- package/dist/broker/main.d.ts +3 -0
- package/dist/broker/main.d.ts.map +1 -0
- package/dist/broker/main.js +21896 -0
- package/dist/broker/main.js.map +110 -0
- package/dist/broker/registry.d.ts +92 -0
- package/dist/broker/registry.d.ts.map +1 -0
- package/dist/broker/server.d.ts +133 -0
- package/dist/broker/server.d.ts.map +1 -0
- package/dist/config.d.ts +76 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/doctor.d.ts +21 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/i18n/catalogs.d.ts +120 -0
- package/dist/i18n/catalogs.d.ts.map +1 -0
- package/dist/i18n/index.d.ts +10 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/opencode/bridge.d.ts +39 -0
- package/dist/opencode/bridge.d.ts.map +1 -0
- package/dist/opencode/config-helper.d.ts +20 -0
- package/dist/opencode/config-helper.d.ts.map +1 -0
- package/dist/opencode/events.d.ts +47 -0
- package/dist/opencode/events.d.ts.map +1 -0
- package/dist/opencode/index.d.ts +4 -0
- package/dist/opencode/index.d.ts.map +1 -0
- package/dist/plugin/client.d.ts +57 -0
- package/dist/plugin/client.d.ts.map +1 -0
- package/dist/plugin/commands.d.ts +4 -0
- package/dist/plugin/commands.d.ts.map +1 -0
- package/dist/plugin/index.d.ts +2 -0
- package/dist/plugin/index.d.ts.map +1 -0
- package/dist/plugin.d.ts +11 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +16913 -0
- package/dist/plugin.js.map +95 -0
- package/dist/protocol/index.d.ts +792 -0
- package/dist/protocol/index.d.ts.map +1 -0
- package/dist/protocol/index.js +14540 -0
- package/dist/protocol/index.js.map +84 -0
- package/dist/setup.d.ts +77 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/state/database.d.ts +159 -0
- package/dist/state/database.d.ts.map +1 -0
- package/dist/state/discovery.d.ts +16 -0
- package/dist/state/discovery.d.ts.map +1 -0
- package/dist/state/identity.d.ts +19 -0
- package/dist/state/identity.d.ts.map +1 -0
- package/dist/state/index.d.ts +4 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/telegram/api.d.ts +212 -0
- package/dist/telegram/api.d.ts.map +1 -0
- package/dist/telegram/authorization.d.ts +25 -0
- package/dist/telegram/authorization.d.ts.map +1 -0
- package/dist/telegram/commands.d.ts +20 -0
- package/dist/telegram/commands.d.ts.map +1 -0
- package/dist/telegram/index.d.ts +9 -0
- package/dist/telegram/index.d.ts.map +1 -0
- package/dist/telegram/interaction.d.ts +49 -0
- package/dist/telegram/interaction.d.ts.map +1 -0
- package/dist/telegram/outbox.d.ts +46 -0
- package/dist/telegram/outbox.d.ts.map +1 -0
- package/dist/telegram/poller.d.ts +26 -0
- package/dist/telegram/poller.d.ts.map +1 -0
- package/dist/telegram/render.d.ts +16 -0
- package/dist/telegram/render.d.ts.map +1 -0
- package/dist/telegram/transcriber.d.ts +20 -0
- package/dist/telegram/transcriber.d.ts.map +1 -0
- package/dist/uninstall.d.ts +12 -0
- package/dist/uninstall.d.ts.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/docker-compose.yml +19 -0
- package/package.json +73 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 OpenCode Telegram Link contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
# OpenCode Telegram Notifier & OpenCode Commander
|
|
2
|
+
|
|
3
|
+
OpenCode Telegram Notifier is a privacy-first OpenCode plugin and multi-host management gateway for asynchronous notifications, interactive inline buttons, safe remote replies, and proactive remote task dispatching. It is designed for developers who run OpenCode across multiple projects and multiple computers (dev machine, laptop, VPS) while routing every Telegram and Web interaction to the exact originating host, process, and workspace window.
|
|
4
|
+
|
|
5
|
+
> Version: **v1.0.0-rc.1** (OpenCode Commander Web Dashboard, Proactive Remote Dispatch, Multi-Engine Voice STT, Multi-Host Gateway & Node Agent Architecture).
|
|
6
|
+
> Status: Release Candidate 1. Install from a release tarball or source checkout until the first public npm package is published.
|
|
7
|
+
|
|
8
|
+
[繁體中文總覽 (Traditional Chinese)](docs/README.zh-TW.md)
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Features & Highlights (v1.0.0-rc.1)
|
|
13
|
+
|
|
14
|
+
- 🖥️ **OpenCode Commander (Web GUI Dashboard)**: Built-in modern Glassmorphism Web Console (`http://<gateway-ip>:42617/dashboard`) providing real-time visibility, live metrics, and centralized cluster management.
|
|
15
|
+
- 🌐 **Cluster Topology & 1-to-1 Window Mapping**: Live cards for all connected computers and OpenCode workspace windows with real-time session indicators and task counters.
|
|
16
|
+
- 🚀 **Proactive Remote Dispatch**: Dispatch new prompts and start new tasks on any connected machine or idle project window directly from the Web Dashboard or Telegram voice/text—no need to switch to VS Code!
|
|
17
|
+
- 🎙️ **Multi-Engine Voice Transcription (Voice STT)**:
|
|
18
|
+
- **Cloudflare Workers AI** (`@cf/openai/whisper-large-v3-turbo` with 10,000 free requests/day).
|
|
19
|
+
- **Groq Whisper** (`whisper-large-v3-turbo` / `whisper-large-v3`).
|
|
20
|
+
- **OpenAI Whisper** (`whisper-1`).
|
|
21
|
+
- **Custom / Self-Hosted Whisper Endpoint**.
|
|
22
|
+
- **Independent Multi-Provider Credentials Retention**: Switch between speech providers seamlessly without losing API tokens.
|
|
23
|
+
- **Live Key Verification & Connection Testing**: In-dashboard one-click authentication and ping testing.
|
|
24
|
+
- 📱 **Mobile & Tablet Responsive Web Design (RWD)**: Touch-friendly navigation tabs, auto-stacking cards, and horizontal scrollable session tables for full smartphone/tablet control.
|
|
25
|
+
- 🛑 **Live Session Cancellation**: One-click remote task cancellation (`[ 🛑 Cancel ]`) from the Web Dashboard or Telegram inline buttons.
|
|
26
|
+
- 🌐 **Multi-Host Hub-and-Spoke Gateway**: Control multiple computers (e.g. Office PC, MacBook, Live VPS) from a single Telegram Bot without message collisions (`409 Conflict`).
|
|
27
|
+
- 🏷️ **Host Tagging**: Notification headers prominently display the origin machine (e.g., `🖥️ [MacBook]` or `☁️ [Live-VPS]`).
|
|
28
|
+
- 🔄 **Cross-Host Reverse Routing**: Tap buttons or reply to any notification—the Central Gateway routes commands back to the exact machine and session.
|
|
29
|
+
- 🔘 **Interactive Inline Buttons**: Single-tap remote permission approvals (`[ ✅ Allow Once ]`, `[ ⚡ Always Allow ]`, `[ ❌ Reject ]`) and question option selections.
|
|
30
|
+
- 📝 **AI Execution Summaries**: Task completion notifications automatically include a concise AI-generated summary of actions taken.
|
|
31
|
+
- ⏰ **Host Local Time**: Timestamps formatted in the server host's local timezone.
|
|
32
|
+
- 🧹 **Interactive Uninstaller**: One-command safe cleanup (`bun run uninstall`) for database, state, tokens, and `opencode.json` configurations.
|
|
33
|
+
- 🌐 **Bilingual Support**: Full Traditional Chinese (`zh-TW`) and English (`en`) notifications and dashboard guidance.
|
|
34
|
+
|
|
35
|
+
## Architecture
|
|
36
|
+
|
|
37
|
+
```text
|
|
38
|
+
[ Node Agent 1 (MacBook) ] ──── (WebSocket) ──┐
|
|
39
|
+
▼
|
|
40
|
+
[ Node Agent 2 (Live VPS) ] ─── (WebSocket) ──► [ Central Gateway Broker ] ──► Telegram Bot API
|
|
41
|
+
▲ (Local or VPS) │
|
|
42
|
+
[ Local OpenCode ] ───────────────────────────┘ ▼
|
|
43
|
+
[ Telegram App (Mobile) ]
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
- **Gateway Mode (Default)**: Runs as the singleton Telegram Poller. Serves local OpenCode instances and accepts reverse WebSocket connections from remote Node Agents.
|
|
47
|
+
- **Node Agent Mode**: Lightweight mode for second/third machines that connects to the Central Gateway, allowing all machines to share one Telegram Bot seamlessly.
|
|
48
|
+
|
|
49
|
+
## Security and Privacy
|
|
50
|
+
|
|
51
|
+
- Central Gateway and Node Agents authenticate over WebSocket using secure tokens.
|
|
52
|
+
- Notifications omit transcripts, source code, tool output, local filesystem paths, and secrets by default.
|
|
53
|
+
- Telegram user and private-chat identities are pinned during Gateway setup.
|
|
54
|
+
- Offline, stale, ambiguous, or unauthorized actions fail closed and are never queued.
|
|
55
|
+
|
|
56
|
+
## Installation & Setup
|
|
57
|
+
|
|
58
|
+
Requirements:
|
|
59
|
+
- Bun `>=1.3.0`.
|
|
60
|
+
- OpenCode with `@opencode-ai/plugin` `>=1.18.0 <2`.
|
|
61
|
+
- A user-owned Telegram bot token from BotFather (only needed on the Gateway machine).
|
|
62
|
+
|
|
63
|
+
## Quick Start (4-Step Setup)
|
|
64
|
+
|
|
65
|
+
On any machine (development host or remote server) where you want to enable notifications:
|
|
66
|
+
|
|
67
|
+
```sh
|
|
68
|
+
# 1. Clone the repository
|
|
69
|
+
git clone https://github.com/proamo/opencode_notification.git
|
|
70
|
+
cd opencode_notification
|
|
71
|
+
|
|
72
|
+
# 2. Install dependencies
|
|
73
|
+
bun install
|
|
74
|
+
|
|
75
|
+
# 3. Build the project
|
|
76
|
+
bun run build
|
|
77
|
+
|
|
78
|
+
# 4. Run the interactive setup wizard
|
|
79
|
+
bun run setup
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
*(Note: Once published to npm, you will also be able to run `bunx opencode-telegram-link setup` directly).*
|
|
83
|
+
|
|
84
|
+
The interactive wizard will:
|
|
85
|
+
- Ask for your preferred language (Traditional Chinese / English).
|
|
86
|
+
- Ask for your preferred deployment mode:
|
|
87
|
+
- **1) Native Mode (Default)**: Broker runs as a lightweight background process, auto-spawned by OpenCode.
|
|
88
|
+
- **2) Docker Container Mode**: The wizard will **automatically build and start the Docker container in the background** via Docker Compose!
|
|
89
|
+
- Prompt and instantly verify your Bot Token with Telegram.
|
|
90
|
+
- Guide you through private chat pairing with a short-lived nonce code.
|
|
91
|
+
- Automatically save the token in a secure private state file (`0600`/`0700`).
|
|
92
|
+
- Automatically detect and update your `opencode.json` configuration file.
|
|
93
|
+
- Send a test welcome notification to your Telegram!
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## 🖥️ OpenCode Commander (Web Dashboard)
|
|
98
|
+
|
|
99
|
+
Once the Gateway is running, navigate to:
|
|
100
|
+
|
|
101
|
+
```text
|
|
102
|
+
http://localhost:42617/dashboard
|
|
103
|
+
# Or from another device / smartphone:
|
|
104
|
+
http://<gateway-ip>:42617/dashboard
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Dashboard Tabs & Capabilities:
|
|
108
|
+
1. **🖥️ Cluster Topology (Nodes)**:
|
|
109
|
+
- Live overview of all connected machines and OpenCode workspace windows (1-to-1 live mapping).
|
|
110
|
+
- Real-time status: Active sessions, running subagent counts, and idle window indicators.
|
|
111
|
+
- One-click **`🚀 Dispatch`** to start a new prompt on any window.
|
|
112
|
+
2. **📝 Active Sessions (Sessions)**:
|
|
113
|
+
- Live stream of all ongoing tasks across the entire cluster.
|
|
114
|
+
- One-click **`🛑 Cancel`** to immediately abort runaway tasks.
|
|
115
|
+
3. **🚀 Proactive Remote Dispatch (Dispatch)**:
|
|
116
|
+
- Select any connected machine / workspace (or auto-detect).
|
|
117
|
+
- Enter your prompt and click **`🚀 Dispatch Task`** to launch tasks remotely.
|
|
118
|
+
4. **⚙️ System Settings (Settings)**:
|
|
119
|
+
- Configure **Voice STT Engine** (Cloudflare Workers AI, Groq Whisper, OpenAI Whisper, Custom Endpoint).
|
|
120
|
+
- **Independent Multi-Provider Credentials Retention**: Switch between providers without losing your saved API keys.
|
|
121
|
+
- In-dashboard **`⚡ Test & Verify Key`** connection diagnostic box.
|
|
122
|
+
- Dynamic zero-downtime hot reloading of speech engine credentials.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## 🎙️ Telegram Voice Input
|
|
127
|
+
|
|
128
|
+
Send Telegram voice messages or audio files directly to the Bot! The Gateway transcribes voice messages using your configured speech engine:
|
|
129
|
+
|
|
130
|
+
1. **Cloudflare Workers AI (Recommended)**:
|
|
131
|
+
- Model: `@cf/openai/whisper-large-v3-turbo`
|
|
132
|
+
- Free tier: **10,000 requests per day**.
|
|
133
|
+
- Requires: Cloudflare Account ID and API Token.
|
|
134
|
+
2. **Groq Whisper**:
|
|
135
|
+
- Model: `whisper-large-v3-turbo` / `whisper-large-v3`
|
|
136
|
+
- Ultra-low latency transcription.
|
|
137
|
+
- Requires: Groq API Key (`gsk_...`).
|
|
138
|
+
3. **OpenAI Whisper**:
|
|
139
|
+
- Model: `whisper-1`
|
|
140
|
+
- Requires: OpenAI API Key (`sk-...`).
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Multi-Host & Node Agent Setup (Connecting a 2nd Machine)
|
|
145
|
+
|
|
146
|
+
To share the **same Telegram Bot** across multiple computers (e.g. Machine A as Central Gateway, Machine B as Node Agent):
|
|
147
|
+
|
|
148
|
+
### Step 1: Set up Machine A (Central Gateway)
|
|
149
|
+
Run `bun run setup` on Machine A, choose `1) Standalone Gateway Mode`, and pair your Telegram Bot.
|
|
150
|
+
Ensure Machine A's Broker WebSocket port (`42617`) is accessible by Machine B (e.g., via LAN, Tailscale VPN, or reverse proxy).
|
|
151
|
+
|
|
152
|
+
### Step 2: Set up Machine B (Node Agent)
|
|
153
|
+
On Machine B (e.g., your laptop or another server):
|
|
154
|
+
1. Run `bun run setup`.
|
|
155
|
+
2. Choose **`2) Node Agent Mode`**.
|
|
156
|
+
3. Enter your machine label (e.g., `MacBook` or `Live-VPS`).
|
|
157
|
+
4. Enter Machine A's Gateway WebSocket URL (e.g., `ws://192.168.1.100:42617`, `ws://100.x.x.x:42617` via Tailscale, or `wss://gateway.example.com`).
|
|
158
|
+
5. Enter Gateway Secret Token (if configured).
|
|
159
|
+
|
|
160
|
+
### Machine B `opencode.json` Example
|
|
161
|
+
```json
|
|
162
|
+
{
|
|
163
|
+
"plugin": {
|
|
164
|
+
"opencode-telegram-link": {
|
|
165
|
+
"mode": "local",
|
|
166
|
+
"role": "node",
|
|
167
|
+
"hostLabel": "MacBook",
|
|
168
|
+
"gateway": {
|
|
169
|
+
"url": "ws://gateway-host-ip:42617",
|
|
170
|
+
"secret": "your-secret-token"
|
|
171
|
+
},
|
|
172
|
+
"notifications": {
|
|
173
|
+
"completion": true,
|
|
174
|
+
"error": true,
|
|
175
|
+
"question": true,
|
|
176
|
+
"permission": true
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
> 💡 **How to get the Gateway Secret Token?**
|
|
184
|
+
> Run the following command on Machine A (Gateway) to view and copy the secret token:
|
|
185
|
+
> `cat ~/.local/state/opencode-telegram-link/broker-secret`
|
|
186
|
+
> (Or on Windows: `type %USERPROFILE%\.local\state\opencode-telegram-link\broker-secret`).
|
|
187
|
+
|
|
188
|
+
Notifications from Machine B will automatically display `🖥️ [MacBook]` in Telegram, and button clicks or replies from Telegram will automatically route back to Machine B!
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Non-Interactive & Scripted Setup (CI / Automated Environments)
|
|
193
|
+
|
|
194
|
+
If you prefer scripted setup with environment variables or flags:
|
|
195
|
+
|
|
196
|
+
```sh
|
|
197
|
+
# Pair with short-lived nonce
|
|
198
|
+
OPENCODE_TELEGRAM_BOT_TOKEN='123456:REPLACE_WITH_BOTFATHER_TOKEN' \
|
|
199
|
+
opencode-telegram-broker setup --pair --locale en
|
|
200
|
+
|
|
201
|
+
# Or specify existing Telegram User and Chat IDs directly
|
|
202
|
+
OPENCODE_TELEGRAM_BOT_TOKEN_FILE=~/.local/state/opencode-telegram-link/telegram-bot-token \
|
|
203
|
+
opencode-telegram-broker setup --user-id 123456789 --chat-id 123456789 --locale en
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Configuration
|
|
207
|
+
|
|
208
|
+
OpenCode supports both **Global Configuration** and **Project-Specific Configuration**:
|
|
209
|
+
|
|
210
|
+
- **Global Config**: `~/.config/opencode/opencode.json` (applied to all projects).
|
|
211
|
+
- **Project-Specific Config**: `<project-root>/.opencode/opencode.json` or `<project-root>/opencode.json`.
|
|
212
|
+
|
|
213
|
+
> ⚠️ **Important: Project Config Overrides Global Plugins**
|
|
214
|
+
> If your project contains its own `.opencode/opencode.json` or `opencode.json` that defines a `"plugin"` array, OpenCode will use that workspace `"plugin"` list and **will not inherit** plugins from your global configuration.
|
|
215
|
+
>
|
|
216
|
+
> Therefore, if a project has its own `opencode.json`, you **must** also add the notification plugin to that project's configuration.
|
|
217
|
+
|
|
218
|
+
### How to Configure a Project with its Own `opencode.json`
|
|
219
|
+
|
|
220
|
+
#### Option 1: Manual Edit (Recommended)
|
|
221
|
+
Open your project's `.opencode/opencode.json` (or `opencode.json`) and add the absolute directory path to the `"plugin"` array:
|
|
222
|
+
|
|
223
|
+
```json
|
|
224
|
+
{
|
|
225
|
+
"$schema": "https://opencode.ai/config.json",
|
|
226
|
+
"plugin": [
|
|
227
|
+
"oc-codex-multi-auth@6.12.1",
|
|
228
|
+
"/home/you/opencode_notification"
|
|
229
|
+
]
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
> 💡 **Local Install vs npm Package**: Until published on the official npm registry, specify the absolute directory path to this repository. Once published, you can simply write `"opencode-telegram-link"`. The plugin automatically reads the paired credentials from the secure local state directory.
|
|
234
|
+
|
|
235
|
+
#### Option 2: Automatic Injection via Setup Wizard
|
|
236
|
+
You can run the setup tool directly inside your target project workspace:
|
|
237
|
+
|
|
238
|
+
```sh
|
|
239
|
+
cd /path/to/your/project
|
|
240
|
+
bun run --cwd /path/to/opencode_notification setup --config-only
|
|
241
|
+
```
|
|
242
|
+
The wizard will automatically detect the local workspace `opencode.json`, create a `.bak` backup, and inject the plugin entry safely.
|
|
243
|
+
|
|
244
|
+
### Permission Configuration (Automatic Command Execution)
|
|
245
|
+
|
|
246
|
+
To allow shell and file operations without manual approval prompts, configure permissions in `opencode.json` or in your `.opencode/agent/<agent-name>.md`:
|
|
247
|
+
|
|
248
|
+
```json
|
|
249
|
+
{
|
|
250
|
+
"permission": {
|
|
251
|
+
"edit": "allow",
|
|
252
|
+
"bash": "allow",
|
|
253
|
+
"webfetch": "allow",
|
|
254
|
+
"task": "allow",
|
|
255
|
+
"external_directory": "allow"
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Use exactly one of `telegram.tokenFile` or `telegram.botToken`. `tokenFile` is recommended because the file permission checker rejects group-readable, world-readable, non-regular, and wrong-owner token files on non-Windows platforms. Inline tokens are accepted for constrained environments but are easier to leak through config sharing.
|
|
261
|
+
|
|
262
|
+
## Broker Commands
|
|
263
|
+
|
|
264
|
+
Start or reuse the native loopback broker:
|
|
265
|
+
|
|
266
|
+
```sh
|
|
267
|
+
opencode-telegram-broker start
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
Check readiness and diagnostics:
|
|
271
|
+
|
|
272
|
+
```sh
|
|
273
|
+
opencode-telegram-broker status
|
|
274
|
+
opencode-telegram-broker doctor
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
Send a credential and chat connectivity test without creating a routable session action:
|
|
278
|
+
|
|
279
|
+
```sh
|
|
280
|
+
OPENCODE_TELEGRAM_BOT_TOKEN_FILE=~/.local/state/opencode-telegram-link/telegram-bot-token \
|
|
281
|
+
opencode-telegram-broker test-notification --chat-id 123456789 --locale en
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
Stop the broker without terminating OpenCode sessions:
|
|
285
|
+
|
|
286
|
+
```sh
|
|
287
|
+
opencode-telegram-broker stop
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Purge operational routing state only after the broker is stopped:
|
|
291
|
+
|
|
292
|
+
```sh
|
|
293
|
+
opencode-telegram-broker purge-state
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Rotate the stored token file after changing the token through BotFather:
|
|
297
|
+
|
|
298
|
+
```sh
|
|
299
|
+
OPENCODE_TELEGRAM_BOT_TOKEN='123456:NEW_TOKEN' \
|
|
300
|
+
opencode-telegram-broker rotate-credential --token-file ~/.local/state/opencode-telegram-link/telegram-bot-token
|
|
301
|
+
opencode-telegram-broker stop
|
|
302
|
+
opencode-telegram-broker start
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
## Sample Notifications
|
|
306
|
+
|
|
307
|
+
### 1. Task Completed Notification (with AI Summary & Local Time)
|
|
308
|
+
|
|
309
|
+
```text
|
|
310
|
+
OpenCode Completed
|
|
311
|
+
Project: api-server
|
|
312
|
+
Session: Fix flaky checkout test
|
|
313
|
+
Time: 2026-08-26 09:30:15
|
|
314
|
+
|
|
315
|
+
📝 Summary:
|
|
316
|
+
Fixed race condition in Stripe webhook handler by wrapping state lookup in a database transaction. Added unit test.
|
|
317
|
+
|
|
318
|
+
Reply to this message to continue the session.
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### 2. Interactive Permission Request (V1.5 Inline Keyboard)
|
|
322
|
+
|
|
323
|
+
```text
|
|
324
|
+
OpenCode Needs Permission
|
|
325
|
+
Project: api-server
|
|
326
|
+
Session: Fix flaky checkout test
|
|
327
|
+
Time: 2026-08-26 09:32:00
|
|
328
|
+
Action: Execute bash command `npm run test:e2e`
|
|
329
|
+
|
|
330
|
+
[ ✅ Allow Once ] [ ⚡ Always Allow ] [ ❌ Reject ]
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### 3. Interactive Question Notification (V1.5 Option Buttons)
|
|
334
|
+
|
|
335
|
+
```text
|
|
336
|
+
OpenCode Needs Input
|
|
337
|
+
Project: api-server
|
|
338
|
+
Question: Which migration strategy should be used?
|
|
339
|
+
Time: 2026-08-26 09:35:10
|
|
340
|
+
|
|
341
|
+
[ Blue-Green ] [ Canary ] [ In-Place ]
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
Notification bodies are intentionally minimal. They omit raw transcripts, source code, tool output, local filesystem paths, and secrets by default.
|
|
345
|
+
|
|
346
|
+
## Reply & Interaction Behavior
|
|
347
|
+
|
|
348
|
+
- **Interactive Permission Approval**: Tap `[ ✅ Allow Once ]`, `[ ⚡ Always Allow ]`, or `[ ❌ Reject ]` on the Telegram message. The Broker validates a single-use token and remotely unblocks OpenCode in the terminal immediately!
|
|
349
|
+
- **Interactive Question Selection**: Tap an option button on the Telegram question notification, or reply directly with text.
|
|
350
|
+
- **Continue Session**: Reply directly with text to any completed task notification to send a new prompt to that exact OpenCode session (active for 24 hours).
|
|
351
|
+
|
|
352
|
+
Rejected replies receive localized feedback when the route is expired, offline, unauthorized, or rejected by OpenCode. Offline commands are not queued.
|
|
353
|
+
|
|
354
|
+
## 🤖 Telegram Slash Commands (Mobile Commander)
|
|
355
|
+
|
|
356
|
+
You can manage your multi-host cluster directly inside Telegram using slash commands:
|
|
357
|
+
|
|
358
|
+
| Command | Description | Example |
|
|
359
|
+
| :--- | :--- | :--- |
|
|
360
|
+
| `/help` | Show command menu and interactive guide | `/help` |
|
|
361
|
+
| `/status` | View Central Gateway health, uptime, memory, and version | `/status` |
|
|
362
|
+
| `/nodes` | List all currently connected machines and active projects | `/nodes` |
|
|
363
|
+
| `/sessions` | List active sessions across all connected nodes | `/sessions` |
|
|
364
|
+
| `/run <target> <prompt>` | Dispatch new prompt to a machine, project, or resume session | `/run openclaw check test logs`<br>`/run ses_abc123 continue debugging` |
|
|
365
|
+
| `/cancel <session_id>` | Abort a running session safely (fail-closed disambiguation) | `/cancel ses_abc123` |
|
|
366
|
+
|
|
367
|
+
## Docker Broker
|
|
368
|
+
|
|
369
|
+
Native mode is recommended. Docker mode runs only the broker in a container; OpenCode and plugins continue to run on the host.
|
|
370
|
+
|
|
371
|
+
### Quick Start with Docker Compose (Recommended)
|
|
372
|
+
|
|
373
|
+
```sh
|
|
374
|
+
docker compose up -d --build
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
To stop:
|
|
378
|
+
```sh
|
|
379
|
+
docker compose down
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Manual Container Run
|
|
383
|
+
|
|
384
|
+
```sh
|
|
385
|
+
bun run build
|
|
386
|
+
docker build -f container/broker.Dockerfile -t opencode-telegram-broker:local .
|
|
387
|
+
|
|
388
|
+
docker run -d --rm \
|
|
389
|
+
--name opencode-telegram-broker \
|
|
390
|
+
-p 127.0.0.1:42617:42617 \
|
|
391
|
+
-v opencode-telegram-state:/state \
|
|
392
|
+
-v "$HOME/.local/state/opencode-telegram-link/telegram-bot-token:/run/secrets/telegram-bot-token:ro" \
|
|
393
|
+
-e OPENCODE_TELEGRAM_BOT_TOKEN_FILE=/run/secrets/telegram-bot-token \
|
|
394
|
+
opencode-telegram-broker:local start
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
Do not publish the port as `42617:42617`; include the `127.0.0.1` host IP so Docker does not expose the broker on every host interface. Do not run native and Docker brokers at the same time for one state directory and bot token.
|
|
398
|
+
|
|
399
|
+
## Diagnostics
|
|
400
|
+
|
|
401
|
+
Use `opencode-telegram-broker doctor` first when setup fails or notifications stop. It checks configuration validity, token-file permissions, broker reachability, singleton conflicts, loopback binding, Telegram API connectivity, allowed identities, catalogs, and OpenCode compatibility. Output is sanitized and should not include bot tokens, broker secrets, reply text, source code, or file contents.
|
|
402
|
+
|
|
403
|
+
Common outcomes:
|
|
404
|
+
|
|
405
|
+
- `ready: true`: setup is usable.
|
|
406
|
+
- `warning`: setup can run but has an operational limitation, such as no active plugin registration yet.
|
|
407
|
+
- `failure`: fix the reported remediation before expecting notifications or replies.
|
|
408
|
+
- Telegram `409 Conflict`: the same bot is being polled elsewhere; stop the other consumer or use a different bot.
|
|
409
|
+
|
|
410
|
+
## Update
|
|
411
|
+
|
|
412
|
+
1. Stop idle OpenCode sessions or leave them running if you only update a compatible patch release.
|
|
413
|
+
2. Update the package or rebuild the checkout.
|
|
414
|
+
3. Restart the broker with `opencode-telegram-broker stop` and `opencode-telegram-broker start`.
|
|
415
|
+
4. Restart OpenCode processes if doctor reports a protocol or compatibility mismatch.
|
|
416
|
+
5. Run `opencode-telegram-broker doctor` and `opencode-telegram-broker test-notification --chat-id <id>`.
|
|
417
|
+
|
|
418
|
+
The broker and plugin negotiate protocol major version `1`. Incompatible upgrades fail closed instead of silently downgrading routing or reply behavior.
|
|
419
|
+
|
|
420
|
+
## Uninstall
|
|
421
|
+
|
|
422
|
+
Run the interactive uninstaller wizard:
|
|
423
|
+
|
|
424
|
+
```sh
|
|
425
|
+
bun run uninstall
|
|
426
|
+
# Or
|
|
427
|
+
opencode-telegram-broker uninstall
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
The uninstaller will safely:
|
|
431
|
+
1. Stop the running broker process.
|
|
432
|
+
2. Search and remove the plugin configuration from `opencode.json` files (with `.bak` backup).
|
|
433
|
+
3. Clear SQLite database and message routing state.
|
|
434
|
+
4. Prompt to remove the private token file and state directory.
|
|
435
|
+
|
|
436
|
+
## Specifications
|
|
437
|
+
|
|
438
|
+
- [Proposal](openspec/changes/design-telegram-notifier/proposal.md)
|
|
439
|
+
- [Technical design](openspec/changes/design-telegram-notifier/design.md)
|
|
440
|
+
- [Telegram notifications](openspec/changes/design-telegram-notifier/specs/telegram-notifications/spec.md)
|
|
441
|
+
- [Local instance routing](openspec/changes/design-telegram-notifier/specs/local-instance-routing/spec.md)
|
|
442
|
+
- [Telegram session interaction](openspec/changes/design-telegram-notifier/specs/telegram-session-interaction/spec.md)
|
|
443
|
+
- [Setup and diagnostics](openspec/changes/design-telegram-notifier/specs/setup-and-diagnostics/spec.md)
|
|
444
|
+
- [Implementation tasks](openspec/changes/design-telegram-notifier/tasks.md)
|
|
445
|
+
- [Future Architecture & Roadmap (V2/V3)](docs/future-architecture-spec.md)
|
|
446
|
+
- [Compatibility policy](docs/compatibility.md)
|
|
447
|
+
- [Local state management](docs/state-management.md)
|
|
448
|
+
- [Threat model](docs/threat-model.md)
|
|
449
|
+
- [Local broker protocol](docs/protocol.md)
|
|
450
|
+
- [Data retention](docs/data-retention.md)
|
|
451
|
+
- [Contributor guide](docs/contributing.md)
|
|
452
|
+
- [GitNexus release readiness](docs/gitnexus-release-readiness.md)
|
|
453
|
+
|
|
454
|
+
The OpenSpec artifacts are the current source of truth. Requirements use RFC 2119 language and testable scenarios.
|
|
455
|
+
|
|
456
|
+
## Technology
|
|
457
|
+
|
|
458
|
+
- TypeScript and Bun
|
|
459
|
+
- `@opencode-ai/plugin` and the OpenCode SDK
|
|
460
|
+
- Telegram Bot API with long polling
|
|
461
|
+
- Authenticated loopback WebSocket protocol
|
|
462
|
+
- SQLite for minimal route, delivery, and idempotency state
|
|
463
|
+
|
|
464
|
+
The project uses the MIT License. `opencode-telegram-link` is the current working npm package name and may be changed before the first public release.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# syntax=docker/dockerfile:1
|
|
2
|
+
|
|
3
|
+
FROM oven/bun:1.3.14-slim AS runtime
|
|
4
|
+
|
|
5
|
+
WORKDIR /app
|
|
6
|
+
|
|
7
|
+
ENV NODE_ENV=production \
|
|
8
|
+
OPENCODE_TELEGRAM_CONTAINER=1 \
|
|
9
|
+
OPENCODE_TELEGRAM_BROKER_STATE_DIR=/state \
|
|
10
|
+
OPENCODE_TELEGRAM_BROKER_BIND_HOST=0.0.0.0 \
|
|
11
|
+
OPENCODE_TELEGRAM_BROKER_PORT=42617
|
|
12
|
+
|
|
13
|
+
RUN apt-get update \
|
|
14
|
+
&& apt-get install -y --no-install-recommends gosu \
|
|
15
|
+
&& rm -rf /var/lib/apt/lists/* \
|
|
16
|
+
&& groupadd -g 10001 opencode \
|
|
17
|
+
&& useradd -u 10001 -g opencode -d /nonexistent -s /usr/sbin/nologin opencode \
|
|
18
|
+
&& mkdir -p /state \
|
|
19
|
+
&& chown -R opencode:opencode /app /state
|
|
20
|
+
|
|
21
|
+
COPY dist ./dist
|
|
22
|
+
COPY package.json README.md LICENSE ./
|
|
23
|
+
COPY container/entrypoint.sh /app/entrypoint.sh
|
|
24
|
+
RUN chmod +x /app/entrypoint.sh
|
|
25
|
+
|
|
26
|
+
VOLUME ["/state"]
|
|
27
|
+
EXPOSE 42617/tcp
|
|
28
|
+
|
|
29
|
+
ENTRYPOINT ["/app/entrypoint.sh"]
|
|
30
|
+
CMD ["start"]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
if [ "$(id -u)" = "0" ]; then
|
|
5
|
+
if [ -d "/state" ]; then
|
|
6
|
+
STATE_UID=$(stat -c '%u' /state 2>/dev/null || stat -f '%u' /state 2>/dev/null || echo "")
|
|
7
|
+
STATE_GID=$(stat -c '%g' /state 2>/dev/null || stat -f '%g' /state 2>/dev/null || echo "")
|
|
8
|
+
if [ "$STATE_UID" != "" ] && [ "$STATE_UID" != "0" ]; then
|
|
9
|
+
usermod -o -u "$STATE_UID" opencode 2>/dev/null || true
|
|
10
|
+
if [ "$STATE_GID" != "" ] && [ "$STATE_GID" != "0" ]; then
|
|
11
|
+
groupmod -o -g "$STATE_GID" opencode 2>/dev/null || true
|
|
12
|
+
fi
|
|
13
|
+
fi
|
|
14
|
+
fi
|
|
15
|
+
chown -R opencode:opencode /app 2>/dev/null || true
|
|
16
|
+
exec gosu opencode bun /app/dist/broker/main.js "$@"
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
exec bun /app/dist/broker/main.js "$@"
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type BrokerServer, type StartBrokerOptions } from "./server";
|
|
2
|
+
type CommandStreams = {
|
|
3
|
+
stdout: Pick<NodeJS.WriteStream, "write">;
|
|
4
|
+
stderr: Pick<NodeJS.WriteStream, "write">;
|
|
5
|
+
};
|
|
6
|
+
export type BrokerCliOptions = {
|
|
7
|
+
argv?: string[];
|
|
8
|
+
env?: NodeJS.ProcessEnv;
|
|
9
|
+
stdout?: Pick<NodeJS.WriteStream, "write">;
|
|
10
|
+
stderr?: Pick<NodeJS.WriteStream, "write">;
|
|
11
|
+
fetch?: typeof fetch;
|
|
12
|
+
onStarted?: (broker: BrokerServer) => void | Promise<void>;
|
|
13
|
+
};
|
|
14
|
+
export declare function runBrokerCli(options?: BrokerCliOptions): Promise<number | undefined>;
|
|
15
|
+
export declare function runStopCommand(options: StartBrokerOptions, streams: CommandStreams, fetchImplementation?: typeof fetch): Promise<number>;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=commands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/broker/commands.ts"],"names":[],"mappings":"AAMA,OAAO,EAEL,KAAK,YAAY,EAEjB,KAAK,kBAAkB,EAExB,MAAM,UAAU,CAAC;AAElB,KAAK,cAAc,GAAG;IACpB,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC1C,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC3C,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC3C,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5D,CAAC;AAEF,wBAAsB,YAAY,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAqC9F;AA2DD,wBAAsB,cAAc,CAClC,OAAO,EAAE,kBAAkB,EAC3B,OAAO,EAAE,cAAc,EACvB,mBAAmB,GAAE,OAAO,KAAa,GACxC,OAAO,CAAC,MAAM,CAAC,CAejB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard-html.d.ts","sourceRoot":"","sources":["../../src/broker/dashboard-html.ts"],"names":[],"mappings":"AAEA,wBAAgB,mBAAmB,IAAI,MAAM,CAy5B5C"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { type BrokerConnectionData, type RegisteredRoute, RouteRegistrationError, RouteRegistry, serializeRouteKey, } from "./registry";
|
|
2
|
+
export { BrokerPortConflictError, BrokerServer, probeBroker, type StartBrokerOptions, type StartOrReuseBrokerResult, startBroker, startOrReuseBroker, } from "./server";
|
|
3
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/broker/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,sBAAsB,EACtB,aAAa,EACb,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,uBAAuB,EACvB,YAAY,EACZ,WAAW,EACX,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC7B,WAAW,EACX,kBAAkB,GACnB,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/broker/main.ts"],"names":[],"mappings":";AAKA,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAa/C"}
|