|
| 1 | +# Implementation Plan |
| 2 | + |
| 3 | +## Architecture |
| 4 | + |
| 5 | +- Add `src/main/presenter/remoteControlPresenter/` as a main-process presenter that exposes a small shared contract to the renderer through the existing `presenter:call` IPC path. |
| 6 | +- Keep Telegram transport in Electron main using native `fetch` and Bot API long polling. |
| 7 | +- Reuse `newAgentPresenter.sendMessage()` and `DeepChatAgentPresenter` for message persistence, stream state, title generation, and stop behavior. |
| 8 | +- Add detached session creation to `newAgentPresenter` so remote conversations do not require a renderer-bound window. |
| 9 | + |
| 10 | +## Main-Process Modules |
| 11 | + |
| 12 | +- `remoteBindingStore` |
| 13 | + - Stores `remoteControl.telegram` config in Electron Store. |
| 14 | + - Persists poll offset, allowlist, default agent id, pair code, internal stream mode, and endpoint bindings. |
| 15 | + - Keeps active event IDs, `/sessions` snapshots, and `/model` inline-menu state in memory. |
| 16 | +- `remoteAuthGuard` |
| 17 | + - Enforces private-chat-only usage. |
| 18 | + - Authenticates strictly by numeric `from.id`. |
| 19 | + - Supports one-time `/pair <code>` flow. |
| 20 | +- `remoteConversationRunner` |
| 21 | + - Creates detached sessions when needed. |
| 22 | + - Resolves a valid enabled DeepChat default agent before creating unbound Telegram sessions. |
| 23 | + - Lists recent sessions by the currently bound session's agent when a valid binding exists; otherwise falls back to the default DeepChat agent. |
| 24 | + - Exposes current-session lookup and bound-session model switching through `newAgentPresenter.setSessionModel()`. |
| 25 | + - Reuses `newAgentPresenter.sendMessage()` for plain-text Telegram input. |
| 26 | + - Tracks the active assistant message/event for `/stop`. |
| 27 | +- `remoteCommandRouter` |
| 28 | + - Handles `/start`, `/help`, `/pair`, `/new`, `/sessions`, `/use`, `/stop`, `/status`, `/model`, plain text, and `/model` callback actions. |
| 29 | +- `telegramClient` |
| 30 | + - Calls `getMe`, `getUpdates`, `sendMessageDraft`, `sendMessage`, `sendChatAction`, `setMyCommands`, `setMessageReaction`, `editMessageText`, `editMessageReplyMarkup`, and `answerCallbackQuery`. |
| 31 | +- `telegramParser` |
| 32 | + - Parses private text updates, bot commands, and callback queries into one internal event shape. |
| 33 | +- `telegramOutbound` |
| 34 | + - Builds plain-text assistant output, detects “desktop confirmation required” states, and chunks output to 4096 characters. |
| 35 | +- `telegramPoller` |
| 36 | + - Runs a single sequential long-poll loop. |
| 37 | + - Advances the stored offset only after a specific update is handled successfully. |
| 38 | + - Uses exponential backoff on failures. |
| 39 | + - Only adds reactions for plain-text conversation messages and clears them after the conversation completes or fails. |
| 40 | + |
| 41 | +## Shared / IPC Contract |
| 42 | + |
| 43 | +- Add `src/shared/types/presenters/remote-control.presenter.d.ts`. |
| 44 | +- Expose methods for reading/saving Telegram settings, reading runtime status, listing/removing bindings, reading pairing snapshot, generating/clearing pair codes, clearing bindings, and testing Telegram hooks. |
| 45 | + |
| 46 | +## Renderer Plan |
| 47 | + |
| 48 | +- Add a new `Remote` settings route and `RemoteSettings.vue`. |
| 49 | +- Move Telegram configuration out of `NotificationsHooksSettings.vue`. |
| 50 | +- Keep `Hooks` for Discord, Confirmo, and command hooks only. |
| 51 | +- Simplify the first-layer Telegram remote UI to allowed user IDs, default agent selection, pairing, and binding management. |
| 52 | +- Show pairing and binding management inside dialogs; hide remote/hook detail forms when their toggle is off. |
| 53 | +- Reuse existing i18n flow for all renderer-visible strings. |
| 54 | + |
| 55 | +## Data Model |
| 56 | + |
| 57 | +- SQLite |
| 58 | + - No schema change. |
| 59 | + - Sessions/messages continue to use existing new-agent tables. |
| 60 | +- Electron Store |
| 61 | + - `hooksNotifications.telegram` |
| 62 | + - Shared Telegram bot token and hook notification target settings. |
| 63 | + - `remoteControl.telegram` |
| 64 | + - `enabled` |
| 65 | + - `allowlist` |
| 66 | + - `defaultAgentId` |
| 67 | + - `streamMode` |
| 68 | + - `pairing` |
| 69 | + - `pollOffset` |
| 70 | + - `bindings` |
| 71 | + |
| 72 | +## Event / Request Flow |
| 73 | + |
| 74 | +1. Renderer saves Remote settings through `remoteControlPresenter`. |
| 75 | +2. Main presenter updates `hooksNotifications.telegram` and `remoteControl.telegram`, then rebuilds the Telegram runtime if required. |
| 76 | +3. Telegram poller receives private updates through `getUpdates`. |
| 77 | +4. Parser normalizes message and callback payloads. |
| 78 | +5. Router applies auth, command handling, and `/model` inline-menu transitions. |
| 79 | +6. Plain text enters `newAgentPresenter.sendMessage()` using the bound or newly created detached session. |
| 80 | +7. `/model` callback actions edit a single bot menu message in place and answer the callback query. |
| 81 | +8. Poller watches assistant message state and sends draft/final Telegram output. |
| 82 | +9. If the assistant pauses on a permission/question action, Telegram returns a desktop-confirmation notice instead of bypassing approval. |
| 83 | + |
| 84 | +## Testing Strategy |
| 85 | + |
| 86 | +- Unit tests for `remoteAuthGuard`. |
| 87 | +- Unit tests for `remoteBindingStore`. |
| 88 | +- Unit tests for `remoteCommandRouter`. |
| 89 | +- Unit tests for `remoteConversationRunner`. |
| 90 | +- Unit tests for `telegramParser`. |
| 91 | +- Unit tests for `telegramClient` request payloads. |
| 92 | +- Unit tests for `telegramOutbound` chunking/final-text behavior. |
| 93 | +- Unit tests for Telegram command registration, callback handling, and message reaction lifecycle behavior. |
| 94 | +- Presenter-level tests for detached session creation. |
| 95 | +- Presenter-level tests for stop-by-event behavior. |
| 96 | + |
| 97 | +## Migration Note |
| 98 | + |
| 99 | +- No SQLite migration is required. |
| 100 | +- Existing Telegram hook settings remain compatible. |
| 101 | +- New remote state is additive and can be removed cleanly by disabling remote control or clearing the config blob. |
0 commit comments