Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions AGENTS.md

Large diffs are not rendered by default.

28 changes: 17 additions & 11 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,31 @@
# Changelog

## 0.18.0: Thread Mode
## 0.18.1: Windows setup transport hotfix

- `[Thread Mode]` Added BotFather private-chat Thread Mode while keeping classic private DM as the base mode. BotFather Thread Mode is now the bus switch: in ordinary private-DM mode, one Pi session owns the bot; when Telegram exposes Threads, one live leader owns polling/Bot API transport and visible follower Pi processes join explicitly with `/telegram-connect`. Impact: operators can choose either a simple single-instance bot or a multi-thread development workspace without competing pollers or hidden process spawning.
- `[Capability Switching]` Reworked Thread Mode availability around private-bot evidence: `getMe.has_topics_enabled`, incoming `message_thread_id`, and private-thread operation success/failure. A 5-second monitor can hot-upgrade classic mode to Thread Mode and hot-downgrade back to classic without `/reload`. Impact: BotFather Thread Mode behaves as a progressive enhancement instead of a startup-only assumption.
- `[Setup]` `/telegram-setup` token validation now uses the same fallback-aware Telegram transport as normal API calls. Impact: Windows/QEMU hosts that fail native `fetch` during bot-token validation can retry through IPv4 fallback instead of failing before config is saved.
- `[Setup]` Token validation transport failures now report a setup error notification instead of escaping as a command failure. Impact: operators get a clear retryable setup failure when Telegram is unreachable.
- `[Docs]` Normalized Threaded Mode language across README, architecture docs, prompt guidance, and changelog: `Threaded Mode` is the mode name, `thread` is the user-visible Telegram surface, and BotFather is only the bot configuration tool. Impact: release docs no longer imply BotFather owns runtime Threaded Mode behavior.

## 0.18.0: Threaded Mode

- `[Threaded Mode]` Added Telegram private-chat Threaded Mode while keeping classic private DM as the base mode. Threaded Mode is now the bus switch: in ordinary private-DM mode, one Pi session owns the bot; when Telegram exposes threads for the bot, one live leader owns polling/Bot API transport and visible follower Pi processes join explicitly with `/telegram-connect`. Impact: operators can choose either a simple single-instance bot or a multi-thread development workspace without competing pollers or hidden process spawning.
- `[Capability Switching]` Reworked Threaded Mode availability around private-bot evidence: `getMe.has_topics_enabled`, incoming `message_thread_id`, and private-thread operation success/failure. A 5-second monitor can hot-upgrade classic mode to Threaded Mode and hot-downgrade back to classic without `/reload`. Impact: Threaded Mode behaves as a progressive enhancement instead of a startup-only assumption.
- `[Thread Routing]` Preserved per-instance ownership for queues, active turns, model/tool state, previews, menus, lifecycle hooks, replies, files, voice, buttons, reactions, and command/control replies. Impact: leader and follower threads behave like scoped Telegram workspaces rather than views over one shared queue.
- `[Thread Lifecycle]` Added durable current-state thread bindings with explicit owners, stable slots, compact baked thread names, reservations, and proof-before-delete cleanup through `thread-reconciler`. Impact: reloads, reconnects, stale tabs, restores, and cleanup avoid duplicate live threads and avoid deleting uncertain targets.
- `[Leader/Follower Recovery]` Added recovery for reloads, reconnects, follower heartbeat loss, promotion, explicit disconnect, stale thread cleanup, and same-profile follower resume. Impact: Thread Mode degrades forward across local process churn while preserving the intended thread binding where possible.
- `[Leader/Follower Recovery]` Added recovery for reloads, reconnects, follower heartbeat loss, promotion, explicit disconnect, stale thread cleanup, and same-profile follower resume. Impact: Threaded Mode degrades forward across local process churn while preserving the intended thread binding where possible.
- `[Native Activity Status]` Kept Telegram work indication native-only through Bot API `sendChatAction(typing)` / Telegram client `...active` status. Custom progress/activity/thinking message surfaces are not part of the release path. Impact: long-running work uses the Telegram-native affordance instead of adding extra chat noise.
- `[Compaction Activity]` Scoped typing to real work: active Telegram turns, tool/reasoning/message activity during those turns, confirmed manual `/compact`, and automatic compaction only when it belongs to an active Telegram turn. Thread-scoped typing preserves the concrete thread target and mirrors to `All` as aggregate activity. Impact: compaction shows native activity when it should, without reviving startup/connect/reload typing.
- `[Thread-Scoped Delivery]` Propagated `{ chatId, threadId? }` across inbound routing, replies, previews/drafts, typing, voice, attachments, menus, sections, callbacks, reactions, media groups, slash commands, and follower-routed Bot API calls. Impact: classic DM delivery and thread delivery share one target-scoped transport contract.
- `[Replies And Drafts]` Anchored the first assistant reply block to the prompting message in Thread Mode and kept later chunks sequential; preview rollover preserves the active turn's source reply metadata. Telegram Desktop may still omit the visual reply header despite the same correct payload that mobile renders. Impact: thread conversations keep local reply context without stacking headers on every chunk.
- `[Thread UX]` Improved unbound-thread reroute/restore flows, cleanup of temporary chooser surfaces, connected/offline notices, status/menu role indicators, and routing controls. Impact: operator-facing Thread Mode surfaces are more recognizable and less likely to leave stale controls behind.
- `[Proactive Push]` Allowed Thread Mode followers to send successful local non-Telegram final replies through the leader transport when `proactivePush` is enabled. Impact: follower-owned local results can reach the assigned thread without granting unrelated non-owner processes Telegram delivery.
- `[Replies And Drafts]` Anchored the first assistant reply block to the prompting message in Threaded Mode and kept later chunks sequential; preview rollover preserves the active turn's source reply metadata. Telegram Desktop may still omit the visual reply header despite the same correct payload that mobile renders. Impact: thread conversations keep local reply context without stacking headers on every chunk.
- `[Thread UX]` Improved unbound-thread reroute/restore flows, cleanup of temporary chooser surfaces, connected/offline notices, status/menu role indicators, and routing controls. Impact: operator-facing Threaded Mode surfaces are more recognizable and less likely to leave stale controls behind.
- `[Proactive Push]` Allowed Threaded Mode followers to send successful local non-Telegram final replies through the leader transport when `proactivePush` is enabled. Impact: follower-owned local results can reach the assigned thread without granting unrelated non-owner processes Telegram delivery.
- `[Agent Responsiveness]` Moved successful Telegram turn follow-up delivery work into extension-owned background tasks. Impact: Pi can leave the working state sooner after producing the final answer while preserving Telegram delivery ordering.
- `[Telegram API Transport]` Added `PI_TELEGRAM_NETWORK_FAMILY=auto|ipv4|ipv6|ipv4-fallback`; the default `ipv4-fallback` retries transport-level dual-stack failures through Node's IPv4-only HTTPS path after native `fetch`. JSON calls, multipart uploads, and file downloads now share one transport helper with richer redacted diagnostics. Impact: hosts with broken IPv6 can keep polling, typing, drafts, downloads, uploads, and direct tools working without global DNS changes.
- `[Security]` Hardened local bus authorization with leader-minted secrets, derived private endpoints, allowed-user checks, target-scoped follower Bot API allowlists, and liveness refreshes around forwarded updates/API calls. Impact: followers can use their assigned thread without gaining arbitrary bot control.
- `[Windows IPC]` Added native Windows named-pipe path selection for the local leader/follower bus alongside Unix socket support. Impact: Thread Mode has an intended native Windows transport path, with live Windows smoke still tracked separately in the backlog.
- `[Diagnostics]` Expanded `/telegram-status`, `tmp/telegram/state.json`, and redacted `tmp/telegram/logs.jsonl` around runtime role, roster, capability state, reservations, thread reconciliation, and transport health, without making diagnostics files routing authority. Impact: operators and agents can inspect Thread Mode health without depending on stale history.
- `[Validation]` Split Thread Mode coverage across focused bus, leader, follower, runtime, integration, routing, lifecycle, and delivery tests. Impact: the release behavior is pinned by domain-owned regressions rather than one oversized integration bucket.
- `[Architecture]` Moved Thread Mode logic out of `index.ts` into focused domains for bus protocol, leader runtime, follower runtime, thread bindings, synchronization, polling/capability switching, and reconciliation. The separate public `telegram.json` bus switch was removed from the product model and implementation. Impact: the public surface stays small, classic mode remains the base mode, BotFather Thread Mode is the multi-instance switch, and product language consistently says Thread while Bot API topics remain implementation details.
- `[Windows IPC]` Added native Windows named-pipe path selection for the local leader/follower bus alongside Unix socket support. Impact: Threaded Mode has an intended native Windows transport path, with live Windows smoke still tracked separately in the backlog.
- `[Diagnostics]` Expanded `/telegram-status`, `tmp/telegram/state.json`, and redacted `tmp/telegram/logs.jsonl` around runtime role, roster, capability state, reservations, thread reconciliation, and transport health, without making diagnostics files routing authority. Impact: operators and agents can inspect Threaded Mode health without depending on stale history.
- `[Validation]` Split Threaded Mode coverage across focused bus, leader, follower, runtime, integration, routing, lifecycle, and delivery tests. Impact: the release behavior is pinned by domain-owned regressions rather than one oversized integration bucket.
- `[Architecture]` Moved Threaded Mode logic out of `index.ts` into focused domains for bus protocol, leader runtime, follower runtime, thread bindings, synchronization, polling/capability switching, and reconciliation. The separate public `telegram.json` bus switch was removed from the product model and implementation. Impact: the public surface stays small, classic mode remains the base mode, Telegram private-chat Threaded Mode is the multi-instance switch, and product language consistently says thread while Bot API topics remain implementation details.

## 0.17.5: Screenshot Refresh

Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ This repository is an actively maintained fork of [`badlogic/pi-telegram`](https
- **Mobile supervision**: continue a live Pi session from Telegram without turning Telegram into a fake terminal.
- **Telegram-native controls**: menus, settings, queue controls, native active status, Rich Markdown replies, drafts, buttons, voice, files, and artifacts.
- **Safe runtime mapping**: Telegram turns map into Pi lifecycle, queueing, model switching, compaction, previews, final replies, and ownership rules.
- **Optional Threaded Mode**: one leader and visible follower Pi processes can share one bot through named Telegram Threads.
- **Optional Threaded Mode**: one leader and visible follower Pi processes can share one bot through named Telegram threads.
- **Extension platform**: companion extensions can add Telegram-native commands, sections, status rows, update handlers, handlers, and voice providers without owning polling.

Use this README for the product shape. Follow the docs for exact contracts.
Expand Down Expand Up @@ -59,7 +59,7 @@ Paste your bot token when prompted. If a bot token is already saved in `~/.pi/ag
/telegram-connect
```

The adapter is session-local: only one Pi instance polls Telegram at a time. In classic mode, `/telegram-connect` records external control/polling ownership in `~/.pi/agent/locks.json`. When BotFather Threaded Mode is available, `/telegram-connect` uses the local Telegram organism automatically: the first live instance becomes leader, later live instances register as followers instead of taking over while the leader heartbeat is healthy. Local queue and reply state stay per Pi instance, so an instance that loses Telegram control still finishes work it already accepted.
The adapter is session-local: only one Pi instance polls Telegram at a time. In classic mode, `/telegram-connect` records external control/polling ownership in `~/.pi/agent/locks.json`. When Telegram private-chat Threaded Mode is available for the bot, `/telegram-connect` uses the local Telegram organism automatically: the first live instance becomes leader, later live instances register as followers instead of taking over while the leader heartbeat is healthy. Local queue and reply state stay per Pi instance, so an instance that loses Telegram control still finishes work it already accepted.

### 4. Pair your Telegram account

Expand Down Expand Up @@ -130,11 +130,11 @@ Send files or images directly to the bot. Inbound downloads are saved under `<ag

If you ask Pi for a generated file, Pi can call `telegram_attach`: during a Telegram-originated turn the adapter sends it with the next Telegram reply, and during local/TUI work it sends directly to the paired/default chat, a registered follower's assigned thread, or explicit `chat_id` plus optional `thread_id`. Local work can also use `telegram_message` when you explicitly ask the agent to push a Markdown text message to Telegram; embedded `telegram_button` comments are parsed and attached to that message. Direct local/TUI delivery requires the current Pi instance to own `/telegram-connect`, or to be registered with an explicitly enabled multi-instance bus so it can route through the leader; if neither is true, take over or enable/register with the bus before sending. Outbound attachments default to a 50 MiB limit. Environment variables for both limits are listed in [Environment-only configuration](#environment-only-configuration).

### BotFather Threads and multi-instance bus
### Telegram Threaded Mode and multi-instance bus

BotFather Threaded Mode is the switch. Classic single-DM polling is the base mode. When Telegram reports private-chat Threads are available, the adapter enables the local leader/follower bus automatically; when Threads are unavailable or later disabled, it uses classic single-DM polling as the ordinary private-bot mode.
Telegram private-chat Threaded Mode is the switch. Classic single-DM polling is the base mode. When Telegram reports private-chat threads are available for the bot, the adapter enables the local leader/follower bus automatically; when threads are unavailable or later disabled, it uses classic single-DM polling as the ordinary private-bot mode.

Only the leader calls `getUpdates`; followers authenticate to the local bus and route allowlisted, target-scoped Telegram work through the leader. When BotFather Threads are available, they become the UI targets:
Only the leader calls `getUpdates`; followers authenticate to the local bus and route allowlisted, target-scoped Telegram work through the leader. When private-chat threads are available, they become the UI targets:

- The leader owns one thread;
- Each explicitly connected follower gets one visible thread;
Expand All @@ -143,7 +143,7 @@ Only the leader calls `getUpdates`; followers authenticate to the local bus and
- Unknown owner-created threads preserve the original prompt and offer a target-thread chooser instead of spawning work invisibly;
- Stale follower tabs receive compact lifecycle notices before cleanup when the leader can prove ownership.

Threaded input is still authorized by `allowedUserId`. There is no separate public `telegram.json` switch for the bus: Telegram capability detection is the runtime source of truth. Native Windows Threaded Mode smoke remains tracked in `BACKLOG.md`; the intended transport is the same local bus over Windows named pipes instead of Unix sockets.
Thread input is still authorized by `allowedUserId`. There is no separate public `telegram.json` switch for the bus: Telegram capability detection is the runtime source of truth. Native Windows Threaded Mode smoke remains tracked in `BACKLOG.md`; the intended transport is the same local bus over Windows named pipes instead of Unix sockets.

## Core features

Expand Down
Loading
Loading