@llblab/pi-telegram 0.9.4 → 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 +5 -2
- package/BACKLOG.md +10 -1
- package/CHANGELOG.md +18 -0
- package/README.md +114 -116
- package/docs/README.md +1 -0
- package/docs/architecture.md +24 -27
- package/docs/callback-namespaces.md +13 -1
- package/docs/extension-sections.md +293 -0
- package/docs/external-handlers.md +33 -75
- package/docs/inbound-handlers.md +6 -6
- package/docs/outbound-handlers.md +12 -12
- package/index.ts +1 -0
- package/lib/api.ts +6 -4
- package/lib/menu-settings.ts +0 -1
- package/lib/preview.ts +37 -8
- package/lib/queue.ts +18 -10
- package/package.json +2 -2
package/AGENTS.md
CHANGED
|
@@ -7,10 +7,11 @@
|
|
|
7
7
|
- `Boundary Clarity`: Separate Telegram transport concerns, π integration concerns, rendering behavior, and release/documentation state
|
|
8
8
|
- `Progressive Enhancement + Graceful Degradation`: Prefer behavior that upgrades automatically when richer runtime context exists, but always preserves a useful fallback path when it does not
|
|
9
9
|
- `Runtime Safety`: Prefer queue and rendering behavior that fails predictably over clever behavior that can desynchronize the Telegram bridge from π session state
|
|
10
|
+
- `Pi-Native Extensibility`: `pi-telegram` should inherit π's own extension philosophy. It is not only a Telegram adapter; it should become a small, convenient, composable Telegram shell for π extensions, where new capabilities plug into stable contracts instead of forking polling, transport, or menu ownership.
|
|
10
11
|
|
|
11
12
|
## 1. Concept
|
|
12
13
|
|
|
13
|
-
`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.
|
|
14
15
|
|
|
15
16
|
## 2. Identity & Naming Contract
|
|
16
17
|
|
|
@@ -27,7 +28,7 @@
|
|
|
27
28
|
- `/tests/*.test.ts`: Domain-mirrored regression suites that follow the same flat naming as `/lib`
|
|
28
29
|
- `/docs/README.md`: Documentation index for technical project docs
|
|
29
30
|
- `/docs/architecture.md`: Runtime and subsystem overview for the bridge
|
|
30
|
-
- `/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.
|
|
31
32
|
- `/AGENTS.md`: Durable engineering and runtime conventions
|
|
32
33
|
- `/BACKLOG.md`: Canonical open work
|
|
33
34
|
- `/CHANGELOG.md`: Completed delivery history
|
|
@@ -121,6 +122,8 @@ The canonical detailed ownership map lives in [`docs/architecture.md`](./docs/ar
|
|
|
121
122
|
- When Telegram-visible behavior changes, sync `README.md` and the relevant `/docs` entry in the same pass
|
|
122
123
|
- When durable runtime constraints or repeat bug patterns emerge, record them here instead of burying them in changelog prose
|
|
123
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.
|
|
124
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
|
|
125
128
|
|
|
126
129
|
## 8. Integration Protocols
|
package/BACKLOG.md
CHANGED
|
@@ -2,4 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## Open Work
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
- Implement Telegram Extension Sections Platform for the 0.10.0 line.
|
|
6
|
+
- Exit: Runtime registry, main-menu integration, `section:` callback routing, safe section context ports, diagnostics, docs, and at least one small demo/fixture prove ordinary pi extensions can add Telegram menu sections without owning a second poller.
|
|
7
|
+
- Explore always-available outbound Telegram tools for queued artifacts and controls.
|
|
8
|
+
- Priority: Low.
|
|
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
|
+
- 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,23 @@
|
|
|
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
|
+
|
|
11
|
+
## 0.9.5: Telegram Delivery Resilience Hotfix
|
|
12
|
+
|
|
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.
|
|
14
|
+
- `[Final Delivery]` Final Markdown preview replacement now catches Telegram transport failures and returns a normal fallback signal; the agent-end delivery path records final-text delivery failures and continues cleanup, attachment handling, and queue dispatch. Impact: a failed `editMessageText` at `agent_end` no longer breaks the bridge lifecycle or blocks the next queued Telegram turn.
|
|
15
|
+
- `[Diagnostics]` Preview and final delivery failures now flow through the runtime event recorder with compact phase metadata. Impact: `/telegram-status` can show recent transport failures without dumping noisy stack traces into the extension runner.
|
|
16
|
+
- `[Tests]` Added preview and queue regressions for non-fatal Telegram transport failures during preview flush and final delivery.
|
|
17
|
+
- `[Extension Sections Draft]` Added a draft design note for pi-native Telegram extension sections, reserved the future `section:` callback prefix, linked the draft from docs, and recorded the project philosophy that `pi-telegram` should inherit π's extensibility model as a shared Telegram shell for loaded extensions. Impact: the future 0.10.0 extension platform direction is documented without exposing a stable API yet.
|
|
18
|
+
- `[Docs Formatting]` Normalized project Markdown so prose paragraphs stay as single logical lines and Markdown tables remain narrow instead of using artificial hard wraps. Impact: editors and viewers can handle visual wrapping naturally while fixed-width structures stay readable.
|
|
19
|
+
- `[Settings Copy]` Tightened the proactive-push settings text by removing redundant persistence/default wording.
|
|
20
|
+
|
|
3
21
|
## 0.9.4: Temp Dir And Command Template Hotfix
|
|
4
22
|
|
|
5
23
|
- `[Telegram Temp Dir]` Default Telegram API temp files now respect `PI_CODING_AGENT_DIR`, falling back to `~/.pi/agent` when the env var is unset. Impact: sandboxed or relocated agent dirs no longer force Telegram downloads through the default home-directory path.
|
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/README.md
CHANGED
|
@@ -11,3 +11,4 @@ Living index of project documentation in `/docs`.
|
|
|
11
11
|
- [locks.md](./locks.md) — Shared `locks.json` standard for singleton extension ownership
|
|
12
12
|
- [callback-namespaces.md](./callback-namespaces.md) — Shared Telegram `callback_data` namespace standard for layered extensions
|
|
13
13
|
- [external-handlers.md](./external-handlers.md) — Runtime interceptor registry that lets layered extensions observe and consume Telegram updates without owning their own polling connection
|
|
14
|
+
- [extension-sections.md](./extension-sections.md) — Draft Telegram Extension Sections Standard for external menu sections and structured Telegram UI extension points
|
package/docs/architecture.md
CHANGED
|
@@ -23,29 +23,28 @@ Naming rule: because the repository already scopes this codebase to Telegram, ex
|
|
|
23
23
|
|
|
24
24
|
Current runtime areas use these ownership boundaries:
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
| `command-templates` | Portable shell-free command-template standard helpers, composition expansion, placeholder substitution, and executable resolution |
|
|
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, runtime error recording, and the `TELEGRAM_API_BASE` constant for the Bot API endpoint.
|
|
28
|
+
- `config` / `setup`: persisted bot/session pairing state, authorization, first-user pairing, token prompting, env fallback, validation, and config persistence.
|
|
29
|
+
- `locks` / `polling`: singleton `locks.json` ownership, takeover/restart semantics, long-poll controller state, update offset persistence, and poll-loop runtime wiring.
|
|
30
|
+
- `updates` / `routing`: update classification/execution planning, paired authorization, reactions, edits, callbacks, and inbound route composition.
|
|
31
|
+
- `media` / `text-groups` / `turns` / `inbound-handlers`: text/media extraction, media-group debounce, long-text split coalescing, inbound downloads, inbound text/media handler execution, turn building/editing, image reads, and legacy `attachmentHandlers` compatibility.
|
|
32
|
+
- `queue`: queue item contracts, lane admission/order, stores, mutations, dispatch readiness/runtime, prompt/control enqueueing, and session/agent/tool lifecycle sequencing.
|
|
33
|
+
- `runtime`: session-local coordination primitives: counters, lifecycle flags, setup guard, abort handler, typing-loop timers, prompt-dispatch flags, and agent-end reset binding.
|
|
34
|
+
- `model` / `menu-model` / `menu-thinking` / `menu-status` / `menu` / `menu-queue` / `menu-settings` / `commands`: model identity/thinking levels, scoped model resolution, in-flight switching, model/thinking/status/queue/settings menu UI, inline application callback composition, slash commands, and bot command registration.
|
|
35
|
+
- Future `extension-sections`: structured external Telegram menu sections registered by ordinary pi extensions; owns section registry, compact section callback tokens, section render/callback dispatch, safe section runtime ports, and diagnostics.
|
|
36
|
+
- `keyboard`: shared Telegram inline-keyboard reply-markup structure; feature domains own callback semantics and button construction.
|
|
37
|
+
- `preview` / `replies` / `rendering`: preview lifecycle/transports, final reply delivery and reply parameters, Telegram HTML Markdown rendering, chunking, and stable-preview snapshots.
|
|
38
|
+
- `outbound-handlers`: outbound text transformation, assistant-authored outbound comments, generated reply artifacts, inline-keyboard callbacks, and post-`agent_end` outbound action delivery.
|
|
39
|
+
- `outbound-attachments`: `telegram_attach` registration, outbound attachment queueing, stat/limit checks, and photo/document delivery classification.
|
|
40
|
+
- `status`: status-bar/status-message rendering, queue-lane status views, redacted runtime event ring, and grouped π diagnostics.
|
|
41
|
+
- `lifecycle` / `prompts` / `prompt-templates` / `pi`: π hook registration, Telegram-specific before-agent prompt injection, π prompt-template discovery/expansion, and centralized direct pi SDK imports/context adapters.
|
|
42
|
+
- `command-templates`: portable shell-free command-template standard helpers, composition expansion, placeholder substitution, and executable resolution.
|
|
44
43
|
|
|
45
44
|
Boundary invariants:
|
|
46
45
|
|
|
47
46
|
- Constants and state types live with their owning domains; do not reintroduce shared buckets such as `lib/constants.ts` or `lib/types.ts`
|
|
48
|
-
- Shared Telegram inline-keyboard structure belongs to `keyboard`; application-control labels, callback data, and callback behavior stay in `menu`/`menu-model`/`menu-thinking`/`menu-status`/`menu-queue`; core queue mechanics stay in `queue`
|
|
47
|
+
- Shared Telegram inline-keyboard structure belongs to `keyboard`; application-control labels, callback data, and callback behavior stay in `menu`/`menu-model`/`menu-thinking`/`menu-status`/`menu-queue`; future external section labels, callbacks, and dispatch stay in `extension-sections`; core queue mechanics stay in `queue`
|
|
49
48
|
- Domain helpers use narrow structural projections when that avoids importing concrete wire DTOs or broader runtime objects unnecessarily
|
|
50
49
|
- Preview appearance stays in `rendering`; preview transport/lifecycle stays in `preview`
|
|
51
50
|
- Direct `node:*` file-operation imports stay in owning domains, not in `index.ts`
|
|
@@ -95,13 +94,11 @@ Queued items now use two explicit dimensions:
|
|
|
95
94
|
|
|
96
95
|
Admission contract:
|
|
97
96
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
| Priority prompt queue | A waiting prompt promoted by `👍`, `⚡️`, `❤️`, `🕊`, or `🔥` | `kind: prompt`, `queueLane: priority` | 1 |
|
|
104
|
-
| Default prompt queue | Normal Telegram text/media turns | `kind: prompt`, `queueLane: default` | 2 |
|
|
97
|
+
- Immediate execution: `/compact`, `/queue`, `/stop`, `/help`, and `/start` do not enter the Telegram queue. `/help` opens the same menu as `/start`; `/stop` also clears queued items. Dispatch rank: N/A.
|
|
98
|
+
- Queued prompt command: `/continue` enqueues a priority Telegram-owned `continue` prompt. Prompt-template commands such as `/template_name args` expand the matching π template before entering the normal prompt queue. Dispatch rank: priority for `/continue`, otherwise default.
|
|
99
|
+
- Control queue: model-switch continuation turns and future deferred controls use `queueLane: control`, accept control items and continuation prompts, and dispatch at rank `0`.
|
|
100
|
+
- Priority prompt queue: a waiting prompt promoted by `👍`, `⚡️`, `❤️`, `🕊`, or `🔥` uses `kind: prompt`, `queueLane: priority`, and dispatches at rank `1`.
|
|
101
|
+
- Default prompt queue: normal Telegram text/media turns use `kind: prompt`, `queueLane: default`, and dispatch at rank `2`.
|
|
105
102
|
|
|
106
103
|
The command action itself carries its execution mode, and the queue domain exposes lane contracts for admission mode, dispatch rank, and allowed item kinds. Queue append and planning paths validate lane admission so a malformed control/default or other invalid lane pairing fails predictably instead of silently changing priority. This lets synthetic control actions and Telegram prompts share one stable ordering model while still rendering distinctly in status output. In the π status bar, busy labels distinguish `active`, `dispatching`, `queued`, `tool running`, `model`, and `compacting`; priority prompts and priority control items are marked with `⚡`. If a queue mutation removes the last waiting item while Telegram-owned work still has running tools, the status remains yellow `active` instead of degrading to green `connected`.
|
|
107
104
|
|
|
@@ -160,7 +157,7 @@ Telegram prompt responses use explicit delivery context to attach outbound text,
|
|
|
160
157
|
|
|
161
158
|
Outbound files are sent only after the active Telegram turn completes, must be staged through the `telegram_attach` tool, are staged atomically per tool call, are checked against a default 50 MiB limit configurable through `PI_TELEGRAM_OUTBOUND_ATTACHMENT_MAX_BYTES` or `TELEGRAM_MAX_ATTACHMENT_SIZE_BYTES`, and use file-backed multipart blobs so large sends do not require preloading whole files into memory.
|
|
162
159
|
|
|
163
|
-
Assistant-authored outbound actions use final-message markup instead of agent tool calls. Preview updates strip closed top-level HTML comments and currently open/partial top-level comment starts before rendering, so users do not see transient metadata even when streaming flushes happen after only `<`, `<!`, or `<!--`. On `agent_end`, the bridge removes top-level comments from the Markdown text reply, but treats column-zero top-level `<!-- telegram_voice ... -->` and `<!-- telegram_button ... -->` blocks specially before delivery; comments inside fenced code, quotes, lists, or indented examples stay literal, including fenced blocks with Markdown-valid indented closing fences. Voice maps to the first matching `outboundHandlers[]` entry with `type: "voice"`, synthesizes body text, `text="..."`, or colon shorthand through command-template execution, and uploads the generated OGG/Opus file via Telegram `sendVoice`; when no outbound voice handler is configured, it silently skips voice delivery. The `template: [...]` form can express TTS plus MP3-to-OGG conversion using configured templates and bridge-provided `{text}`, `{mp3}`, and `{ogg}` placeholders. Top-level `args` and `defaults` apply to all composed steps unless a step defines private values, the default command timeout applies automatically, and each step receives the previous step's stdout on stdin by default, without hard-coded filesystem defaults. Button blocks are built in: each `telegram_button` block becomes one inline-keyboard button on the final text, and callback clicks enqueue the configured prompt text as a normal Telegram prompt turn; the `telegram_button: Label` shorthand uses the same text for label and prompt, `prompt="..."` supports explicit one-line prompts, and body-form buttons use the body as the prompt. Unknown callback data that does not match pi-telegram-owned prefixes (`tgbtn:`, `menu:`, `model:`, `thinking:`, `status:`, `queue:`) is forwarded to π as `[callback] <data>` after built-in handlers decline it, giving layered extensions a simple namespaced button channel without separate polling; layered callback payloads should follow the [Callback Namespace Standard](./callback-namespaces.md). When proactive push is enabled, successful local non-Telegram final replies are sent to the paired chat. Local prompt text is not sent because the bot does not own or mirror terminal user messages. This keeps terminal-originated results visible in Telegram without changing Telegram-originated turn delivery.
|
|
160
|
+
Assistant-authored outbound actions use final-message markup instead of agent tool calls. Preview updates strip closed top-level HTML comments and currently open/partial top-level comment starts before rendering, so users do not see transient metadata even when streaming flushes happen after only `<`, `<!`, or `<!--`. On `agent_end`, the bridge removes top-level comments from the Markdown text reply, but treats column-zero top-level `<!-- telegram_voice ... -->` and `<!-- telegram_button ... -->` blocks specially before delivery; comments inside fenced code, quotes, lists, or indented examples stay literal, including fenced blocks with Markdown-valid indented closing fences. Voice maps to the first matching `outboundHandlers[]` entry with `type: "voice"`, synthesizes body text, `text="..."`, or colon shorthand through command-template execution, and uploads the generated OGG/Opus file via Telegram `sendVoice`; when no outbound voice handler is configured, it silently skips voice delivery. The `template: [...]` form can express TTS plus MP3-to-OGG conversion using configured templates and bridge-provided `{text}`, `{mp3}`, and `{ogg}` placeholders. Top-level `args` and `defaults` apply to all composed steps unless a step defines private values, the default command timeout applies automatically, and each step receives the previous step's stdout on stdin by default, without hard-coded filesystem defaults. Button blocks are built in: each `telegram_button` block becomes one inline-keyboard button on the final text, and callback clicks enqueue the configured prompt text as a normal Telegram prompt turn; the `telegram_button: Label` shorthand uses the same text for label and prompt, `prompt="..."` supports explicit one-line prompts, and body-form buttons use the body as the prompt. Unknown callback data that does not match pi-telegram-owned prefixes (`tgbtn:`, `menu:`, `model:`, `thinking:`, `status:`, `queue:`, future `section:`) is forwarded to π as `[callback] <data>` after built-in handlers decline it, giving layered extensions a simple namespaced button channel without separate polling; layered callback payloads should follow the [Callback Namespace Standard](./callback-namespaces.md). Future structured menu integrations should use the [Telegram Extension Sections Standard](./extension-sections.md) instead of hand-rolled fallback callbacks. When proactive push is enabled, successful local non-Telegram final replies are sent to the paired chat. Local prompt text is not sent because the bot does not own or mirror terminal user messages. This keeps terminal-originated results visible in Telegram without changing Telegram-originated turn delivery.
|
|
164
161
|
|
|
165
162
|
This keeps technical Markdown, code, tables, formulas, and numbered lists in the text channel when appropriate while allowing TTS-friendly voice messages and tappable continuations without invoking `telegram_attach` or extra transport tools. Telegram prompt guidance targets about 37 visible cells for tables, dense list items, and compact text blocks because emoji and other wide glyphs make raw character counts misleading on mobile screens.
|
|
166
163
|
|
|
@@ -20,7 +20,7 @@ myext:page:2
|
|
|
20
20
|
|
|
21
21
|
- Use a stable extension-owned namespace, preferably the package or extension name without scope punctuation.
|
|
22
22
|
- Keep the namespace lowercase ASCII: `a-z`, `0-9`, `_`, `-`.
|
|
23
|
-
- Do not use `pi-telegram` owned prefixes: `tgbtn:`, `menu:`, `model:`, `thinking:`, `status:`, `queue:`. Current app navigation uses `menu:`; `status:` remains reserved for legacy/owned status callbacks but is not emitted by current UI.
|
|
23
|
+
- Do not use `pi-telegram` owned prefixes: `tgbtn:`, `menu:`, `model:`, `thinking:`, `status:`, `queue:`, `section:`. Current app navigation uses `menu:`; `status:` remains reserved for legacy/owned status callbacks but is not emitted by current UI. `section:` is reserved for the structured extension-section router documented in [Extension Sections](./extension-sections.md).
|
|
24
24
|
- Keep the full `callback_data` within Telegram's 64-byte limit.
|
|
25
25
|
- Put only opaque ids or small enum values in payloads; do not store secrets, full prompts, or large state.
|
|
26
26
|
- Treat callbacks as untrusted input. Validate namespace, action, and payload before executing side effects.
|
|
@@ -34,3 +34,15 @@ If `pi-telegram` receives callback data that is not owned by its built-in prefix
|
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
Layered extensions may intercept that message and handle their own namespace. If no extension handles it, the assistant may see the fallback message and should tell the user the callback was not handled and the environment may be misconfigured.
|
|
37
|
+
|
|
38
|
+
## Extension sections
|
|
39
|
+
|
|
40
|
+
[Telegram Extension Sections](./extension-sections.md) are a higher-level UI contract over this namespace rule. A section owns a canonical extension identity such as `@llblab/pi-telegram-explorer`, but its Telegram `callback_data` should use the `pi-telegram` owned `section:` prefix plus a compact token, because Telegram limits callback payloads to 64 bytes.
|
|
41
|
+
|
|
42
|
+
Conceptual form:
|
|
43
|
+
|
|
44
|
+
```text
|
|
45
|
+
section:<token>:<action>[:<payload>]
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The token maps back to the full section identity inside the section registry. Section authors should not hand-roll `section:` callbacks outside the section context helpers, and ordinary layered extensions should continue using their own namespace plus external handlers or the `[callback]` fallback.
|