@llblab/pi-telegram 0.9.5 → 0.9.6
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/AGENTS.md +4 -2
- package/BACKLOG.md +4 -0
- package/CHANGELOG.md +8 -0
- package/README.md +114 -116
- package/docs/architecture.md +1 -1
- package/lib/api.ts +6 -4
- package/package.json +2 -2
package/AGENTS.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
## 1. Concept
|
|
13
13
|
|
|
14
|
-
`pi-telegram` is a
|
|
14
|
+
`pi-telegram` is a Telegram Runtime Adapter for π: a session-local operator console that turns a private Telegram DM into a runtime surface for prompt intake, streaming previews, queue management, model/thinking/settings controls, inbound/outbound handler pipelines, voice/buttons, artifacts, and extension callback interop. Treat it as a Telegram membrane around π, not a narrow message pipe.
|
|
15
15
|
|
|
16
16
|
## 2. Identity & Naming Contract
|
|
17
17
|
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
- `/tests/*.test.ts`: Domain-mirrored regression suites that follow the same flat naming as `/lib`
|
|
29
29
|
- `/docs/README.md`: Documentation index for technical project docs
|
|
30
30
|
- `/docs/architecture.md`: Runtime and subsystem overview for the bridge
|
|
31
|
-
- `/README.md`: User-facing project entry point
|
|
31
|
+
- `/README.md`: User-facing project entry point. Keep its rhythm as install → connect → use → core features → docs, with vivid examples that explain the runtime adapter/operator-console model without duplicating full docs.
|
|
32
32
|
- `/AGENTS.md`: Durable engineering and runtime conventions
|
|
33
33
|
- `/BACKLOG.md`: Canonical open work
|
|
34
34
|
- `/CHANGELOG.md`: Completed delivery history
|
|
@@ -122,6 +122,8 @@ The canonical detailed ownership map lives in [`docs/architecture.md`](./docs/ar
|
|
|
122
122
|
- When Telegram-visible behavior changes, sync `README.md` and the relevant `/docs` entry in the same pass
|
|
123
123
|
- When durable runtime constraints or repeat bug patterns emerge, record them here instead of burying them in changelog prose
|
|
124
124
|
- When fork identity changes, keep `README.md`, package metadata, and docs aligned so the published package does not point back at stale upstream coordinates
|
|
125
|
+
- README positioning should emphasize `/start` as the primary Telegram operator menu and keep reaction shortcuts secondary. Reactions are useful queue affordances, but menu controls are the core CLI-to-Telegram bridge.
|
|
126
|
+
- Document configuration knobs without UI in the root README when they affect bootstrap, networking, or transport limits; currently this includes token env bootstrap, Node env proxy mode, and inbound/outbound size limits.
|
|
125
127
|
- Work only inside this repository during development tasks; updating the installed Pi extension checkout is a separate manual operator step, not part of normal in-repo implementation work
|
|
126
128
|
|
|
127
129
|
## 8. Integration Protocols
|
package/BACKLOG.md
CHANGED
|
@@ -8,3 +8,7 @@
|
|
|
8
8
|
- Priority: Low.
|
|
9
9
|
- Idea: Provide tools such as `telegram_attach_file` and `telegram_attach_button` that can be called outside an active Telegram turn, using the paired chat/session as the delivery target when safe.
|
|
10
10
|
- Exit: Design note defines active-turn versus ambient delivery semantics, safety constraints, failure modes, and whether the current `telegram_attach` contract should stay turn-scoped or gain an ambient companion.
|
|
11
|
+
- Tighten dependency posture for reproducible extension development.
|
|
12
|
+
- Priority: Medium.
|
|
13
|
+
- Idea: Replace broad peer dependency `*` ranges and dev dependency `latest` ranges with explicit compatible ranges once the supported pi/Node/TypeScript matrix is clear.
|
|
14
|
+
- Exit: `package.json` documents the supported Node expectation and compatible pi package ranges without over-constraining early-stage extension iteration.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.9.6: Runtime Adapter Positioning
|
|
4
|
+
|
|
5
|
+
- `[Package]` Bumped package metadata to `0.9.6` and repositioned the package description from "Better Telegram DM bridge extension for π" to "Telegram Runtime Adapter for π". Impact: package metadata now reflects the runtime adapter/operator-console role rather than a narrow pipe metaphor.
|
|
6
|
+
- `[Telegram API]` Introduced `TELEGRAM_API_BASE` for the Bot API endpoint and documented native HTTP/HTTPS proxy operation through `HTTP_PROXY`, `HTTPS_PROXY`, `NO_PROXY`, and explicit `NODE_USE_ENV_PROXY=1` / `--use-env-proxy` enablement. Impact: users behind corporate proxies, local HTTP tunnels, or restricted networks get a zero-runtime-dependency proxy path without replacing native `fetch`; SOCKS5 remains outside the zero-dependency core.
|
|
7
|
+
- `[Dependencies]` Refreshed the lockfile transitive dependency set so `npm audit` clears current `fast-uri` and `fast-xml-builder` advisories inherited through development peer installs. Impact: the full `npm run validate` pipeline passes without changing runtime dependencies.
|
|
8
|
+
- `[README]` Restructured the user entrypoint around install → connect → use → core features → docs, then consolidated examples, terminology, proxy setup, `PI_CODING_AGENT_DIR`, and other environment-only configuration around the runtime-adapter/operator-console model. Impact: first-time users get a clearer path from installation to operation, while vivid examples and non-UI runtime knobs stay discoverable.
|
|
9
|
+
- `[Context]` Promoted the runtime-adapter/operator-console README rhythm, `/start` menu emphasis, and environment-only configuration rule into `AGENTS.md`. Impact: future documentation edits preserve the same positioning and env-knob coverage instead of drifting back toward a narrow bridge metaphor.
|
|
10
|
+
|
|
3
11
|
## 0.9.5: Telegram Delivery Resilience Hotfix
|
|
4
12
|
|
|
5
13
|
- `[Preview Delivery]` Preview flush failures from Telegram transport errors such as `fetch failed` / `ECONNRESET` are now caught and recorded as runtime diagnostics instead of escaping from the preview pipeline. Impact: transient Telegram connectivity failures no longer crash the extension during streamed preview edits.
|
package/README.md
CHANGED
|
@@ -2,24 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## Start Here
|
|
5
|
+
**Telegram Runtime Adapter for π.**
|
|
8
6
|
|
|
9
|
-
-
|
|
10
|
-
- [Open Backlog](./BACKLOG.md)
|
|
11
|
-
- [Changelog](./CHANGELOG.md)
|
|
12
|
-
- [Documentation](./docs/README.md)
|
|
7
|
+
`pi-telegram` turns a private Telegram DM into a session-local operator console for π. It admits work, preserves context, streams readable replies, keeps busy sessions usable through queues, lets other extensions share one bot, and turns assistant-authored intent into native Telegram artifacts.
|
|
13
8
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
- **Telegram Controls**: `/start` opens the inline application menu with command help, available π prompt templates, status rows, model, thinking, and queue sections; the Status row reports `compacting` during Telegram `/compact`; `/stop`, `/abort`, `/next`, and `/continue` provide queue-clear, queue-preserve, force-next, and queued-resume semantics respectively; model-switch continuation turns still use the control lane when a restart needs to resume safely.
|
|
17
|
-
- **Interactive UI**: Manage your session directly from Telegram. Inline buttons expose an application menu for switching models, choosing model pages from the pagination indicator, adjusting reasoning (thinking) levels, and inspecting or mutating the waiting queue; model scope/pagination controls stay at the top of the model menu, the Queue button shows the current item count, and command emoji are reused on matching controls such as model and thinking.
|
|
18
|
-
- **In-flight Model Switching**: Change the active model mid-generation. The agent gracefully pauses, applies the new model, and restarts its response without losing context.
|
|
19
|
-
- **Smart Message Queue**: Messages sent while the agent is busy are queued and previewed in the π status bar, and queued turns can be reprioritized or removed with Telegram reactions or the queue section of the inline application menu.
|
|
20
|
-
- **Mobile-Optimized Rendering**: Tables and lists are formatted for narrow screens, table padding accounts for emoji grapheme and wide Unicode display width, and Telegram-originated runs prompt the assistant to prefer narrow table columns for phone readability. Markdown is correctly parsed and split to fit Telegram's limits without breaking HTML structures or code blocks, block spacing stays faithful to the original Markdown with readable heading separation, supported absolute links stay clickable, and unsupported link forms degrade safely.
|
|
21
|
-
- **File Handling & Attachments**: Send images and files to the agent, transcribe or transform inbound text/media with configured inbound handlers, or ask π to generate and return artifacts. Inbound downloads and outbound attachments are size-limited by default, and outbound files are delivered automatically via the `telegram_attach` tool.
|
|
22
|
-
- **Streaming Responses**: Closed Markdown blocks stream back as rich Telegram HTML while π is generating, and the still-growing tail stays readable until the final fully rendered reply lands.
|
|
9
|
+
This repository is an actively maintained fork of [`badlogic/pi-telegram`](https://github.com/badlogic/pi-telegram). It started from upstream commit [`cb34008460b6c1ca036d92322f69d87f626be0fc`](https://github.com/badlogic/pi-telegram/commit/cb34008460b6c1ca036d92322f69d87f626be0fc) and has since diverged substantially.
|
|
23
10
|
|
|
24
11
|
## Install
|
|
25
12
|
|
|
@@ -35,22 +22,16 @@ From git:
|
|
|
35
22
|
pi install git:github.com/llblab/pi-telegram
|
|
36
23
|
```
|
|
37
24
|
|
|
38
|
-
##
|
|
25
|
+
## Connect
|
|
39
26
|
|
|
40
|
-
###
|
|
41
|
-
|
|
42
|
-
The extension intentionally keeps rich visual/TUI configuration minimal for now. Rich setup screens may arrive later, but they are not the main configuration surface yet.
|
|
43
|
-
|
|
44
|
-
For advanced setup, ask an agent to read this `README.md` and the docs, then update `~/.pi/agent/telegram.json` for your workflow. Agents are good at small configuration changes, and this keeps the bridge simple while handler pipelines and operator preferences continue to evolve.
|
|
45
|
-
|
|
46
|
-
### 1. Telegram Bot
|
|
27
|
+
### 1. Create a Telegram bot
|
|
47
28
|
|
|
48
29
|
1. Open [@BotFather](https://t.me/BotFather)
|
|
49
30
|
2. Run `/newbot`
|
|
50
31
|
3. Pick a name and username
|
|
51
32
|
4. Copy the bot token
|
|
52
33
|
|
|
53
|
-
### 2. Configure the
|
|
34
|
+
### 2. Configure the bot token in π
|
|
54
35
|
|
|
55
36
|
Start π, then run:
|
|
56
37
|
|
|
@@ -66,63 +47,110 @@ Paste your bot token when prompted. If a bot token is already saved in `~/.pi/ag
|
|
|
66
47
|
/telegram-connect
|
|
67
48
|
```
|
|
68
49
|
|
|
69
|
-
The
|
|
50
|
+
The adapter is session-local: only one π instance polls Telegram at a time. `/telegram-connect` records polling ownership in `~/.pi/agent/locks.json`; live ownership moves require confirmation, while `/new` and same-`cwd` process restarts resume automatically.
|
|
70
51
|
|
|
71
|
-
### 4. Pair your account
|
|
52
|
+
### 4. Pair your Telegram account
|
|
72
53
|
|
|
73
54
|
1. Open the DM with your bot in Telegram
|
|
74
55
|
2. Send `/start`
|
|
75
56
|
|
|
76
|
-
The first user to message the bot becomes the exclusive owner of the
|
|
57
|
+
The first user to message the bot becomes the exclusive owner of the adapter. Messages from other users are ignored.
|
|
77
58
|
|
|
78
|
-
|
|
59
|
+
### Environment-only configuration
|
|
79
60
|
|
|
80
|
-
|
|
61
|
+
Most day-to-day controls live in the Telegram menu or π commands. A few important runtime knobs intentionally stay in environment variables because they affect bootstrap, networking, or transport limits before a menu can help:
|
|
81
62
|
|
|
82
|
-
|
|
63
|
+
- **Bot token bootstrap**: `/telegram-setup` can prefill from `TELEGRAM_BOT_TOKEN`, `TELEGRAM_BOT_KEY`, `TELEGRAM_TOKEN`, or `TELEGRAM_KEY` when no token is already saved.
|
|
64
|
+
- **HTTP/HTTPS proxy**: native `fetch` can use `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY` when Node's environment proxy mode is enabled. Use `NODE_USE_ENV_PROXY=1` or start Node with `--use-env-proxy`.
|
|
65
|
+
- **Agent data root / temp location**: `PI_CODING_AGENT_DIR` changes the base agent directory used for `telegram.json`, locks, generated outbound-handler artifacts, and Telegram temp files. When unset, the adapter uses `~/.pi/agent`, so inbound Telegram files land in `~/.pi/agent/tmp/telegram`.
|
|
66
|
+
- **Inbound file limit**: `PI_TELEGRAM_INBOUND_FILE_MAX_BYTES` or `TELEGRAM_MAX_FILE_SIZE_BYTES` changes the default 50 MiB Telegram download limit.
|
|
67
|
+
- **Outbound attachment limit**: `PI_TELEGRAM_OUTBOUND_ATTACHMENT_MAX_BYTES` or `TELEGRAM_MAX_ATTACHMENT_SIZE_BYTES` changes the default 50 MiB `telegram_attach` delivery limit.
|
|
83
68
|
|
|
84
|
-
|
|
69
|
+
Proxy example:
|
|
85
70
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
71
|
+
```bash
|
|
72
|
+
export HTTPS_PROXY="http://127.0.0.1:8083"
|
|
73
|
+
export HTTP_PROXY="http://127.0.0.1:8083"
|
|
74
|
+
export NO_PROXY="localhost,127.0.0.1"
|
|
75
|
+
export NODE_USE_ENV_PROXY=1
|
|
76
|
+
|
|
77
|
+
pi
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
SOCKS5 is not part of the zero-dependency core. If you need it, run a local HTTP-to-SOCKS bridge or system tunnel and point `HTTP_PROXY` / `HTTPS_PROXY` at the HTTP endpoint.
|
|
81
|
+
|
|
82
|
+
## Use
|
|
83
|
+
|
|
84
|
+
Once paired, chat with your bot in Telegram. Text, images, files, replies, edits, media groups, and configured handler output are forwarded into π as Telegram-originated turns.
|
|
85
|
+
|
|
86
|
+
What it feels like:
|
|
87
|
+
|
|
88
|
+
- Open `/start` and get a Telegram control panel for the running π session: status, prompt templates, model, thinking, settings, and queue.
|
|
89
|
+
- Fire off three tasks while π is busy. They become visible queue items instead of terminal noise.
|
|
90
|
+
- Open Queue from the menu, inspect waiting work, delete stale prompts, or move important work forward.
|
|
91
|
+
- Switch models from Telegram mid-run; the adapter schedules a safe continuation instead of tearing state apart.
|
|
92
|
+
- Send a voice note; an inbound handler transcribes it; π answers in the same chat.
|
|
93
|
+
- Drop a screenshot and ask, "what is broken here?" The image payload reaches π with the local file context.
|
|
94
|
+
- Ask for a generated file; when π calls `telegram_attach`, the artifact returns to Telegram with the next reply.
|
|
92
95
|
|
|
93
|
-
|
|
96
|
+
### Telegram controls
|
|
94
97
|
|
|
95
|
-
|
|
98
|
+
Use these inside the Telegram DM with your bot. The main entrypoint is `/start`: it opens the operator menu and exposes many of the important agent controls that normally live in the CLI, adapted for Telegram.
|
|
96
99
|
|
|
97
|
-
|
|
100
|
+
- **`/start`**: Pair the first Telegram user when needed, register bot commands, and open the inline application menu with command help, prompt-template commands, status rows, model controls, thinking controls, settings, and queue controls.
|
|
101
|
+
- **`/compact`**: Start session compaction when the session is idle.
|
|
102
|
+
- **`/next`**: Dispatch the next queued turn, aborting π first if needed.
|
|
103
|
+
- **`/continue`**: Enqueue a priority `continue` prompt.
|
|
104
|
+
- **`/abort`**: Abort the active run without touching the queue.
|
|
105
|
+
- **`/stop`**: Abort the active run and clear waiting Telegram queue items.
|
|
106
|
+
|
|
107
|
+
Hidden compatibility shortcuts: `/help` and `/status` open the main application menu, `/model` opens model controls, `/thinking` opens reasoning controls, `/queue` opens queue controls, and `/settings` opens bridge settings.
|
|
98
108
|
|
|
99
|
-
|
|
109
|
+
Prompt-template commands are discovered from π prompt templates, mapped to Telegram-safe aliases (`fix-tests.md` becomes `/fix_tests`), shown in `/start`, and expanded before queueing.
|
|
110
|
+
|
|
111
|
+
### π commands
|
|
100
112
|
|
|
101
113
|
Run these inside π, not Telegram:
|
|
102
114
|
|
|
103
115
|
- **`/telegram-setup`**: Configure or update the Telegram bot token.
|
|
104
|
-
- **`/telegram-
|
|
105
|
-
- **`/telegram-settings`**: Open local
|
|
106
|
-
- **`/telegram-connect`**: Start polling Telegram updates in the current π session, acquire the singleton lock, or interactively move ownership here from another live instance.
|
|
116
|
+
- **`/telegram-connect`**: Start polling Telegram updates in the current π session and acquire the singleton lock.
|
|
117
|
+
- **`/telegram-settings`**: Open local settings and toggle proactive push using the same `telegram.json` flag as the Telegram `/settings` menu.
|
|
107
118
|
- **`/telegram-disconnect`**: Stop polling in the current π session and release the singleton lock.
|
|
119
|
+
- **`/telegram-status`**: Inspect adapter status, connection, polling, execution, queue, and recent redacted runtime/API failure events.
|
|
120
|
+
|
|
121
|
+
### Files and artifacts
|
|
122
|
+
|
|
123
|
+
Send files or images directly to the bot. Inbound downloads are saved under `<agent-dir>/tmp/telegram` and default to a 50 MiB limit. The agent dir is `~/.pi/agent` unless `PI_CODING_AGENT_DIR` overrides it.
|
|
124
|
+
|
|
125
|
+
If you ask π for a generated file, π can call the `telegram_attach` tool and the adapter sends the file with the next Telegram reply. Outbound attachments also default to a 50 MiB limit. Environment variables for both limits are listed in [Environment-only configuration](#environment-only-configuration).
|
|
126
|
+
|
|
127
|
+
## Core features
|
|
128
|
+
|
|
129
|
+
### Operator menu and controls
|
|
108
130
|
|
|
109
|
-
|
|
131
|
+
The inline application menu is the primary operator surface. It exposes status, prompt-template commands, model selection, thinking level selection, settings, and queue inspection/mutation: a Telegram-shaped subset of the important handles normally available from the CLI. A typical control loop stays inside Telegram: open `/start`, inspect status, jump into Queue, delete stale work, switch model, return to the main menu, and keep the π session running without touching the terminal.
|
|
110
132
|
|
|
111
|
-
|
|
112
|
-
- Very long text messages that Telegram appears to split automatically are coalesced through a short conservative debounce and forwarded to π as one prompt when the first chunk is near Telegram's text limit, currently using a 3600-character threshold. Commands, bot messages, media groups, and normal short follow-ups are not coalesced.
|
|
113
|
-
- `👍`, `⚡️`, `❤️`, `🕊`, and `🔥` move a waiting prompt into the priority prompt queue, behind control actions but ahead of default prompts. Removing the last priority reaction sends it back to its normal queue position, and adding a priority reaction again gives it a fresh priority position.
|
|
114
|
-
- `👎`, `👻`, `💔`, `💩`, and `🗑` remove a waiting turn from the queue. Telegram Bot API does not expose ordinary DM message-deletion events through the polling path used here, so queue removal is bound to removal reactions.
|
|
115
|
-
- Reactions apply to any waiting Telegram turn, including text, voice, files, images, and media groups. For media groups, a reaction on any message in the group applies to the whole queued turn.
|
|
116
|
-
- If you edit a Telegram message while it is still waiting in the queue, the queued turn is updated instead of creating a duplicate prompt. Edits after a turn has already started may not affect the active run.
|
|
117
|
-
- Telegram replies to earlier text or caption messages are forwarded as `[reply]` context for normal prompts, while slash commands still parse from the new message text only.
|
|
118
|
-
- Inbound images, albums, and files are saved to `~/.pi/agent/tmp/telegram`. Unhandled local file paths are included in the prompt, handled attachment output is injected into the prompt text, and inbound images are forwarded to π as image inputs. Inbound downloads default to a 50 MiB limit and can be adjusted with `PI_TELEGRAM_INBOUND_FILE_MAX_BYTES` or `TELEGRAM_MAX_FILE_SIZE_BYTES`.
|
|
119
|
-
- Queue reactions depend on Telegram delivering `message_reaction` updates for your bot and chat type.
|
|
133
|
+
### Queue runtime
|
|
120
134
|
|
|
121
|
-
|
|
135
|
+
Messages sent while π is busy enter the prompt queue and are processed in order. Control actions and model-switch continuation turns use higher-priority lanes so operational commands can resume before normal prompts.
|
|
122
136
|
|
|
123
|
-
|
|
137
|
+
The menu is the primary way to inspect and mutate the queue. Reactions are an extra shortcut when Telegram delivers `message_reaction` updates for the chat: `👍`, `⚡️`, `❤️`, `🕊`, and `🔥` promote waiting work; `👎`, `👻`, `💔`, `💩`, and `🗑` remove it. The set intentionally includes common default reactions first; premium-only reactions such as `🗑` are optional convenience, not the core queue UI. The same rules apply to text, voice, files, images, and media groups.
|
|
124
138
|
|
|
125
|
-
|
|
139
|
+
### Streaming and Telegram HTML rendering
|
|
140
|
+
|
|
141
|
+
Closed Markdown blocks stream back as rich Telegram HTML while π is generating. The growing tail stays conservative until the final rendered reply lands. Long replies are split below Telegram limits without intentionally breaking HTML structures, links, code blocks, blockquotes, lists, or code fences.
|
|
142
|
+
|
|
143
|
+
Rendering is phone-aware: tables and lists stay narrow, table padding accounts for emoji graphemes and wide Unicode display width, unsupported link forms degrade safely, and block spacing stays faithful to the original Markdown.
|
|
144
|
+
|
|
145
|
+
### Media, replies, edits, and split text
|
|
146
|
+
|
|
147
|
+
Telegram replies to earlier text or caption messages are forwarded as `[reply]` context for normal prompts, while slash commands still parse from the new message text only. If a Telegram message is edited while still waiting in the queue, the queued turn is updated instead of duplicated. Very long text messages that Telegram appears to split automatically are coalesced through a conservative debounce when the first chunk is near Telegram's text limit.
|
|
148
|
+
|
|
149
|
+
### Inbound handlers
|
|
150
|
+
|
|
151
|
+
`telegram.json` can define ordered `inboundHandlers` for Telegram → π preprocessing: text translation, voice transcription, OCR, PDF extraction, or any command-template pipeline. Matching handlers run before the turn enters the queue; failed handlers record diagnostics and fall back safely. Legacy `attachmentHandlers` still work as a deprecated compatibility alias appended after `inboundHandlers`.
|
|
152
|
+
|
|
153
|
+
A practical voice setup is simple: Telegram `.ogg` arrives, STT runs locally or through your chosen command, stdout is injected as `[outputs]`, and π receives the result as usable prompt context.
|
|
126
154
|
|
|
127
155
|
```json
|
|
128
156
|
{
|
|
@@ -149,19 +177,9 @@ Run these inside π, not Telegram:
|
|
|
149
177
|
}
|
|
150
178
|
```
|
|
151
179
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
### Requesting Files
|
|
180
|
+
### Outbound handlers, voice, and buttons
|
|
155
181
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
### Assistant-Authored Outbound Actions
|
|
159
|
-
|
|
160
|
-
Assistant replies can include hidden outbound blocks. `telegram_voice` and `telegram_button` are not π tools; they are assistant-authored HTML comments that the bridge removes from Telegram text and handles after `agent_end`. Recognized blocks must start at column zero on a top-level line outside fenced code, quotes, and lists, so documentation examples remain literal. The agent writes normal Markdown; the extension owns voice generation, button markup, callback routing, and delivery.
|
|
161
|
-
|
|
162
|
-
#### Voice
|
|
163
|
-
|
|
164
|
-
Voice blocks synthesize their text and upload it as a native Telegram `sendVoice` OGG/Opus message. Use body form for multiline text, `text="..."` for explicit one-line text with optional attributes, and the colon shorthand for a one-line voice with no attributes. The spoken text may be a concise companion summary, but it does not have to follow that format; write what you want spoken and keep it TTS-friendly:
|
|
182
|
+
Assistant replies can include hidden outbound blocks. `telegram_voice` and `telegram_button` are not π tools; they are assistant-authored HTML comments that the adapter removes from Telegram text and handles after `agent_end`. Recognized blocks must start at column zero on a top-level line outside fenced code, quotes, and lists.
|
|
165
183
|
|
|
166
184
|
```md
|
|
167
185
|
Full technical answer stays readable as text.
|
|
@@ -170,27 +188,14 @@ Full technical answer stays readable as text.
|
|
|
170
188
|
Text to synthesize as a Telegram voice message.
|
|
171
189
|
-->
|
|
172
190
|
|
|
173
|
-
<!--
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
Outbound `type: "text"` handlers can transform final text/Markdown before Telegram rendering and delivery, using stdin and `{text}` as input and non-empty stdout as replacement text. They are a good fit for machine translation, tone normalization, redaction, glossary expansion, or any other final text rewrite that should happen outside the agent prompt. The transform also applies when the bridge finalizes an already streamed rich preview, so Telegram may briefly show the pre-transform preview before the final edited message lands. Inline button labels are transformed too, while callback data and prompts stay unchanged.
|
|
179
|
-
|
|
180
|
-
```json
|
|
181
|
-
{
|
|
182
|
-
"outboundHandlers": [
|
|
183
|
-
{
|
|
184
|
-
"type": "text",
|
|
185
|
-
"template": "/path/to/translate --lang {lang=ru} --text {text}"
|
|
186
|
-
}
|
|
187
|
-
]
|
|
188
|
-
}
|
|
191
|
+
<!-- telegram_button label="Show risks"
|
|
192
|
+
List the main risks first.
|
|
193
|
+
-->
|
|
189
194
|
```
|
|
190
195
|
|
|
191
|
-
Outbound
|
|
196
|
+
Outbound `type: "text"` handlers can transform final text/Markdown before Telegram rendering and delivery. Outbound `type: "voice"` handlers can translate, synthesize, and convert hidden `telegram_voice` text into Telegram-native OGG/Opus voice through the same command-template contract used by inbound handlers.
|
|
192
197
|
|
|
193
|
-
A composed voice
|
|
198
|
+
A composed voice pipeline can translate, synthesize, and convert in one pass:
|
|
194
199
|
|
|
195
200
|
```json
|
|
196
201
|
{
|
|
@@ -208,43 +213,36 @@ A composed voice setup can translate the hidden `telegram_voice` text, synthesiz
|
|
|
208
213
|
}
|
|
209
214
|
```
|
|
210
215
|
|
|
211
|
-
|
|
216
|
+
The agent writes intent; the adapter owns transport. Text remains readable, voice becomes native Telegram media, and buttons route back as queued prompts.
|
|
212
217
|
|
|
213
|
-
|
|
218
|
+
### Extension interop
|
|
214
219
|
|
|
215
|
-
|
|
216
|
-
I can continue.
|
|
220
|
+
Unknown inline-button callbacks are forwarded to π as `[callback] <data>` when they do not belong to pi-telegram, so other extensions can namespace and handle Telegram buttons without polling the bot themselves. Layered extensions that need synchronous update handling can register a runtime interceptor on the shared update registry.
|
|
217
221
|
|
|
218
|
-
|
|
219
|
-
List the main risks first.
|
|
220
|
-
-->
|
|
222
|
+
### Proactive push
|
|
221
223
|
|
|
222
|
-
|
|
224
|
+
`telegram.json` can set `proactivePush: true` to send successful local non-Telegram final replies to the paired Telegram chat when no Telegram turn is active. Local prompt text is not mirrored because the bot does not own terminal user messages. The mode is off by default and can be toggled from settings.
|
|
223
225
|
|
|
224
|
-
|
|
225
|
-
```
|
|
226
|
+
## Docs
|
|
226
227
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
```text
|
|
240
|
-
telegram active +3
|
|
241
|
-
```
|
|
228
|
+
- [Project Context](./AGENTS.md): durable engineering conventions and architecture constraints.
|
|
229
|
+
- [Open Backlog](./BACKLOG.md): planned work and known follow-ups.
|
|
230
|
+
- [Changelog](./CHANGELOG.md): completed delivery history.
|
|
231
|
+
- [Documentation Index](./docs/README.md): technical docs hub.
|
|
232
|
+
- [Architecture](./docs/architecture.md): runtime and subsystem overview.
|
|
233
|
+
- [Inbound Handlers](./docs/inbound-handlers.md): Telegram → π preprocessing.
|
|
234
|
+
- [Outbound Handlers](./docs/outbound-handlers.md): final text, voice, and artifact pipelines.
|
|
235
|
+
- [Command Templates](./docs/command-templates.md): portable command-template contract.
|
|
236
|
+
- [Callback Namespaces](./docs/callback-namespaces.md): callback interop for layered extensions.
|
|
237
|
+
- [External Handlers](./docs/external-handlers.md): shared update interception.
|
|
238
|
+
- [Extension Sections Draft](./docs/extension-sections.md): future Telegram extension sections platform.
|
|
239
|
+
- [Locks](./docs/locks.md): singleton polling ownership.
|
|
242
240
|
|
|
243
241
|
## Notes
|
|
244
242
|
|
|
245
|
-
-
|
|
246
|
-
-
|
|
247
|
-
- Temporary inbound Telegram files are cleaned up on later session starts
|
|
243
|
+
- The extension intentionally keeps rich visual/TUI configuration minimal for now. For advanced setup, ask an agent to read this README and the docs, then update `~/.pi/agent/telegram.json` for your workflow.
|
|
244
|
+
- Replies to Telegram prompts are sent as Telegram replies to the source message when possible; if the source message is unavailable, delivery falls back to a normal message.
|
|
245
|
+
- Temporary inbound Telegram files are cleaned up on later session starts.
|
|
248
246
|
|
|
249
247
|
## License
|
|
250
248
|
|
package/docs/architecture.md
CHANGED
|
@@ -24,7 +24,7 @@ Naming rule: because the repository already scopes this codebase to Telegram, ex
|
|
|
24
24
|
Current runtime areas use these ownership boundaries:
|
|
25
25
|
|
|
26
26
|
- `index.ts`: single composition root for live π/Telegram ports, session state, API-bound transport adapters, and status updates.
|
|
27
|
-
- `api`: Bot API transport shapes/helpers, retries, file download, temp-dir lifecycle, inbound limits, chat actions, lazy bot-token clients,
|
|
27
|
+
- `api`: Bot API transport shapes/helpers, retries, file download, temp-dir lifecycle, inbound limits, chat actions, lazy bot-token clients, runtime error recording, and the `TELEGRAM_API_BASE` constant for the Bot API endpoint.
|
|
28
28
|
- `config` / `setup`: persisted bot/session pairing state, authorization, first-user pairing, token prompting, env fallback, validation, and config persistence.
|
|
29
29
|
- `locks` / `polling`: singleton `locks.json` ownership, takeover/restart semantics, long-poll controller state, update offset persistence, and poll-loop runtime wiring.
|
|
30
30
|
- `updates` / `routing`: update classification/execution planning, paired authorization, reactions, edits, callbacks, and inbound route composition.
|
package/lib/api.ts
CHANGED
|
@@ -12,6 +12,8 @@ import { join, resolve } from "node:path";
|
|
|
12
12
|
import { Readable, Transform } from "node:stream";
|
|
13
13
|
import { pipeline } from "node:stream/promises";
|
|
14
14
|
|
|
15
|
+
export const TELEGRAM_API_BASE = "https://api.telegram.org";
|
|
16
|
+
|
|
15
17
|
export const TELEGRAM_FILE_MAX_BYTES = 50 * 1024 * 1024;
|
|
16
18
|
|
|
17
19
|
export function getTelegramInboundFileByteLimitFromEnv(
|
|
@@ -513,7 +515,7 @@ export async function callTelegram<TResponse>(
|
|
|
513
515
|
return callTelegramWithRetry(
|
|
514
516
|
method,
|
|
515
517
|
async () =>
|
|
516
|
-
fetch(
|
|
518
|
+
fetch(`${TELEGRAM_API_BASE}/bot${configuredBotToken}/${method}`, {
|
|
517
519
|
method: "POST",
|
|
518
520
|
headers: { "content-type": "application/json" },
|
|
519
521
|
body: JSON.stringify(body),
|
|
@@ -533,7 +535,7 @@ export async function fetchTelegramBotIdentity(
|
|
|
533
535
|
fetchImpl: typeof fetch = fetch,
|
|
534
536
|
): Promise<TelegramBotIdentityResponse> {
|
|
535
537
|
const response = await fetchImpl(
|
|
536
|
-
|
|
538
|
+
`${TELEGRAM_API_BASE}/bot${botToken}/getMe`,
|
|
537
539
|
);
|
|
538
540
|
return response.json() as Promise<TelegramBotIdentityResponse>;
|
|
539
541
|
}
|
|
@@ -558,7 +560,7 @@ export async function callTelegramMultipart<TResponse>(
|
|
|
558
560
|
}
|
|
559
561
|
form.set(fileField, fileBlob, fileName);
|
|
560
562
|
return fetch(
|
|
561
|
-
|
|
563
|
+
`${TELEGRAM_API_BASE}/bot${configuredBotToken}/${method}`,
|
|
562
564
|
{
|
|
563
565
|
method: "POST",
|
|
564
566
|
body: form,
|
|
@@ -591,7 +593,7 @@ export async function downloadTelegramFile(
|
|
|
591
593
|
`${randomUUID()}-${sanitizeFileName(suggestedName)}`,
|
|
592
594
|
);
|
|
593
595
|
const response = await fetch(
|
|
594
|
-
|
|
596
|
+
`${TELEGRAM_API_BASE}/file/bot${configuredBotToken}/${file.file_path}`,
|
|
595
597
|
{ signal: options?.signal },
|
|
596
598
|
);
|
|
597
599
|
if (!response.ok) {
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@llblab/pi-telegram",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.6",
|
|
4
4
|
"private": false,
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "Telegram Runtime Adapter for π",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"pi-package",
|