opencode-tbot 0.1.32 → 0.1.34

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.ja.md CHANGED
@@ -1,29 +1,31 @@
1
1
  # opencode-tbot
2
2
 
3
- チャットから [OpenCode](https://opencode.ai) を操作するための Telegram プラグインです。
3
+ Telegram から [OpenCode](https://opencode.ai) を操作するためのプラグインです。
4
4
 
5
5
  [English](./README.md) | [简体中文](./README.zh-CN.md) | [日本語](./README.ja.md)
6
6
 
7
- > このプロジェクトは OpenCode チームによって開発されたものではなく、公式な関連もありません。
7
+ > このプロジェクトは OpenCode チームによって開発されたものではなく、公式プロジェクトでもありません。
8
8
 
9
9
  ## 概要
10
10
 
11
- `opencode-tbot` を使うと、Telegram から OpenCode を操作できます。
11
+ `opencode-tbot` を使うと、Telegram から OpenCode を操作でき、チャットごとに 1 つのバインド状態を維持できます。
12
12
 
13
- - テキストメッセージは現在アクティブな OpenCode セッションに転送されます。
13
+ - プレーンテキストメッセージは現在の OpenCode セッションに転送されます。
14
14
  - Telegram の写真と画像ドキュメントは OpenCode のファイルパートとしてアップロードされます。
15
- - Telegram の音声メッセージは明示的に拒否され、ローカライズされた返信を返します。
15
+ - 画像を含むターンは一時的に fork したセッションで実行されるため、後続のテキスト専用プロンプトに画像コンテキストが残りません。
16
16
  - OpenCode が発行した権限リクエストは、Telegram のインラインボタンから承認または拒否できます。
17
- - セッション完了やエラーイベントは、紐付けられた Telegram チャットへ通知できます。
18
- - チャットの紐付け状態は JSON の state ファイルに保存されます。
17
+ - セッションエラーイベントは、紐付けられた Telegram チャットへ通知できます。
18
+ - 音声メッセージは明示的に拒否され、ローカライズされた案内を返します。
19
+ - チャットのバインドとセッション選択状態は JSON の state ファイルに保存されます。
19
20
 
20
21
  ## 前提条件
21
22
 
22
- - このプラグインを読み込む OpenCode ホストプロセスが動作していること。
23
+ - このプラグインを読み込む OpenCode Host プロセスが動作していること。
23
24
  - Telegram bot token を用意していること。
24
- - CLI とローカル開発には Node.js `>=22.12.0` が必要です。
25
+ - CLI とローカル開発のために Node.js `>=22.12.0` が必要です。
26
+ - リポジトリ開発には `pnpm` が必要です。
25
27
 
26
- ## インストール
28
+ ## インストールと更新
27
29
 
28
30
  推奨インストール方法:
29
31
 
@@ -31,7 +33,14 @@
31
33
  npm exec --package opencode-tbot@latest opencode-tbot -- install
32
34
  ```
33
35
 
34
- インストーラーはプラグインをグローバルに登録し、デフォルトのランタイム設定を書き込みます。
36
+ インストーラーは次を行います。
37
+
38
+ - グローバル OpenCode プラグイン一覧に `opencode-tbot@latest` を登録
39
+ - 実際に使われる OpenCode グローバル設定ファイルを更新
40
+ - グローバルのプラグイン実行設定を作成またはマージ
41
+ - OpenCode 設定パス、プラグイン設定パス、既定のプラグインログディレクトリを表示
42
+
43
+ `~/.config/opencode/opencode.jsonc` がすでに存在する場合はそのファイルを優先して更新し、存在しない場合は `~/.config/opencode/opencode.json` を使います。
35
44
 
36
45
  インストール済み CLI のバージョン確認:
37
46
 
@@ -39,12 +48,18 @@ npm exec --package opencode-tbot@latest opencode-tbot -- install
39
48
  npm exec --package opencode-tbot@latest opencode-tbot -- --version
40
49
  ```
41
50
 
42
- OpenCode に登録済みの npm プラグイン spec を更新:
51
+ bot token を変更せず、OpenCode に登録された npm プラグイン spec だけを更新:
43
52
 
44
53
  ```bash
45
54
  npm exec --package opencode-tbot@latest opencode-tbot -- update
46
55
  ```
47
56
 
57
+ `install` は既定コマンドです。たとえば、非対話インストールでは次の形でも実行できます。
58
+
59
+ ```bash
60
+ npm exec --package opencode-tbot@latest opencode-tbot -- --bot-token <token>
61
+ ```
62
+
48
63
  ### CLI オプション
49
64
 
50
65
  `install` で利用可能:
@@ -62,13 +77,23 @@ npm exec --package opencode-tbot@latest opencode-tbot -- update
62
77
 
63
78
  ## 設定
64
79
 
65
- ランタイム設定は `~/.config/opencode/opencode-tbot/config.json` からのみ読み込まれます。
80
+ ランタイム設定は次のパスからのみ読み込まれます。
81
+
82
+ - `~/.config/opencode/opencode-tbot/config.json`
83
+
84
+ OpenCode のプラグイン登録情報はグローバル OpenCode 設定に保存されます。
66
85
 
67
- 古い `<worktree>/tbot.config.json` はランタイムでは無視されます。検出された場合は、値をグローバル設定へ移行できるように警告ログを出します。
86
+ - 存在する場合は `~/.config/opencode/opencode.jsonc`
87
+ - なければ `~/.config/opencode/opencode.json`
68
88
 
69
- 古い `openrouter` 音声転写設定はランタイムでは無視され、インストーラーが設定を書き直す際にも削除されます。
89
+ このプラグインは `.env` からランタイム設定を読み込みません。グローバル JSON 設定を使ってください。
70
90
 
71
- ### グローバル `config.json` の例
91
+ レガシー挙動:
92
+
93
+ - `<worktree>/tbot.config.json` はランタイムで無視されます。見つかった場合は移行用の警告ログが出ます
94
+ - 古い `openrouter` 音声文字起こし設定はランタイムで無視され、インストーラーが設定を書き直す際にも削除されます
95
+
96
+ ### `config.json` の例
72
97
 
73
98
  ```json
74
99
  {
@@ -85,55 +110,100 @@ npm exec --package opencode-tbot@latest opencode-tbot -- update
85
110
  "pollRequestTimeoutMs": 15000,
86
111
  "recoveryInactivityTimeoutMs": 120000
87
112
  },
113
+ "logging": {
114
+ "level": "info",
115
+ "sinks": {
116
+ "host": true,
117
+ "file": true
118
+ },
119
+ "file": {
120
+ "dir": "C:/Users/your-user/.local/share/opencode/log/plugins/opencode-tbot",
121
+ "retention": {
122
+ "maxFiles": 30,
123
+ "maxTotalBytes": 314572800
124
+ }
125
+ }
126
+ },
88
127
  "logLevel": "info"
89
128
  }
90
129
  ```
91
130
 
92
- ### フィールド
131
+ ### 設定項目
93
132
 
94
- | フィールド | 必須 | デフォルト | 説明 |
133
+ | 項目 | 必須 | 既定値 | 説明 |
95
134
  | --- | --- | --- | --- |
96
- | `telegram.botToken` | はい | - | Telegram bot token。通常はインストーラーがグローバルプラグイン設定へ書き込みます。 |
97
- | `telegram.allowedChatIds` | いいえ | `[]` | 許可する Telegram chat ID の配列。空の場合はすべての chat を受け付けます。 |
98
- | `telegram.apiRoot` | いいえ | `https://api.telegram.org` | Telegram Bot API のベース URL。テストやセルフホストのゲートウェイ向けです。 |
135
+ | `telegram.botToken` | はい | - | Telegram bot token。通常はインストーラーがグローバル設定に書き込みます。 |
136
+ | `telegram.allowedChatIds` | いいえ | `[]` | 許可する Telegram chat ID。一覧が空なら任意の chat を受け付けます。 |
137
+ | `telegram.apiRoot` | いいえ | `https://api.telegram.org` | Telegram Bot API のベース URL。テストやセルフホスト環境向けです。 |
99
138
  | `state.path` | いいえ | `./data/opencode-tbot.state.json` | JSON state ファイルのパス。現在の OpenCode worktree からの相対パスとして解決されます。 |
100
- | `logLevel` | いいえ | `info` | プラグインのログレベル。ログは `client.app.log()` 経由で出力されます。 |
139
+ | `prompt.waitTimeoutMs` | いいえ | `1800000` | 1 回の非同期 prompt ライフサイクル全体に対する待機上限。 |
140
+ | `prompt.pollRequestTimeoutMs` | いいえ | `15000` | OpenCode への各 recovery poll リクエストのタイムアウト。 |
141
+ | `prompt.recoveryInactivityTimeoutMs` | いいえ | `120000` | 進捗が止まった場合にのみ適用される recovery タイムアウト。 |
142
+ | `logging.level` | いいえ | `info` | host/file 両方に使う構造化ログレベル。`debug`、`info`、`warn`、`error` に正規化されます。 |
143
+ | `logging.sinks.host` | いいえ | `true` | `client.app.log({ body: ... })` 経由で OpenCode Host ログへ書き込むかどうか。 |
144
+ | `logging.sinks.file` | いいえ | `true` | プラグイン独自の JSONL ファイルログを有効にするかどうか。 |
145
+ | `logging.file.dir` | いいえ | `%USERPROFILE%/.local/share/opencode/log/plugins/opencode-tbot` | プラグイン JSONL ログのディレクトリ。相対パスは現在の OpenCode worktree 基準で解決されます。 |
146
+ | `logging.file.retention.maxFiles` | いいえ | `30` | 保持するプラグインログファイル数の上限。 |
147
+ | `logging.file.retention.maxTotalBytes` | いいえ | `314572800` | 保持するプラグインログ合計サイズの上限。 |
148
+ | `logLevel` | いいえ | `info` | `logging.level` の互換エイリアス。後方互換のため引き続き利用できます。 |
101
149
 
102
150
  ### 補足
103
151
 
104
152
  - `state.path` は現在の OpenCode worktree からの相対パスとして解決されます。
153
+ - `logging.file.dir` が相対パスの場合も現在の worktree から解決されます。
154
+ - Telegram の prompt 処理は async-first です。プラグインは `session.promptAsync()` を送信し、その後メッセージとセッション状態から最終応答を回収します。
105
155
  - `telegram.allowedChatIds` を空のままにすると、bot は任意の chat からのメッセージを受け付けます。本番では制限を設定してください。
106
- - 権限承認とセッション通知はプラグインの hook で処理されます。
107
- - `/language` は現在 English、简体中文、日本語 をサポートしています。
156
+ - 権限承認とセッションエラー通知はプラグイン hook で処理されます。
157
+ - `/language` は現在 English、简体中文、日本語 をサポートし、その chat 用の Telegram コマンド説明も同期します。
158
+ - ファイルログは既定でメタデータのみを記録し、prompt 本文、添付内容、生の URL、secret は書き込みません。
108
159
 
109
160
  ## クイックスタート
110
161
 
111
- 1. `npm exec --package opencode-tbot@latest opencode-tbot -- install` でプラグインをインストールします。
112
- 2. 特定の chat のみ許可したい場合は、`~/.config/opencode/opencode-tbot/config.json` `telegram.allowedChatIds` を設定します。
113
- 3. 対象の worktree で OpenCode を起動し、プラグインランタイムを読み込ませます。
114
- 4. Telegram で `/status` を実行し、接続を確認します。
115
- 5. `/new [title]` を実行するか、テキストメッセージを直接送信して使い始めます。
162
+ 1. `npm exec --package opencode-tbot@latest opencode-tbot -- install` を実行します。
163
+ 2. 特定の chat だけに制限したい場合は `~/.config/opencode/opencode-tbot/config.json` `telegram.allowedChatIds` を設定します。
164
+ 3. 対象 worktree で OpenCode を起動し、プラグインランタイムを読み込ませます。
165
+ 4. Telegram で `/status` を実行して接続を確認します。
166
+ 5. `/new [title]` を実行するか、直接テキストメッセージを送信して使い始めます。
116
167
 
117
168
  ## コマンド
118
169
 
119
- - `/start` 短いウェルカムメッセージとクイックスタート手順を表示
120
- - `/status` OpenCode のヘルス、パス、プラグイン、LSP、MCP の状態をまとめて表示
121
- - `/new [title]` 新しい OpenCode セッションを作成
122
- - `/agents` または `/agent` 利用可能な agent を一覧表示し、アクティブな agent を切り替え
123
- - `/sessions` 利用可能なセッションを一覧表示し、アクティブなセッションを切り替え
124
- - `/cancel` セッション名の変更をキャンセルするか、現在のセッションで実行中のリクエストを中止
125
- - `/model` または `/models` 利用可能なモデルを一覧表示し、アクティブなモデルを切り替え
126
- - `/language` bot の表示言語を切り替え
170
+ | コマンド | 内容 |
171
+ | --- | --- |
172
+ | `/start` | ウェルカムメッセージとクイックスタートを表示します。 |
173
+ | `/status` | OpenCode のヘルス、バージョン、ワークスペースパス、プラグイン一覧、LSP、MCP の状態をまとめて表示します。 |
174
+ | `/new [title]` | 現在のプロジェクトで新しい OpenCode セッションを作成します。 |
175
+ | `/agents` または `/agent` | 利用可能なエージェントを表示し、現在のエージェントを切り替えます。 |
176
+ | `/sessions` | 利用可能なセッションを表示し、切り替えやリネーム操作を提供します。 |
177
+ | `/cancel` | 保留中のセッション名変更入力をキャンセルするか、現在のセッションで動作中のリクエストを中止します。 |
178
+ | `/model` または `/models` | 利用可能なモデルを表示し、切り替えや推論レベル選択を行います。 |
179
+ | `/language` | 現在の chat に対する bot 表示言語を切り替えます。 |
127
180
 
128
- メッセージ処理:
181
+ ### メッセージ動作
129
182
 
130
- - コマンド以外のテキストは prompt として扱われ、OpenCode に送信されます。
183
+ - コマンド以外のテキストは prompt として OpenCode に送信されます。
131
184
  - Telegram の写真と画像ドキュメントは OpenCode のファイルパートとして転送されます。
185
+ - 画像添付は現在のセッションの一時 fork 内で処理されるため、後続のテキスト専用コンテキストを汚しません。
186
+ - `/cancel` は OpenCode セッション側の処理と Telegram 側の待機状態を同時に中止し、次の prompt をすぐ開始できるようにします。
132
187
  - Telegram の音声メッセージは未対応で、ローカライズされた拒否メッセージを返します。
133
188
 
189
+ ## ロギング
190
+
191
+ - OpenCode Host ログディレクトリ: `%USERPROFILE%/.local/share/opencode/log`
192
+ - プラグインログディレクトリ: `%USERPROFILE%/.local/share/opencode/log/plugins/opencode-tbot`
193
+ - ファイル形式: 追記型 JSONL、1 行 1 イベント
194
+ - 代表的な相関フィールド: `runtimeId`, `operationId`, `correlationId`, `updateId`, `chatId`, `sessionId`, `projectId`
195
+ - よく出るコンポーネント: `runtime`, `telegram`, `opencode`, `prompt`, `plugin-event`, `storage`
196
+ - 既定の保持ポリシー: 新しい 30 ファイルまで、合計 300 MB まで
197
+
134
198
  ## 開発
135
199
 
136
- プラグインバンドルをビルド:
200
+ 依存関係のインストール:
201
+
202
+ ```bash
203
+ pnpm install
204
+ ```
205
+
206
+ ビルド:
137
207
 
138
208
  ```bash
139
209
  pnpm build
@@ -145,19 +215,45 @@ pnpm build
145
215
  pnpm typecheck
146
216
  ```
147
217
 
148
- テスト実行:
218
+ 通常テストの実行:
149
219
 
150
220
  ```bash
151
221
  pnpm test
152
222
  ```
153
223
 
154
- このリポジトリでソースベースのローカル読み込みを行う場合、OpenCode は [.opencode/plugins/opencode-tbot.ts](./.opencode/plugins/opencode-tbot.ts) を使って `src/plugin.ts` を再エクスポートできます。
224
+ CI に最も近い統合経路の実行:
225
+
226
+ ```bash
227
+ npm install -g opencode-ai
228
+ OPENCODE_HOST_E2E=1 pnpm test
229
+ ```
230
+
231
+ PowerShell の場合:
232
+
233
+ ```powershell
234
+ npm install -g opencode-ai
235
+ $env:OPENCODE_HOST_E2E="1"; pnpm test
236
+ ```
237
+
238
+ 通常利用では、グローバルにインストールした npm プラグインとグローバル OpenCode 設定を使ってください。このリポジトリは既定の `.opencode/plugins` bridge を含みません。
239
+
240
+ このリポジトリでソースベースのローカル読み込みを行いたい場合は、`.opencode/plugins/opencode-tbot.ts` を手動で作成してください。
241
+
242
+ ```ts
243
+ export { default } from "../../src/plugin.ts";
244
+ ```
245
+
246
+ 有効にする読み込み経路は常に 1 つだけにしてください。手動で作成したローカル bridge か、グローバルにインストールした `opencode-tbot@latest` のどちらかを使います。
155
247
 
156
248
  ## FAQ
157
249
 
158
250
  ### 実行中の OpenCode インスタンスは必要ですか?
159
251
 
160
- はい。このリポジトリが提供するのは Telegram 連携レイヤーであり、プラグインを読み込む OpenCode ホストプロセスに依存します。
252
+ はい。このリポジトリは Telegram 連携レイヤーのみを提供しており、プラグインを読み込む OpenCode Host プロセスに依存します。
253
+
254
+ ### なぜ OpenCode に `file:///.../node_modules/...` 形式のプラグインパスが表示されるのですか?
255
+
256
+ 通常は、どこかのローカルプロジェクトに `opencode-tbot` が `node_modules` として入っていることを意味します。CLI はその状態を検出すると警告します。そのプロジェクトで `npm uninstall opencode-tbot` を実行してローカル依存を外し、推奨の `npm exec --package ...` インストールフローを使ってください。
161
257
 
162
258
  ### これは OpenCode の公式プロジェクトですか?
163
259
 
package/README.md CHANGED
@@ -8,23 +8,24 @@ A Telegram plugin for driving [OpenCode](https://opencode.ai) from chat.
8
8
 
9
9
  ## Overview
10
10
 
11
- `opencode-tbot` lets you operate OpenCode from Telegram.
11
+ `opencode-tbot` lets you operate OpenCode from Telegram with a single bot binding per chat.
12
12
 
13
- - Text messages are forwarded to the active OpenCode session.
13
+ - Plain text messages are forwarded to the current OpenCode session.
14
14
  - Telegram photos and image documents are uploaded as OpenCode file parts.
15
15
  - Image turns run in a temporary forked session, so later text-only prompts do not inherit image context.
16
- - Telegram voice messages are explicitly rejected with a localized reply.
17
16
  - Permission requests raised by OpenCode can be approved or rejected from Telegram inline buttons.
18
- - Session completion and error events can be reported back to the bound Telegram chat.
19
- - Chat bindings are stored in a JSON state file.
17
+ - Session error events can be reported back to the bound Telegram chat.
18
+ - Voice messages are explicitly rejected with a localized reply.
19
+ - Chat bindings and session selections are stored in a JSON state file.
20
20
 
21
21
  ## Requirements
22
22
 
23
23
  - A running OpenCode host process that loads the plugin.
24
24
  - A Telegram bot token.
25
25
  - Node.js `>=22.12.0` for the CLI and local development workflow.
26
+ - `pnpm` for repository development.
26
27
 
27
- ## Install
28
+ ## Install And Update
28
29
 
29
30
  Recommended install:
30
31
 
@@ -32,7 +33,14 @@ Recommended install:
32
33
  npm exec --package opencode-tbot@latest opencode-tbot -- install
33
34
  ```
34
35
 
35
- The installer registers the plugin globally, writes the default runtime config, and prints both the config path and the default plugin log directory.
36
+ The installer:
37
+
38
+ - registers `opencode-tbot@latest` in the global OpenCode plugin list
39
+ - updates the resolved OpenCode config file
40
+ - writes or merges the global plugin runtime config
41
+ - prints the OpenCode config path, plugin config path, and default plugin log directory
42
+
43
+ If `~/.config/opencode/opencode.jsonc` already exists, the installer updates that file. Otherwise it uses `~/.config/opencode/opencode.json`.
36
44
 
37
45
  Check the installed CLI version:
38
46
 
@@ -40,12 +48,18 @@ Check the installed CLI version:
40
48
  npm exec --package opencode-tbot@latest opencode-tbot -- --version
41
49
  ```
42
50
 
43
- Update the registered npm plugin spec in OpenCode:
51
+ Update the registered npm plugin spec in OpenCode without touching your bot token:
44
52
 
45
53
  ```bash
46
54
  npm exec --package opencode-tbot@latest opencode-tbot -- update
47
55
  ```
48
56
 
57
+ `install` is the default command. For example, this also works for a non-interactive install:
58
+
59
+ ```bash
60
+ npm exec --package opencode-tbot@latest opencode-tbot -- --bot-token <token>
61
+ ```
62
+
49
63
  ### CLI Options
50
64
 
51
65
  `install` supports:
@@ -63,13 +77,23 @@ npm exec --package opencode-tbot@latest opencode-tbot -- update
63
77
 
64
78
  ## Configuration
65
79
 
66
- Runtime config is loaded from `~/.config/opencode/opencode-tbot/config.json`.
80
+ Runtime config is loaded only from:
67
81
 
68
- Legacy `<worktree>/tbot.config.json` files are ignored at runtime. If one is present, the plugin logs a warning so you can migrate its values into the global config.
82
+ - `~/.config/opencode/opencode-tbot/config.json`
69
83
 
70
- Legacy `openrouter` voice-transcription settings are ignored at runtime. When the installer rewrites the config, it removes them.
84
+ OpenCode plugin registration is stored in the global OpenCode config:
71
85
 
72
- ### Example Global `config.json`
86
+ - `~/.config/opencode/opencode.jsonc` when present
87
+ - otherwise `~/.config/opencode/opencode.json`
88
+
89
+ This plugin does not read runtime settings from `.env`. Use the global JSON config instead.
90
+
91
+ Legacy behavior:
92
+
93
+ - `<worktree>/tbot.config.json` is ignored at runtime. If one is present, the plugin logs a warning so you can migrate it.
94
+ - legacy `openrouter` voice-transcription settings are ignored at runtime and removed when the installer rewrites the config
95
+
96
+ ### Example `config.json`
73
97
 
74
98
  ```json
75
99
  {
@@ -115,10 +139,10 @@ Legacy `openrouter` voice-transcription settings are ignored at runtime. When th
115
139
  | `prompt.waitTimeoutMs` | No | `1800000` | Maximum total wait for one async prompt lifecycle before the plugin stops waiting for OpenCode recovery. |
116
140
  | `prompt.pollRequestTimeoutMs` | No | `15000` | Timeout for each individual recovery poll request to OpenCode. |
117
141
  | `prompt.recoveryInactivityTimeoutMs` | No | `120000` | Recovery timeout that only applies when prompt progress stops advancing. |
118
- | `logging.level` | No | `info` | Structured log level for both host and file sinks. |
142
+ | `logging.level` | No | `info` | Structured log level for host and file sinks. Accepted values normalize to `debug`, `info`, `warn`, or `error`. |
119
143
  | `logging.sinks.host` | No | `true` | Enable OpenCode host logging through `client.app.log({ body: ... })`. |
120
144
  | `logging.sinks.file` | No | `true` | Enable plugin-owned JSONL file logs. |
121
- | `logging.file.dir` | No | `%USERPROFILE%/.local/share/opencode/log/plugins/opencode-tbot` | Plugin JSONL log directory. |
145
+ | `logging.file.dir` | No | `%USERPROFILE%/.local/share/opencode/log/plugins/opencode-tbot` | Plugin JSONL log directory. Relative paths are resolved from the current OpenCode worktree. |
122
146
  | `logging.file.retention.maxFiles` | No | `30` | Maximum number of retained plugin log files. |
123
147
  | `logging.file.retention.maxTotalBytes` | No | `314572800` | Maximum total size of retained plugin log files. |
124
148
  | `logLevel` | No | `info` | Legacy alias for `logging.level`. Still accepted for compatibility. |
@@ -126,25 +150,13 @@ Legacy `openrouter` voice-transcription settings are ignored at runtime. When th
126
150
  ### Notes
127
151
 
128
152
  - `state.path` is resolved relative to the current OpenCode worktree.
153
+ - Relative `logging.file.dir` values are also resolved from the current worktree.
129
154
  - Telegram prompt handling is async-first: the plugin submits `session.promptAsync()` and then recovers the reply from session messages and session status.
130
- - `prompt.waitTimeoutMs` is the total safety cap; `prompt.recoveryInactivityTimeoutMs` only applies when OpenCode stops making progress.
131
155
  - If `telegram.allowedChatIds` is left empty, the bot accepts messages from any chat. Restrict it in production.
132
- - Permission approvals and session notifications are handled through plugin hooks.
133
- - `/language` currently supports English, Simplified Chinese, and Japanese.
134
- - Plugin logs are dual-written by default: OpenCode host logs through `client.app.log({ body: ... })`, plus plugin JSONL files.
135
- - OpenCode host logs live under `%USERPROFILE%/.local/share/opencode/log`.
136
- - The default plugin JSONL log directory is `%USERPROFILE%/.local/share/opencode/log/plugins/opencode-tbot`.
156
+ - Permission approvals and session error notifications are handled through plugin hooks.
157
+ - `/language` currently supports English, Simplified Chinese, and Japanese, and syncs localized Telegram command descriptions for that chat.
137
158
  - File logs are metadata-only by default. Prompt bodies, attachment contents, raw URLs, and secrets are not written.
138
159
 
139
- ## Logging
140
-
141
- - Host log directory: `%USERPROFILE%/.local/share/opencode/log`
142
- - Plugin log directory: `%USERPROFILE%/.local/share/opencode/log/plugins/opencode-tbot`
143
- - File format: append-only JSONL, one structured event per line
144
- - Correlation fields: `runtimeId`, `operationId`, `correlationId`, `updateId`, `chatId`, `sessionId`, `projectId`
145
- - Common components: `runtime`, `telegram`, `opencode`, `prompt`, `plugin-event`, `storage`
146
- - Retention: keep the newest 30 files and at most 300 MB by default
147
-
148
160
  ## Quick Start
149
161
 
150
162
  1. Install the plugin with `npm exec --package opencode-tbot@latest opencode-tbot -- install`.
@@ -155,26 +167,43 @@ Legacy `openrouter` voice-transcription settings are ignored at runtime. When th
155
167
 
156
168
  ## Commands
157
169
 
158
- - `/start` show a short welcome message and quick-start steps
159
- - `/status` show aggregated OpenCode health, path, plugin, LSP, and MCP status
160
- - `/new [title]` create a new OpenCode session
161
- - `/agents` or `/agent` list available agents and switch the active one
162
- - `/sessions` list available sessions and switch the active one
163
- - `/cancel` cancel session rename or abort the running request for the current session, including the local Telegram wait state
164
- - `/model` or `/models` list available models and switch the active one
165
- - `/language` switch the bot display language
170
+ | Command | What it does |
171
+ | --- | --- |
172
+ | `/start` | Show a short welcome message and quick-start steps. |
173
+ | `/status` | Show aggregated OpenCode health, version, workspace paths, plugin list, LSP status, and MCP status. |
174
+ | `/new [title]` | Create a new OpenCode session in the current project. |
175
+ | `/agents` or `/agent` | List available agents and switch the active one. |
176
+ | `/sessions` | List available sessions, switch the active one, and offer rename actions. |
177
+ | `/cancel` | Cancel pending session rename input or abort the running request for the current session. |
178
+ | `/model` or `/models` | List available models, switch the active one, and choose a reasoning level when available. |
179
+ | `/language` | Switch the bot display language for the current chat. |
166
180
 
167
- Message handling:
181
+ ### Message Behavior
168
182
 
169
183
  - Non-command text is treated as a prompt and sent to OpenCode.
170
184
  - Telegram photos and image documents are forwarded as OpenCode file parts.
171
185
  - Image attachments are processed in a temporary fork of the active session so later text-only prompts stay clean.
172
- - `/cancel` aborts both the OpenCode session and the local Telegram wait, so the next prompt can start immediately.
186
+ - `/cancel` aborts both the OpenCode session and the local Telegram wait state, so the next prompt can start immediately.
173
187
  - Telegram voice messages are not supported and receive a localized rejection reply.
174
188
 
189
+ ## Logging
190
+
191
+ - Host log directory: `%USERPROFILE%/.local/share/opencode/log`
192
+ - Plugin log directory: `%USERPROFILE%/.local/share/opencode/log/plugins/opencode-tbot`
193
+ - File format: append-only JSONL, one structured event per line
194
+ - Correlation fields: `runtimeId`, `operationId`, `correlationId`, `updateId`, `chatId`, `sessionId`, `projectId`
195
+ - Common components: `runtime`, `telegram`, `opencode`, `prompt`, `plugin-event`, `storage`
196
+ - Default retention: newest 30 files and at most 300 MB total
197
+
175
198
  ## Development
176
199
 
177
- Build the plugin bundle:
200
+ Install dependencies:
201
+
202
+ ```bash
203
+ pnpm install
204
+ ```
205
+
206
+ Build the bundle:
178
207
 
179
208
  ```bash
180
209
  pnpm build
@@ -186,15 +215,35 @@ Type-check:
186
215
  pnpm typecheck
187
216
  ```
188
217
 
189
- Run tests:
218
+ Run the normal test suite:
190
219
 
191
220
  ```bash
192
221
  pnpm test
193
222
  ```
194
223
 
195
- For local source-based loading in this repository, OpenCode can use [.opencode/plugins/opencode-tbot.ts](./.opencode/plugins/opencode-tbot.ts), which re-exports `src/plugin.ts`.
224
+ Run the integration path closest to CI:
196
225
 
197
- OpenCode may load both the local `.opencode/plugins/` bridge and an installed npm plugin such as `opencode-tbot@latest` in the same process. This repository now guards against duplicate Telegram runners, but local development is still clearer if you keep only one loading path enabled at a time.
226
+ ```bash
227
+ npm install -g opencode-ai
228
+ OPENCODE_HOST_E2E=1 pnpm test
229
+ ```
230
+
231
+ PowerShell:
232
+
233
+ ```powershell
234
+ npm install -g opencode-ai
235
+ $env:OPENCODE_HOST_E2E="1"; pnpm test
236
+ ```
237
+
238
+ Normal usage should rely on the globally installed npm plugin plus the global OpenCode config. This repository does not ship a default `.opencode/plugins` bridge.
239
+
240
+ If you need source-based local loading while developing in this repository, create `.opencode/plugins/opencode-tbot.ts` manually:
241
+
242
+ ```ts
243
+ export { default } from "../../src/plugin.ts";
244
+ ```
245
+
246
+ Keep only one loading path enabled at a time: either the manual local bridge or the globally installed `opencode-tbot@latest` plugin.
198
247
 
199
248
  ## FAQ
200
249
 
@@ -202,6 +251,10 @@ OpenCode may load both the local `.opencode/plugins/` bridge and an installed np
202
251
 
203
252
  Yes. This repository provides a Telegram integration layer and depends on the OpenCode host process that loads the plugin.
204
253
 
254
+ ### Why does OpenCode show the plugin as `file:///.../node_modules/...`?
255
+
256
+ That usually means a local project has `opencode-tbot` installed in its own `node_modules`. The CLI warns when it detects that layout. Remove the local package with `npm uninstall opencode-tbot` in that project and use the recommended `npm exec --package ...` install flow instead.
257
+
205
258
  ### Is this an official OpenCode project?
206
259
 
207
260
  No. It integrates with OpenCode, but it is not built by the OpenCode team.