opencode-tbot 0.1.33 → 0.1.35

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