@llblab/pi-telegram 0.6.3 → 0.7.1
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 +153 -0
- package/BACKLOG.md +5 -0
- package/CHANGELOG.md +148 -0
- package/README.md +40 -39
- package/docs/README.md +1 -0
- package/docs/architecture.md +36 -27
- package/docs/attachment-handlers.md +4 -6
- package/docs/callback-namespaces.md +36 -0
- package/docs/command-templates.md +53 -9
- package/docs/locks.md +4 -0
- package/docs/outbound-handlers.md +6 -5
- package/index.ts +60 -7
- package/lib/api.ts +1 -0
- package/lib/attachment-handlers.ts +21 -10
- package/lib/attachments.ts +1 -0
- package/lib/command-templates.ts +37 -3
- package/lib/commands.ts +363 -88
- package/lib/config.ts +6 -2
- package/lib/keyboard.ts +14 -0
- package/lib/lifecycle.ts +26 -0
- package/lib/locks.ts +3 -2
- package/lib/media.ts +1 -0
- package/lib/menu-model.ts +881 -0
- package/lib/menu-queue.ts +610 -0
- package/lib/menu-status.ts +226 -0
- package/lib/menu-thinking.ts +171 -0
- package/lib/menu.ts +143 -1019
- package/lib/model.ts +1 -0
- package/lib/outbound-handlers.ts +28 -19
- package/lib/pi.ts +8 -0
- package/lib/polling.ts +1 -0
- package/lib/preview.ts +97 -50
- package/lib/prompt-templates.ts +150 -0
- package/lib/prompts.ts +2 -0
- package/lib/queue.ts +60 -15
- package/lib/rendering.ts +1 -0
- package/lib/replies.ts +90 -2
- package/lib/routing.ts +106 -14
- package/lib/runtime.ts +2 -0
- package/lib/setup.ts +1 -0
- package/lib/status.ts +18 -6
- package/lib/turns.ts +1 -0
- package/lib/updates.ts +55 -6
- package/package.json +5 -2
package/AGENTS.md
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# Project Context
|
|
2
|
+
|
|
3
|
+
## 0. Meta-Protocol Principles
|
|
4
|
+
|
|
5
|
+
- `Constraint-Driven Evolution`: Add structure when the bridge gains real operator or runtime constraints
|
|
6
|
+
- `Single Source of Truth`: Keep durable rules in `AGENTS.md`, open work in `BACKLOG.md`, completed delivery in `CHANGELOG.md`, and deeper technical detail in `/docs`
|
|
7
|
+
- `Boundary Clarity`: Separate Telegram transport concerns, π integration concerns, rendering behavior, and release/documentation state
|
|
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
|
+
- `Runtime Safety`: Prefer queue and rendering behavior that fails predictably over clever behavior that can desynchronize the Telegram bridge from π session state
|
|
10
|
+
|
|
11
|
+
## 1. Concept
|
|
12
|
+
|
|
13
|
+
`pi-telegram` is a π extension that turns a Telegram DM into a session-local frontend for π, including text/file forwarding, streaming previews, queued follow-ups, model controls, and outbound attachment delivery.
|
|
14
|
+
|
|
15
|
+
## 2. Identity & Naming Contract
|
|
16
|
+
|
|
17
|
+
- `Telegram turn`: One unit of Telegram input processed by π; this may represent one message or a coalesced media group
|
|
18
|
+
- `Queued Telegram turn`: A Telegram turn accepted by the bridge but not yet active in π
|
|
19
|
+
- `Active Telegram turn`: The Telegram turn currently bound to the running π agent loop
|
|
20
|
+
- `Preview`: The transient streamed response shown through Telegram drafts or editable messages before the final reply lands
|
|
21
|
+
- `Scoped models`: The subset of models exposed to Telegram model selection when π settings or CLI flags limit the available list
|
|
22
|
+
|
|
23
|
+
## 3. Project Topology
|
|
24
|
+
|
|
25
|
+
- `/index.ts`: Main extension entrypoint and runtime composition layer for the bridge
|
|
26
|
+
- `/lib/*.ts`: Flat domain modules for reusable runtime logic. Favor domain files such as queueing/runtime, replies, polling, updates, attachments, commands, lifecycle hooks, prompts, prompt-templates, pi SDK adapter, Telegram API, config, turns, media, setup, rendering, app menu, menu-model, menu-thinking, menu-queue, status/model-resolution support, and other cohesive bridge subsystems; use `shared` only when a type or constant truly spans multiple domains
|
|
27
|
+
- `/tests/*.test.ts`: Domain-mirrored regression suites that follow the same flat naming as `/lib`
|
|
28
|
+
- `/docs/README.md`: Documentation index for technical project docs
|
|
29
|
+
- `/docs/architecture.md`: Runtime and subsystem overview for the bridge
|
|
30
|
+
- `/README.md`: User-facing project entry point, install guide, and fork summary
|
|
31
|
+
- `/AGENTS.md`: Durable engineering and runtime conventions
|
|
32
|
+
- `/BACKLOG.md`: Canonical open work
|
|
33
|
+
- `/CHANGELOG.md`: Completed delivery history
|
|
34
|
+
|
|
35
|
+
## 4. Core Entities
|
|
36
|
+
|
|
37
|
+
- `TelegramConfig`: Persisted bot/session pairing state
|
|
38
|
+
- `PendingTelegramTurn`: Queue-domain prompt turn state for queued and active Telegram-originated work
|
|
39
|
+
- `TelegramPreviewRuntimeState`: Preview-domain streaming state for drafts or editable Telegram messages
|
|
40
|
+
- `TelegramModelMenuState`: Shared inline application-menu state for status, model, thinking, and queue menu messages
|
|
41
|
+
- `QueuedAttachment`: Outbound files staged for delivery through `telegram_attach`
|
|
42
|
+
|
|
43
|
+
## 5. Architectural Decisions
|
|
44
|
+
|
|
45
|
+
## 5.1 Flat Domain DAG Shape
|
|
46
|
+
|
|
47
|
+
- The project follows a `Flat Domain DAG`: cohesive bridge domains live as flat `/lib/*.ts` modules, and local imports must form a directed acyclic graph
|
|
48
|
+
- `index.ts` stays the single extension entrypoint and composition root for live π/Telegram ports, SDK adapters, and session state
|
|
49
|
+
- Reusable runtime logic should be split into flat domain files under `/lib`
|
|
50
|
+
- Opening source-module comments must include `Zones:` tags such as `telegram`, `pi agent`, `tui`, or `shared utils`; these tags replace folder nesting as the quick responsibility map for flat Domain DAG files
|
|
51
|
+
- Prefer domain-oriented grouping over atomizing every helper into its own file
|
|
52
|
+
- Use `shared` sparingly and only for types or constants that genuinely span multiple bridge domains
|
|
53
|
+
|
|
54
|
+
## 5.2 Session And Queue Semantics
|
|
55
|
+
|
|
56
|
+
- The bridge is session-local, paired to one allowed Telegram user, and owns a local queue aligned with π lifecycle hooks
|
|
57
|
+
- Queue admission is explicit and validated: immediate commands, control lane, priority lane, and default lane must preserve allowed kind/lane pairings
|
|
58
|
+
- Dispatch is gated by active turns, pending dispatch, unsettled control work, compaction, `ctx.isIdle()`, and π pending messages; dispatched prompts remain queued until `agent_start` consumes them
|
|
59
|
+
- `/stop`, `/abort`, `/next`, and `/continue` have distinct contracts: reset queue and abort; abort while preserving queue; force next queued turn; enqueue a priority `continue` prompt
|
|
60
|
+
- `/start`, `/help`, and `/status` open the unified command-help/status-row/control menu; `/model`, `/thinking`, and `/queue` jump to sections directly; visible bot commands are `/start`, `/compact`, `/next`, `/continue`, `/abort`, `/stop`
|
|
61
|
+
- Command/menu emoji are fixed UI adornments owned by the `commands` map; do not add a persisted emoji toggle or Settings menu until there is a real setting to own
|
|
62
|
+
- Telegram `reply_to_message` context is prompt-only and must not affect slash-command parsing
|
|
63
|
+
- Long-lived timers, pollers, watchers, and deferred queue dispatch must be session-bound and avoid stale live π contexts after session replacement
|
|
64
|
+
- In-flight `/model` switching is limited to Telegram-owned active turns; if a tool call is active, abort is delayed until the tool finishes
|
|
65
|
+
|
|
66
|
+
## 5.3 Telegram Delivery Semantics
|
|
67
|
+
|
|
68
|
+
- Telegram replies render through Telegram HTML, not raw Markdown
|
|
69
|
+
- Real code blocks must stay literal and escaped
|
|
70
|
+
- `telegram_attach` is the canonical outbound file-delivery path for Telegram-originated requests
|
|
71
|
+
- Telegram delivery strips top-level HTML comments from preview/final text; column-zero top-level `<!-- telegram_voice ... -->` and `<!-- telegram_button ... -->` blocks are special outbound comments handled after `agent_end` without requiring agent-side transport tool calls, while comments inside code, quotes, lists, or indented examples stay literal
|
|
72
|
+
- `telegram_voice` and `telegram_button` are not π tools; keep prompts/docs explicit that agents should author markup while the extension owns command-template voice pipelines, button routing, and Telegram delivery
|
|
73
|
+
- `telegram_voice` text is arbitrary TTS-target text: use body form for multiline text, `<!-- telegram_voice text="Short summary" -->` for explicit one-line text, or `<!-- telegram_voice: Short summary -->` for one-line text with no attributes
|
|
74
|
+
- `telegram_button` has three canonical forms: `<!-- telegram_button: OK -->` for label-only buttons, `<!-- telegram_button label=Continue prompt="Continue with the current plan." -->` for one-line prompts, or `<!-- telegram_button label="Show risks"\nList the main risks first.\n-->` for multiline prompts
|
|
75
|
+
|
|
76
|
+
## 6. Engineering Conventions
|
|
77
|
+
|
|
78
|
+
## 6.1 Validation Hotspots
|
|
79
|
+
|
|
80
|
+
- Treat queue handling, compaction interaction, and lifecycle-hook state transitions as regression-prone areas; validate them after changing dispatch logic
|
|
81
|
+
- Route important runtime failures through the recent runtime event recorder so `/telegram-status` remains useful for post-mortem debugging, not just transient status-bar errors
|
|
82
|
+
- Treat Markdown rendering as Telegram-specific output work, not generic Markdown rendering
|
|
83
|
+
- Preserve literal code content in Telegram rendering
|
|
84
|
+
- Avoid HTML chunk splits that break tags
|
|
85
|
+
- Prefer width-efficient monospace table and list formatting for narrow clients, with table padding based on grapheme/display width rather than raw UTF-16 length where possible
|
|
86
|
+
- Flatten nested Markdown quotes into indented single-blockquote output because Telegram does not render nested blockquotes reliably
|
|
87
|
+
|
|
88
|
+
## 6.2 File And Naming Style
|
|
89
|
+
|
|
90
|
+
- Keep comments and user-facing docs in English unless the surrounding file already follows another convention
|
|
91
|
+
- Each project `.ts` file should start with a short multi-line responsibility header comment that explains the file boundary to future maintainers; source-module headers must include `Zones:` tags for cross-cutting responsibility areas
|
|
92
|
+
- Name extracted `/lib` modules and mirrored `/tests` suites by bare domain when the repository already supplies the Telegram scope; prefer `api.ts`, `queue.ts`, `updates.ts`, and `queue.test.ts` over redundant `telegram-*` filename prefixes
|
|
93
|
+
- Keep test helpers with the mirrored domain suite by default because test files mirror module-domain boundaries; introduce shared `tests/fixtures` only when multiple domain suites truly reuse the same setup
|
|
94
|
+
- Prefer targeted edits, keeping `index.ts` as the orchestration layer and moving reusable logic into flat `/lib` domain modules when a subsystem becomes large enough to earn extraction
|
|
95
|
+
- Keep composition wiring DRY with small local adapters or owning-domain contracts when repetition appears, but do not hide live mutable session state behind broad facades just to reduce repeated closures
|
|
96
|
+
- Keep interface contracts consistent for the same runtime entity: prefer the owning domain's exported contract when multiple modules mean the same entity, and use local structural `*Like`/view contracts only for deliberate narrow projections that avoid real coupling without duplicating source-of-truth shapes
|
|
97
|
+
|
|
98
|
+
## 6.3 Current Domain Ownership Snapshot
|
|
99
|
+
|
|
100
|
+
The canonical detailed ownership map lives in [`docs/architecture.md`](./docs/architecture.md). Keep this section as a compact agent-facing index, not a second copy of the full map.
|
|
101
|
+
|
|
102
|
+
- Scheduling and lifecycle: `queue`, `runtime`, `lifecycle`, `locks`
|
|
103
|
+
- Telegram transport and inbound flow: `api`, `polling`, `updates`, `routing`, `media`, `turns`, `attachment-handlers`, `config`, `setup`
|
|
104
|
+
- Response surfaces: `preview`, `replies`, `rendering`, `keyboard`, `attachments`, `outbound-handlers`, `status`
|
|
105
|
+
- Controls and application menu UI: `commands`, `menu`, `menu-model`, `menu-thinking`, `menu-status`, `menu-queue`, `model`, `prompts`
|
|
106
|
+
- Pi SDK boundary: `pi` owns direct pi imports and bound extension API ports
|
|
107
|
+
|
|
108
|
+
## 6.4 Entrypoint And Import Boundaries
|
|
109
|
+
|
|
110
|
+
- Keep preview appearance logic in the rendering domain and preview transport/lifecycle logic in the preview domain so richer streaming strategies can evolve without entangling Telegram delivery state with Markdown formatting rules
|
|
111
|
+
- Keep direct `node:*` file-operation dependencies out of `index.ts` when an owning domain exists; the entrypoint should compose ports while domains own local filesystem details such as temp-dir preparation, attachment stats, and turn image reads
|
|
112
|
+
- In `index.ts`, prefer namespace imports for local bridge domains so orchestration reads as domain-scoped calls such as `Queue.*`, `Turns.*`, and `Rendering.*` instead of long flat import lists
|
|
113
|
+
- Keep the local `index.ts` plus `/lib/*.ts` import graph acyclic; `tests/invariants.test.ts` guards this boundary plus shared-bucket bans, empty interface-extension shell regressions, pi SDK centralization, source-only entrypoint Node-runtime/local-adapter/process/direct-pi access avoidance, runtime-domain isolation, structural leaf-domain import isolation, menu/model boundary drift, API/config default coupling, structural update/media coupling to API transport shapes, and attachment coupling to queue/inbound media/API helpers as domains keep evolving
|
|
114
|
+
- Do not reintroduce shared bucket domains such as `lib/constants.ts` or `lib/types.ts`; constants, state interfaces, and concrete transport shapes should stay in their owning domains, and `index.ts` should not grow new shared magic constants
|
|
115
|
+
- Keep remaining `index.ts` code focused on cross-domain adapter wiring that needs live extension state, pi callbacks, Telegram API ports, or status updates; do not extract one-off closures solely to reduce line count
|
|
116
|
+
- Domain-specific queue planning, preview transport/controller behavior, rendering, Telegram API transport, menu state, and command behavior should stay in their owning domains instead of moving to `/lib/runtime.ts` solely to shrink `index.ts`
|
|
117
|
+
- Prefer narrow structural runtime ports in domains that only store or route pi-compatible values; direct pi SDK/model imports should stay centralized in `/lib/pi.ts`, while domains that actively register pi hooks/tools/commands should consume those concrete contracts through the adapter
|
|
118
|
+
|
|
119
|
+
## 7. Operational Conventions
|
|
120
|
+
|
|
121
|
+
- When Telegram-visible behavior changes, sync `README.md` and the relevant `/docs` entry in the same pass
|
|
122
|
+
- When durable runtime constraints or repeat bug patterns emerge, record them here instead of burying them in changelog prose
|
|
123
|
+
- When fork identity changes, keep `README.md`, package metadata, and docs aligned so the published package does not point back at stale upstream coordinates
|
|
124
|
+
- 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
|
+
|
|
126
|
+
## 8. Integration Protocols
|
|
127
|
+
|
|
128
|
+
- Telegram API methods currently used include polling, message editing, draft streaming, callback queries, reactions, file download, and media upload endpoints
|
|
129
|
+
- π integration depends on lifecycle hooks such as `before_agent_start`, `agent_start`, `message_start`, `message_update`, and `agent_end`
|
|
130
|
+
- `ctx.ui.input()` provides placeholder text rather than an editable prefilled value; when a real default must appear already filled in, prefer `ctx.ui.editor()`
|
|
131
|
+
- For `/telegram-setup`, prefer the locally saved bot token over environment variables on repeat setup runs; env vars are the bootstrap path when no local token exists, and persisted `telegram.json` writes must remain atomic plus private because status/setup/polling paths may read it concurrently
|
|
132
|
+
- Command help plus prompt-template commands and status/model/thinking/queue controls are driven through `/start`'s Telegram inline application menu and callback queries; the Queue button shows the queued-item count, model-menu scope/pagination controls stay at the top under Main menu, the model pagination indicator opens a compact page picker, and thinking-menu text stays a compact heading because the current level is marked by button state; `/status`, `/model`, `/thinking`, and `/queue` are hidden compatibility shortcuts
|
|
133
|
+
- Shared inline-keyboard structure belongs to `keyboard`; application-control button labels, callback data, and callback behavior stay in `menu`/`menu-model`/`menu-thinking`/`menu-status`/`menu-queue` while core queue mechanics stay in `queue`
|
|
134
|
+
- Inbound files may become π image inputs or configured attachment-handler text before queueing; outbound files must flow through `telegram_attach`
|
|
135
|
+
- Inbound attachment handlers and command-backed outbound handlers use command templates as the standard integration contract; built-in outbound buttons use inline keyboards plus callback routing because no external command execution is needed
|
|
136
|
+
- Telegram prompt-template commands are discovered from π slash commands with `source: "prompt"`; π template names are mapped to Bot API-compatible aliases (`fix-tests` → `/fix_tests`), aliases that conflict with built-in bridge commands or hidden shortcuts are not displayed, prompt-template aliases stay out of the Telegram bot command menu, and the bridge expands template files before queueing because extension-originated `sendUserMessage()` bypasses π's interactive template expansion
|
|
137
|
+
- Unknown callback data not owned by pi-telegram prefixes (`tgbtn:`, `menu:`, `model:`, `thinking:`, `status:`, `queue:`) may be forwarded as `[callback] <data>` after built-in handlers decline it; external extensions should follow `docs/callback-namespaces.md` and must not poll the same bot independently
|
|
138
|
+
- Command templates stay compact and shell-free: no `command` field, no shell execution, inline defaults are allowed as `{name=default}`, `template` may be a string or an ordered composition array, only `args`/`defaults` inherit into leaves, top-level `timeout` wraps composed sequences, stdout pipes to the next step's stdin by default, and multi-step work should use `template: [...]` rather than provider-specific fields; `pipe` is only a legacy local alias
|
|
139
|
+
- Command-template documentation examples should use portable executable placeholders such as `/path/to/stt` and `/path/to/tts`, not host-local skill paths or machine-specific install locations
|
|
140
|
+
|
|
141
|
+
## 9. Pre-Task Preparation Protocol
|
|
142
|
+
|
|
143
|
+
- Read `README.md` for current user-facing behavior and fork positioning
|
|
144
|
+
- Read `BACKLOG.md` before changing runtime behavior or documentation so open work stays truthful
|
|
145
|
+
- Read `/docs/architecture.md` before restructuring queue, preview, rendering, or command-handling logic
|
|
146
|
+
- Inspect the relevant `index.ts` section before editing because most bridge behavior is stateful and cross-linked
|
|
147
|
+
|
|
148
|
+
## 10. Task Completion Protocol
|
|
149
|
+
|
|
150
|
+
- Run the smallest meaningful validation for the touched area; `npm test` is the default regression suite once rendering or queue logic changes
|
|
151
|
+
- For rendering changes, ensure regressions still cover nested lists, code blocks, underscore-heavy text, and long-message chunking
|
|
152
|
+
- For queue/dispatch changes, validate abort, compaction, pending-dispatch, and π pending-message guard behavior
|
|
153
|
+
- Sync `README.md`, `CHANGELOG.md`, `BACKLOG.md`, and `/docs` whenever user-visible behavior or real open-work state changes
|
package/BACKLOG.md
ADDED
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.7.1: Layered Callback Interop
|
|
4
|
+
|
|
5
|
+
- `[Callback Interop]` Unknown Telegram inline-button callback data that does not belong to pi-telegram-owned prefixes (`tgbtn:`, `menu:`, `model:`, `thinking:`, `status:`, `queue:`) is now forwarded to π as `[callback] <data>` after assistant-button, queue-menu, and app-menu handlers decline it. `docs/callback-namespaces.md` defines the shared callback namespace standard for layered extensions. Impact: layered π extensions can namespace and handle their own Telegram inline buttons without polling the same bot or forking pi-telegram.
|
|
6
|
+
- `[Prompt Templates]` Prompt-template aliases stay visible only inside `/start` and are no longer registered in the Telegram bot command menu. Impact: reusable π workflows remain discoverable without making Telegram's global command menu noisy.
|
|
7
|
+
- `[Package]` Bumped package metadata to `0.7.1` through npm and kept the lockfile in sync.
|
|
8
|
+
|
|
9
|
+
## 0.7.0: Unified App Menu & Command Template Hardening
|
|
10
|
+
|
|
11
|
+
- `[Commands]` Visible Telegram bot command menu now exposes `/start`, `/compact`, `/next`, `/continue`, `/abort`, and `/stop`; `/help`, `/status`, `/model`, `/thinking`, and `/queue` remain hidden compatibility shortcuts. `/start`, `/help`, and `/status` open one unified app menu containing command help, status rows, and inline controls. Command emoji are centralized as fixed adornments in the commands domain and reused by matching menu buttons (`🤖` model, `🧠` thinking); `/next` uses `⏩` and `/continue` uses `▶️`. `/continue` enqueues a priority Telegram-owned `continue` prompt instead of forcing the next queued item or requiring π to be idle. Impact: the visible command surface is cleaner while existing operator muscle memory still works and skills can react to queued `continue` prompts.
|
|
12
|
+
- `[Application Menu]` `/start` opens command help plus status rows and the inline application menu; `/queue` opens the queue section directly, the status menu Queue button shows the current queued-item count, all submenus keep Back/Main menu navigation in the top row, and queued items are listed in dispatch order with numeric labels plus `⚡`/`📎` markers. Queue menu message text uses the same HTML heading style as the other inline menus; empty queue menus render bold message text with only the Main menu navigation button instead of a disabled empty-state button. Item submenus support Back, priority toggle, and Cancel, and stale item clicks refresh the live list. Impact: queued Telegram work is inspectable and mutable from the menu control surface without relying only on reactions.
|
|
13
|
+
- `[Prompt Templates]` `/start` now shows a separate block for π prompt-template commands, and the Telegram bot command menu registers Telegram-safe prompt-template aliases such as `fix-tests` → `/fix_tests` when they do not conflict with built-in bridge commands or hidden shortcuts. Sending `/template_name args` from Telegram expands the matching π prompt-template file before queueing the turn. Impact: reusable π workflows are available from Telegram without duplicating prompt text manually.
|
|
14
|
+
- `[Keyboard]` Shared Telegram inline-keyboard reply-markup structure was extracted to `keyboard`, while `menu` owns application-control button semantics and `outbound-handlers` owns assistant-authored button semantics. Impact: inline UI domains share one Bot API shape without centralizing feature behavior.
|
|
15
|
+
- `[Domain DAG]` Source-module opening comments now include `Zones:` tags for cross-cutting responsibility areas such as Telegram transport, π agent lifecycle, TUI, and shared utilities. Impact: flat files keep folder-like orientation without adding directory nesting.
|
|
16
|
+
- `[Menu Refactor]` Queue-menu UI moved from `menu.ts` into the flat `menu-queue` domain while core queue mechanics remain in `queue`; model-menu state, scoped model pages, callback planning, and model-menu rendering moved into the flat `menu-model` domain while core model semantics remain in `model`; thinking-menu text, markup, callbacks, and rendering moved into the flat `menu-thinking` domain; status-menu payloads, callbacks, and rendering moved into the flat `menu-status` domain. Impact: `menu.ts` is smaller and queue/model/thinking/status control surfaces have dedicated UI boundaries without adding folders or changing Telegram behavior.
|
|
17
|
+
- `[Menu]` Busy-state messages now mention `/abort`, `/next`, and `/stop`; submenu main navigation uses top-row `⬆️ Main menu`; thinking-menu text is a compact bold heading because the selected level is already marked in the buttons; model-menu scope and pagination controls now sit at the top under Main menu, and the pagination indicator opens a compact `<b>Choose a page:</b>` picker with numbered page buttons.
|
|
18
|
+
- `[Queue Reactions]` Priority reactions now accept `👍`, `⚡️`, `❤️`, and `🕊`; removal reactions now accept `👎`, `👻`, `💔`, and `💩`. Impact: users can use more default Telegram reactions for queue control while keeping the same priority/removal semantics.
|
|
19
|
+
- `[Config]` `telegram.json` persistence now writes through a private temp file and atomic rename before restoring `0600` permissions. Impact: concurrent setup/status reload paths and interrupted writes no longer expose readers to a truncated JSON file.
|
|
20
|
+
- `[Status]` Main-menu status output now renders `Status: idle|active|pending|unknown` as a normal status row instead of a standalone heading; TUI status-bar `active` uses the `warning` color token.
|
|
21
|
+
- `[Reply Dedup]` Only the first agent message in a turn replies to the triggering prompt; subsequent messages skip `reply_to_message_id`. Impact: stacked reply headers no longer waste vertical viewport space—the first message anchors the thread and the rest deliver as independent messages. Implemented at the transport level in `buildTelegramReplyParameters` so preview delivery, voice upload, and all text paths are caught uniformly. Reset on `agent_start` via `lifecycle.ts`.
|
|
22
|
+
- `[Command Template]` Default timeout of 30s (`DEFAULT_COMMAND_TIMEOUT_MS`) is now exported and enforced; handler invocations may omit explicit `timeout` where the default is sufficient.
|
|
23
|
+
- `[Command Template]` `critical` field standardised: when `true`, leaf failure aborts the entire root composition. `attachment-handlers.ts` and `outbound-handlers.ts` composition loops implement fail-open default (continue on non-critical failure) with critical re-throw gating. Impact: the TTS pipeline (edge-tts → ffmpeg) can mark ffmpeg as critical and abort cleanly.
|
|
24
|
+
- `[Docs]` Handler documentation and README examples now rely on default command timeouts and keep config examples minimal; critical-step guidance remains where needed.
|
|
25
|
+
- `[Typing Safety]` Typing-loop send failures now update the live status through the prompt-dispatch context and still record diagnostics. Impact: transient typing failures are visible without relying only on `/telegram-status`.
|
|
26
|
+
- `[Type Safety]` Preview reply markup now flows through generic preview controller/runtime and agent-end finalization contracts instead of `any`. Impact: assistant-authored buttons keep their concrete inline-keyboard type through preview finalization without narrowing future preview transports.
|
|
27
|
+
- `[Tests]` 416 passing (was 402 before prompt-template command coverage): reply dedup, critical composition gating, queue controls, queued `/continue`, unified app menu/status rows, menu-domain splits, queue-menu navigation order, preview reply-markup typing, prompt-template command expansion, and transport-level reply-parameter dedup are all covered.
|
|
28
|
+
|
|
29
|
+
## 0.6.3: Outbound Action Syntax & Prompt Guidance
|
|
30
|
+
|
|
31
|
+
- `[Outbound Buttons]` `telegram_button: Label` now creates a label-only button whose callback prompt equals the label. Impact: button shorthand now matches the `telegram_voice: Text` inline style and leaves one canonical label-only syntax.
|
|
32
|
+
- `[Outbound Actions]` `telegram_voice text="..."` and `telegram_button label=... prompt="..."` now provide explicit one-line action forms. Impact: agents can keep short voice and button actions on one line without relying on body blocks.
|
|
33
|
+
- `[Outbound Parsing]` Hidden action bodies now stay attached to their action heads within the parser recovery window. Impact: hidden prompt and TTS bodies stay out of Telegram-visible messages.
|
|
34
|
+
- `[Prompt Guidance]` Telegram prompt injection is now organized by inbound context, visible output, and native outbound actions, with explicit one-line vs body `telegram_button` syntax. Impact: agents get the same operational rules with less duplicated guidance and more consistent action markup.
|
|
35
|
+
- `[Architecture]` Entrypoint wiring now names inbound routing, queue session lifecycle, agent lifecycle hooks, outbound reply collaborators, and repeated pi context ports before registration. Impact: `index.ts` remains the composition root while the final hook/polling registration blocks are easier to scan.
|
|
36
|
+
- `[Config]` Missing `telegram.json` is now handled with an explicit existence check before reading. Impact: first-run config loading keeps the empty-config fallback without using read failures as control flow.
|
|
37
|
+
|
|
38
|
+
## 0.6.2: Reload-Stale Queue Dispatch Hotfix
|
|
39
|
+
|
|
40
|
+
- `[Queue Dispatch]` Deferred post-agent-end queue dispatch is now session-bound and canceled on session shutdown. Impact: `/reload` and session replacement can no longer leave old queue timers calling stale `ExtensionContext` methods such as `ctx.isIdle()`.
|
|
41
|
+
- `[Typing Safety]` Typing-loop transport failures now go only to runtime diagnostics instead of updating status through an interval-captured context. Impact: typing errors remain visible in diagnostics without retaining live `ExtensionContext` in timer error paths.
|
|
42
|
+
- `[Lock Watcher Safety]` Ownership-loss watchers now retain only the snapshotted lock identity and stop polling without a captured live context. Impact: singleton takeover cleanup no longer needs stale-prone status refreshes from watcher callbacks.
|
|
43
|
+
- `[Media Group Safety]` Media-group debounce timers now flush through controller state instead of closure-capturing the inbound context. Impact: album coalescing keeps the same behavior while reducing stale-context retention in timer callbacks.
|
|
44
|
+
|
|
45
|
+
## 0.6.1: Outbound Action & Command Timeout Hardening
|
|
46
|
+
|
|
47
|
+
- `[Command Template Runtime]` Timed-out command templates now escalate from `SIGTERM` to `SIGKILL` when the child process does not exit. Impact: attachment and outbound-handler pipelines no longer hang forever on commands that ignore graceful termination.
|
|
48
|
+
- `[Outbound Buttons]` `telegram_button` blocks may now omit the body when the callback prompt should equal the label. Impact: concise buttons such as `<!-- telegram_button label="OK" -->` work without duplicating the prompt text.
|
|
49
|
+
- `[Outbound Comment Parsing]` Top-level outbound comments are now recognized again after fenced code blocks closed by Markdown-valid indented or longer fences. Impact: code examples stay literal while later `telegram_voice` and `telegram_button` blocks still execute correctly.
|
|
50
|
+
- `[Command Template Docs]` The command-template contract now explicitly documents the strict 0.6.x shape: use `timeout`, and keep `args` as a string array of placeholder declarations. Impact: legacy `timeoutMs` and string-form `args` are not presented as supported compatibility paths.
|
|
51
|
+
|
|
52
|
+
## 0.6.0: Command Templates & Assistant-Authored Outbound Actions
|
|
53
|
+
|
|
54
|
+
- `[Outbound Actions]` Assistant replies now use hidden `telegram_voice` and `telegram_button` blocks as Telegram-native action markup. Impact: text stays in the normal Markdown answer, voice block bodies become native OGG/Opus `sendVoice` messages, and button bodies become normal queued Telegram prompt turns without agent-side transport tool calls.
|
|
55
|
+
- `[Outbound Semantics]` Outbound behavior is now owned by the unified `outbound-handlers` domain. Impact: voice artifacts, per-block language/rate attributes, independent multi-voice delivery, singular one-block-one-button callbacks, top-level-only comment stripping, artifact upload, and prompt reply metadata are planned and delivered as one post-`agent_end` response surface while code examples stay literal.
|
|
56
|
+
- `[Command Template Standard]` Command-backed handlers now share a compact shell-free template contract: no `command` field, `template` as string or `template: [...]`, `args` as declarations only, defaults via `defaults` or `{name=default}`, top-level `timeout` wrapping composed sequences, stdout-to-stdin composition piping, and `output` defaulting to `"stdout"` while allowing artifact selectors such as `"ogg"`. Impact: inbound attachment preprocessing and outbound artifact generation use the same portable automation model without provider-specific fields or shell evaluation.
|
|
57
|
+
- `[Handler Boundaries]` Inbound preprocessing now lives in `attachment-handlers`, outbound generated actions live in `outbound-handlers`, and reusable template mechanics live in `command-templates`. Impact: file names, mirrored tests, and docs match the actual domains instead of broad `handlers`, standalone voice, or grouped button mini-DSL boundaries.
|
|
58
|
+
- `[Docs]` Handler examples now use portable `/path/to/stt`, `/path/to/tts`, and `/path/to/tool` placeholders and dense command-template documentation. Impact: release docs describe what operators configure without leaking host-local skill paths or repeating the same template rules across documents.
|
|
59
|
+
|
|
60
|
+
## 0.5.2: Telegram Reply Context
|
|
61
|
+
|
|
62
|
+
- `[Telegram Replies]` Normal Telegram prompts now include quoted Telegram `reply_to_message` text/caption as a bounded `[reply]` context block. Impact: replying to an earlier Telegram message gives the agent the quoted context instead of only the new message text. Inspired by external PR #4 from @maphim.
|
|
63
|
+
- `[Command Safety]` Slash-command parsing still uses only the new message text/caption, and reply context is injected only while building or editing queued prompt turns. Impact: replying with `/status`, `/model`, `/stop`, and other commands still executes the command instead of becoming a normal prompt.
|
|
64
|
+
- `[Docs & Tests]` Updated README, architecture/context notes, package metadata, and media/turn regressions for reply-context forwarding, truncation, queued edits, and command-safe raw text extraction. Impact: the feature is documented and covered without weakening the existing queue/command split.
|
|
65
|
+
|
|
66
|
+
## 0.5.1: Stop Queue Reset Hotfix
|
|
67
|
+
|
|
68
|
+
- `[Queue Safety]` Telegram `/stop` now clears all waiting Telegram queue items, resets pending model-switch/abort-history preservation state, and then aborts the active run when possible. Impact: queued priority/default/control turns can no longer leave the bridge stopped after an abort; the next Telegram message starts from a clean queue like a fresh TUI prompt.
|
|
69
|
+
- `[Docs & Tests]` Updated README, architecture notes, agent context, and queue/runtime/command regressions for the new stop/reset contract. Impact: the hotfix behavior is documented and covered by the high-risk stop plus queue path.
|
|
70
|
+
|
|
71
|
+
## 0.5.0: Command Templates, Domain Boundaries & Queue UX
|
|
72
|
+
|
|
73
|
+
- `[Queue UX]` Telegram `/status` and `/model` now execute immediately, post-agent-end queue dispatch retries after pi settles idle state, and the status bar shows specific busy labels (`active`, `dispatching`, `queued`, `tool running`, `model`). Reaction priority remains local and applies to text, voice, file, image, and media-group turns without introducing pi steering semantics. Impact: controls do not get stuck behind generation, queued work no longer needs a later Telegram update to unstick, and attachment turns keep predictable ordering.
|
|
74
|
+
- `[Attachment Handlers]` Inbound preprocessing now uses portable `template` configs with `args`/`defaults` and ordered fallback chains, documented in `docs/command-templates.md` and `docs/attachment-handlers.md`. Impact: voice/STT primary-fallback setups work from `telegram.json` without coupling pi-telegram to private auto-tool registry internals.
|
|
75
|
+
- `[Domain Boundaries]` Removed the broad `registration` domain and moved registration surfaces to owners: attachments register `telegram_attach`, commands register pi `/telegram-*` commands, lifecycle registers hooks, and prompts own Telegram-specific system prompt injection. Impact: entrypoint wiring is clearer and each registration surface has focused tests.
|
|
76
|
+
- `[telegram_attach]` The outbound attachment tool now lives in the attachments domain with outbound limits, queueing failure events, and pi-friendly tool-result formatting. Impact: outbound file delivery behavior is owned by the same domain that queues and sends Telegram attachments.
|
|
77
|
+
- `[Docs & Validation]` Updated README, docs, architecture/context maps, backlog, focused coverage, and removed vendored repository-local agent skills in favor of global validation tooling. Impact: user-facing docs, validation, and package-adjacent repo contents match the 0.5.0 code shape without stale skill copies.
|
|
78
|
+
|
|
79
|
+
## 0.4.0: Singleton Locks & Attachment Handlers
|
|
80
|
+
|
|
81
|
+
- `[Locks]` Added the shared `locks.json` singleton ownership standard and documented it in `docs/locks.md`. Telegram polling ownership now lives under `@llblab/pi-telegram` in `~/.pi/agent/locks.json`, while `telegram.json` remains pure bot/user configuration. `/telegram-connect` acquires the lock, replaces stale locks, or moves live external owners here through an interactive confirmation; `/telegram-disconnect` releases it. Session initialization reads ownership state, active owners stop local polling when `locks.json` no longer points at their own `pid`/`cwd`, session replacement via `/new` suspends polling/watchers without touching explicit ownership before resuming in the new session, and a reopened pi process resumes a stale same-`cwd` lock automatically. Impact: runtime locks can be reset or moved without deleting Telegram configuration, finding the previous pi instance, or crashing on stale extension contexts.
|
|
82
|
+
- `[Attachment Handlers]` Added `telegram.json` inbound attachment handlers with MIME/type matching, safe command placeholder substitution, compact `[attachments] <directory>` plus `[outputs]` prompt sections, and quiet omission of empty or failed handler output. Impact: common flows such as Telegram voice transcription can happen before the agent sees the turn while keeping source attachment paths visible.
|
|
83
|
+
- `[Refactor]` Extracted inbound route composition from `index.ts` into `/lib/routing.ts`, keeping paired update execution, callback menus, command-or-prompt dispatch, media grouping, prompt enqueueing, queued edits, and attachment-handler turn building behind one cohesive route wiring boundary. Impact: the entrypoint stays smaller while high-risk Telegram update flow remains covered by runtime and invariant tests.
|
|
84
|
+
|
|
85
|
+
## 0.3.0: Modular Runtime, Queue Controls, Diagnostics
|
|
86
|
+
|
|
87
|
+
### Runtime Architecture
|
|
88
|
+
|
|
89
|
+
- `[Flat Domain DAG]` The extension now uses `index.ts` as the single composition root over flat, acyclic `/lib` domains. API transport, persisted config/pairing, model control, queue/lifecycle, runtime state, commands, menu UI, polling, previews, replies, rendering, media, turns, attachments, updates, setup, status, pi SDK adapters, and registration each have explicit ownership. Impact: bridge behavior is easier to locate without introducing a second entrypoint or shared bucket modules.
|
|
90
|
+
- `[Composition Root]` `index.ts` now focuses on live pi/Telegram ports, session-local state, and cross-domain wiring. Stable defaults and local adapters for rendering, preview limits, preview reply metadata, attachment limits, Telegram prompt prefixes, prompt suffixes, command control items, bot command registration, API runtime construction, polling controllers, prompt dispatch, reply delivery, setup prompts, queue/session lifecycle, agent hooks, and tool hooks live in their owning domains. Impact: the entrypoint is smaller and reads as orchestration instead of carrying domain behavior.
|
|
91
|
+
- `[Type Boundaries]` Concrete Bot API transport shapes live in `api`, queued/active turn contracts live in `queue`, persisted session state lives in `config`, media download metadata lives in `media`, model selection contracts live in `model`, and domain constants stay with their owners. Narrow structural view contracts are used where a domain only needs a projection. Impact: public module interfaces are cleaner and accidental cross-domain coupling is reduced.
|
|
92
|
+
- `[Runtime State]` `runtime` owns only session-local coordination primitives: queue/control/priority counters, lifecycle flags, setup guards, abort handler storage, typing-loop timers, prompt-dispatch lifecycle binding, and agent-end reset sequencing. Preview state, queue planning, command behavior, rendering, and API transport stay outside `runtime`. Impact: mutable bridge state is centralized without becoming a general-purpose behavior bucket.
|
|
93
|
+
|
|
94
|
+
### Queue, Lifecycle, And Controls
|
|
95
|
+
|
|
96
|
+
- `[Queue Core]` `queue` owns prompt/control item contracts, explicit control/priority/default lane admission rules, queue stores, active-turn state, queue mutation, dispatch readiness, prompt enqueueing, control enqueueing, session start/shutdown sequencing, and agent/tool lifecycle hooks. Impact: scheduling rules, active-turn binding, abort preservation, compaction guards, and dispatch safety are enforced in one place.
|
|
97
|
+
- `[Command Admission]` `/stop`, `/compact`, `/help`, and `/start` execute immediately, while `/status`, `/model`, and model-switch continuation prompts enter the control lane ahead of normal prompts. Priority reactions promote waiting prompts into the priority lane without bypassing control actions. Asynchronous control-item execution is serialized so new prompts or controls cannot dispatch while a queued `/status` or `/model` action is still settling. Impact: Telegram controls stay responsive while normal messages remain predictably ordered.
|
|
98
|
+
- `[Model Control]` `model` owns model identity, thinking levels, scoped model pattern parsing/resolution/sorting, current-model state, in-flight model-switch state, restart eligibility, delayed abort decisions, continuation prompt construction, and model-switch controller runtime binding. Impact: model selection, scoped menus, and in-flight restart behavior have one cohesive home.
|
|
99
|
+
- `[Commands And Menus]` `commands` owns slash-command parsing, command metadata, command-message targets, command execution modes, control-queue adapters, bot command registration, and stop/compact/status/model/help side effects. The Telegram bot command menu no longer exposes `/debug`; diagnostics live in pi-side `/telegram-status` and the pi TUI. `menu` owns inline status/model/thinking UI state, model-menu caching, callback routing, callback planning, render payloads, and menu message updates. Impact: Telegram controls can be tested without reading the full runtime composition.
|
|
100
|
+
|
|
101
|
+
### Telegram Delivery, Rendering, And Files
|
|
102
|
+
|
|
103
|
+
- `[Rendering]` `rendering` owns Telegram HTML Markdown scanning, escaping, preview snapshots, raw HTML chunking, long-message splitting, table/list formatting, grapheme/display-width-aware table padding for emoji and wide Unicode text, nested quote flattening, link safety, task-list handling, and literal code preservation. Impact: Telegram output stays readable on narrow clients while avoiding malformed HTML and broken code blocks.
|
|
104
|
+
- `[Registration]` The Telegram before-agent prompt suffix now reminds the assistant to prefer narrow table columns because Telegram is often read on phone-width screens where wide monospace tables become unreadable. Impact: Telegram-originated tabular answers are more likely to fit mobile chats before renderer-level formatting is applied.
|
|
105
|
+
- `[Preview And Replies]` `preview` owns streaming preview lifecycle, draft/editable-message transport choices, flush scheduling, preview finalization, and assistant-message hooks, while defaulting preview reply metadata through the `replies` helper instead of threading it through `index.ts`. `replies` owns final rendered-message delivery, reply parameters, assistant-message extraction, plain/Markdown replies, interactive message delivery, and split-message reply metadata. Impact: rich previews, final replies, errors, attachment notices, and uploads are tied to the source Telegram prompt when possible and degrade safely when Telegram cannot attach the reply.
|
|
106
|
+
- `[Files And Attachments]` `api` owns Bot API calls, retries, runtime error recording, temp-dir cleanup, inbound file limits, lazy bot-token clients, chat actions, and file downloads. `media` owns inbound text/media extraction, file-info normalization, media-group debounce, and download assembly. `attachments` owns outbound attachment queueing, atomic multi-file staging, stat checks, outbound limits, photo/document classification, and queued attachment sending. Impact: inbound downloads and outbound uploads are size-limited by default, large files fail predictably without leaving partial attachment batches staged, and outbound artifacts flow through `telegram_attach`.
|
|
107
|
+
- `[Config And Setup]` `config` owns `telegram.json`, bot-token/allowed-user state, single-user authorization, and first-user pairing. `setup` owns token prompting, stored-token/env fallback selection, validation, and guarded setup orchestration. Impact: pairing and setup behavior stays consistent across `/telegram-setup`, `/telegram-connect`, `/start`, and update routing.
|
|
108
|
+
|
|
109
|
+
### Observability, Packaging, And Validation
|
|
110
|
+
|
|
111
|
+
- `[Status And Diagnostics]` `/telegram-status` now reports bridge diagnostics as grouped line-by-line pi notification sections separated by blank lines, ending with the redacted recent runtime/API event ring after connection, polling, execution, and queue state such as active turn, queue depth, queue lanes, compaction, active tool count, and pending model-switch state. Transport/API failures, polling/update failures, prompt dispatch failures, control action failures, typing failures, compaction failures, setup failures, session lifecycle failures, and attachment queue/delivery failures are recorded in the ring, while benign unchanged edit responses and empty draft-clear attempts do not pollute it. Impact: operators can diagnose bridge stalls and transport/runtime failures after the fact without exposing a Telegram-side debug command.
|
|
112
|
+
- `[Package Contents]` The npm package uses an explicit allowlist and keeps the tracked lockfile. Impact: published tarballs exclude tests and internal context files while preserving predictable release contents.
|
|
113
|
+
- `[Validation]` The project now ships typecheck, test, audit, package dry-run, and combined `validate` scripts plus GitHub Actions validation. Regression coverage spans rendering fixtures, queue/runtime/session behavior, command admission, lane contracts, invalid-lane rejection, setup, registration, replies, polling, updates, attachments, media, config, model resolution, preview timers, and extension-runtime flows. Impact: release checks catch type errors, dependency issues, package-content drift, rendering regressions, queue/lifecycle races, and architecture-boundary drift before publishing.
|
|
114
|
+
- `[Architecture Guards]` Invariant tests enforce an acyclic local import graph, ban `lib/constants.ts` and `lib/types.ts`, keep empty interface-extension shells collapsed into clearer type aliases, centralize direct pi SDK imports, keep `index.ts` source code free of direct Node runtime imports, local helper declarations, local arrow adapters, direct `process.env`, and direct `pi.*` receiver access, keep `runtime` and structural leaf domains isolated, guard menu/model, API/config, media/update/API, and attachment/queue/media/API boundaries, and require project TypeScript files to keep responsibility headers. Impact: the Flat Domain DAG shape and file-boundary documentation stay protected as domains continue to evolve.
|
|
115
|
+
- `[Refactor]` Reopened compression/decomposition/refactor/consistency passes tightened menu-domain message render/send plumbing, compressed repeated menu/media/attachment/runtime/API/model/queue test harness shapes, extracted shared runtime context, model-context, dispatch-event, Telegram config, deferred-response, API-response, rich-response, prompt-block, fetch-method, API response/client/fetch-restore, runtime fetch/model, model-test, queue-model, queue prompt/control/item-type, registration active-turn, menu-model, and pi API test fixtures, migrated runtime integration tests onto those fixtures, replaced ad hoc structural casts with owning-domain or test-local helpers where practical, and removed avoidable test casts from attachment, polling, update, model, reply, menu, pi-adapter, and registration suites. Impact: the codebase stays easier to extend without changing Telegram runtime behavior.
|
|
116
|
+
|
|
117
|
+
## 0.2.x: Fork Genesis
|
|
118
|
+
|
|
119
|
+
- `[Turns]` Preserved existing attachment-path blocks and aborted-turn history context when a still-queued Telegram message is edited. Impact: caption edits no longer make queued prompts lose their downloaded file references or prior-message context.
|
|
120
|
+
- `[Polling]` Persisted Telegram long-poll offsets only after each update is handled successfully. Impact: a handler failure no longer marks an unprocessed Telegram update as consumed, reducing the chance of silently dropping inbound messages.
|
|
121
|
+
- `[Telegram API]` Added HTTP-status-aware Bot API response parsing, malformed-success handling, retry/backoff for 429 and 5xx Bot API responses, streaming Telegram downloads with size-limit checks, file-backed multipart upload blobs, partial-download cleanup on limit failures, startup cleanup for stale Telegram temp files, and UUID-based sanitized temp filenames. Impact: Telegram transport failures now report clearer status/description details, transient Telegram throttling/server failures get retried automatically, oversized inbound files are rejected before or during download, outbound multipart sends avoid preloading files into memory, partial and stale temp files are removed, and downloaded files are less prone to timestamp collisions or unsafe local names.
|
|
122
|
+
- `[Rendering]` Escaped generated HTML attributes separately, sanitized code-fence language classes, and chunked raw HTML-mode output below Telegram length limits with balanced tag reopening across raw HTML chunks. Impact: generated Telegram HTML is harder to malformed through link or fence metadata and long raw-HTML replies no longer exceed Telegram's message size limit or break active tags across chunk boundaries.
|
|
123
|
+
- `[Preview]` Serialized overlapping preview flushes through a single in-flight flush chain. Impact: rapid streaming updates no longer allow concurrent Telegram edit calls to overwrite newer preview text with stale snapshots.
|
|
124
|
+
- `[Polling]` Added a bounded poisoned-update policy for repeatedly failing Telegram updates. Impact: one malformed or consistently failing update can no longer stall the long-poll loop forever; after the retry threshold, the bridge records and advances past it.
|
|
125
|
+
- `[Menu]` Added short-lived model-menu input caching plus TTL/LRU cleanup for stored inline menu state. Impact: repeated `/status` and `/model` interactions do less settings/model-registry work, while old Telegram inline keyboards expire predictably instead of accumulating for the whole session.
|
|
126
|
+
- `[Updates]` Routed Telegram `edited_message` updates separately from new messages and applied edits to matching queued turns. Impact: editing a still-queued Telegram message updates the pending prompt instead of enqueueing a duplicate turn.
|
|
127
|
+
- `[Refactor]` Moved shared Telegram Bot API transport shapes out of `index.ts` into `lib/types.ts`. Impact: the entrypoint is smaller and future runtime extraction can reuse one type boundary instead of keeping local duplicate interfaces.
|
|
128
|
+
- `[Refactor]` Moved Telegram media-group debounce and pending-group removal into the existing media domain with mirrored tests. Impact: album coalescing and reaction/delete cleanup are easier to validate without reading the full extension entrypoint, while avoiding an unnecessary extra domain file.
|
|
129
|
+
- `[Refactor]` Extracted Telegram slash-command parsing and command-action routing into `lib/commands.ts` with mirrored tests, and moved queued-turn text replacement for edited messages into the turn domain. Impact: command normalization/execution planning and queued edit mutations are reusable, while the entrypoint keeps less local runtime state logic.
|
|
130
|
+
- `[Rendering]` Hardened link rendering so absolute links stay clickable, markdown-heavy link labels reduce to plain clickable labels, tooltip titles are ignored safely, balanced-parenthesis URLs stay intact, and unsupported link forms degrade without broken anchors. Impact: Telegram replies now keep more links usable while avoiding malformed output for relative, reference-style, or footnote-like link syntax.
|
|
131
|
+
- `[Preview]` Evolved rich streaming from first-chunk snapshots to stable-block previews with a conservative plain tail fallback, while preserving original blank-line spacing between rendered blocks and keeping headings visually separated from following blocks. Impact: closed top-level Markdown blocks now stream as rich Telegram HTML before finalization, incomplete fences, quotes, lists, and other trailing work remain readable without producing broken rich formatting, preview/final block spacing no longer collapses extra empty lines, and headings no longer visually merge into following code blocks when source Markdown omits a blank line.
|
|
132
|
+
- `[Refactor]` Split preview concerns so runtime transport and finalization live in the preview domain while preview snapshot derivation lives in the rendering domain. Impact: rich streaming can evolve independently from final reply delivery while keeping preview appearance decisions closer to the Telegram renderer.
|
|
133
|
+
- `[Streaming]` Switched Telegram previews from plain draft-first text to rich first-chunk message editing, so formatting appears during generation instead of only after finalization. Impact: users now see richer streamed output earlier, while final replies still replace the preview with fully rendered Telegram HTML.
|
|
134
|
+
- `[Rendering]` Preserved leading indentation on the first Markdown line, kept numeric markers for ordered task lists in both preview and final Telegram rendering, and stopped reinterpreting standalone `[x]` or `[ ]` prose as inline checkboxes. Impact: nested content no longer flattens when a message starts with indentation, numbered checklists keep their ordered semantics, and literal checklist-like prose stays literal.
|
|
135
|
+
- `[Queue UI]` Marked liked high-priority queued Telegram turns with `⬆` in the pi status-bar queue preview. Impact: operators can now distinguish reaction-promoted turns from normal queued prompts at a glance.
|
|
136
|
+
- `[Docs]` Added short responsibility header comments to every project `.ts` file. Impact: file boundaries are easier to understand while navigating the growing `/lib` split.
|
|
137
|
+
- `[Naming]` Renamed extracted domain modules and mirrored regression suites to use repo-scoped bare domain filenames such as `api.ts`, `queue.ts`, and `queue.test.ts` instead of repeating `telegram-*` in every path. Impact: the internal topology is easier to scan and stays aligned with the repository-level Telegram scope.
|
|
138
|
+
- `[Controls]` Expanded Telegram session controls with a richer `/status` view, inline model selection, and thinking-level controls, and fixed the callback-selection path so idle model and thinking picks apply immediately instead of only becoming visible after a later Telegram interaction. Impact: more bridge configuration can be managed directly from Telegram with more predictable immediate feedback.
|
|
139
|
+
- `[Queue]` Upgraded Telegram turn queueing with previews, reaction-driven prioritization/removal, media-group handling, aborted-turn history preservation, and safer dispatch gating. Impact: follow-up handling is more transparent and less prone to lifecycle races.
|
|
140
|
+
- `[Rendering]` Added Telegram-oriented Markdown rendering and hardened reply streaming/chunking behavior, including narrower monospace Markdown table output without outer side borders, monospace list markers for unordered and ordered lists, and flattened nested quote indentation inside a single Telegram blockquote. Impact: formatted replies render more reliably while preserving literal code blocks and using width more efficiently on narrow Telegram clients.
|
|
141
|
+
- `[Runtime]` Hardened attachment delivery, polling/runtime behavior, Telegram session integration, preview-finalization and reply-transport routing into the replies domain, lazy Telegram API client routing into the Telegram API domain, turn-building extraction into its own domain, menu/model-resolution plus menu-state, pure menu-page derivation, pure menu render-payload builders, menu-message runtime, callback parsing, callback entry handling, callback mutation helpers, full model-callback planning and execution, and interface-polished callback effect ports into the menu domain, direct execute-from-update routing into the updates domain, model-switch restart glue extraction into the model-switch domain, and tool/command/lifecycle-hook registration extraction into a dedicated registration domain. Impact: the bridge is more robust as a daily Telegram frontend for pi.
|
|
142
|
+
- `[Metadata]` Updated package repository metadata to point at the `llblab/pi-telegram` fork and renamed the npm package to `@llblab/pi-telegram` with public scoped publish settings. Impact: published package links no longer send users to stale upstream coordinates and the package can be published under the fork-owned npm scope.
|
|
143
|
+
- `[Validation]` Added lightweight regression tests for Telegram Markdown rendering, queue/runtime/agent-loop/session/control/dispatch, replies, polling, updates, attachments, registration, turns, menu, and Telegram API/media/config helpers, including quote/list, table, link/code, mixed-link/code chunking, mixed-block chunk transitions, long multi-block, long-quote, long inline-formatting chunk boundaries, list-code-quote-prose chunk transitions, narrower monospace table rendering without outer side borders, monospace unordered and ordered list markers, flattened nested quote indentation inside one Telegram blockquote, inbound poll/pair/dispatch runtime cases, preview finalization, aborted-turn history carry-over, queued-status/model-after-agent-end sequencing, compaction gating, media-group debounce dispatch, direct menu callback planning and execution, pure menu-page derivation, pure menu render-payload builders, reaction-driven reprioritization/removal, immediate in-flight model-switch continuation, delayed abort-after-tool-completion, lazy Telegram API client routing, turn-building, and scoped-model resolution. Impact: key renderer and queue invariants now have repeatable automated coverage across the known high-risk bridge paths.
|
|
144
|
+
- `[Model Switching]` Enabled `/model` during an active Telegram-owned run by applying the new model and continuing on the new model automatically, delaying the abort until the current tool finishes when needed. Impact: Telegram can now approximate pi's manual stop-switch-continue workflow with fewer mid-tool aborts.
|
|
145
|
+
- `[Queue Core]` Introduced queued item kinds and explicit queue-lane ordering semantics so prompt turns and synthetic control actions share one ordering model, then regrouped the extracted helpers into flatter domain-oriented `/lib` modules such as queue, replies, polling, updates, attachments, turns, menu, Telegram API, and registration while keeping `index.ts` as the entrypoint. Prompt items now stay queued until `agent_start` consumes the dispatched turn, which restores correct active-turn binding for previews and final delivery. Impact: the bridge now has a clearer foundation for scheduling async extension operations alongside Telegram prompts without losing a single obvious runtime entry file.
|
|
146
|
+
- `[Registration]` Moved extension tool, command, and lifecycle-hook binding into the registration domain and added registration-focused regression coverage. Impact: extension wiring is easier to reason about and test without dragging full runtime state into every registration change.
|
|
147
|
+
- `[Control Queue]` Moved `/status` and `/model` command handling onto high-priority control queue items. Impact: control actions can wait safely behind the current run while still jumping ahead of normal queued prompts.
|
|
148
|
+
- `[Setup]` `/telegram-setup` now shows the stored bot token first, otherwise prefills from common Telegram bot environment variables before falling back to the placeholder, using an actual prefilled editor when a real default exists. Impact: repeat setup respects local saved state while first-run and secret-managed setup stay fast.
|
package/README.md
CHANGED
|
@@ -13,13 +13,13 @@ This repository is an actively maintained fork of [`badlogic/pi-telegram`](https
|
|
|
13
13
|
|
|
14
14
|
## Key Features
|
|
15
15
|
|
|
16
|
-
- **
|
|
17
|
-
- **Interactive UI**: Manage your session directly from Telegram. Inline buttons
|
|
16
|
+
- **Telegram Controls**: `/start` opens the inline application menu with command help, available π prompt templates, status rows, model, thinking, and queue sections; `/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
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
|
|
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
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 files with configured attachment handlers, or ask
|
|
22
|
-
- **Streaming Responses**: Closed Markdown blocks stream back as rich Telegram HTML while
|
|
21
|
+
- **File Handling & Attachments**: Send images and files to the agent, transcribe or transform inbound files with configured attachment 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.
|
|
23
23
|
|
|
24
24
|
## Install
|
|
25
25
|
|
|
@@ -44,23 +44,23 @@ pi install git:github.com/llblab/pi-telegram
|
|
|
44
44
|
3. Pick a name and username
|
|
45
45
|
4. Copy the bot token
|
|
46
46
|
|
|
47
|
-
### 2. Configure the extension in
|
|
47
|
+
### 2. Configure the extension in π
|
|
48
48
|
|
|
49
|
-
Start
|
|
49
|
+
Start π, then run:
|
|
50
50
|
|
|
51
51
|
```bash
|
|
52
52
|
/telegram-setup
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
-
Paste your bot token when prompted. If a bot token is already saved in `~/.pi/agent/telegram.json`, the setup prompt shows that stored value by default. Otherwise it prefills from the first configured environment variable in `TELEGRAM_BOT_TOKEN`, `TELEGRAM_BOT_KEY`, `TELEGRAM_TOKEN`, or `TELEGRAM_KEY`. The saved config file is written with private `0600` permissions.
|
|
55
|
+
Paste your bot token when prompted. If a bot token is already saved in `~/.pi/agent/telegram.json`, the setup prompt shows that stored value by default. Otherwise it prefills from the first configured environment variable in `TELEGRAM_BOT_TOKEN`, `TELEGRAM_BOT_KEY`, `TELEGRAM_TOKEN`, or `TELEGRAM_KEY`. The saved config file is written atomically with private `0600` permissions.
|
|
56
56
|
|
|
57
|
-
### 3. Connect this
|
|
57
|
+
### 3. Connect this π session
|
|
58
58
|
|
|
59
59
|
```bash
|
|
60
60
|
/telegram-connect
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
The bridge is session-local: only one
|
|
63
|
+
The bridge 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.
|
|
64
64
|
|
|
65
65
|
### 4. Pair your account from Telegram
|
|
66
66
|
|
|
@@ -71,57 +71,59 @@ The first user to message the bot becomes the exclusive owner of the bridge. The
|
|
|
71
71
|
|
|
72
72
|
## Usage
|
|
73
73
|
|
|
74
|
-
Once paired, simply chat with your bot in Telegram. All text, images, and files are forwarded to
|
|
74
|
+
Once paired, simply chat with your bot in Telegram. All text, images, and files are forwarded to π.
|
|
75
75
|
|
|
76
76
|
### Telegram Commands & Controls
|
|
77
77
|
|
|
78
78
|
Use these inside the Telegram DM with your bot:
|
|
79
79
|
|
|
80
|
-
- **`/start`**: Pair the first Telegram user when needed, register the bot command menu, and
|
|
81
|
-
- **`/help`**: Show the Telegram help text.
|
|
82
|
-
- **`/status`**: View session stats, cost, and use inline buttons to change models.
|
|
83
|
-
- **`/model`**: Open the interactive model selector.
|
|
80
|
+
- **`/start`**: Pair the first Telegram user when needed, register the bot command menu, and open the inline application menu with command help, available π prompt templates, status rows, and controls.
|
|
84
81
|
- **`/compact`**: Start session compaction (only works when the session is idle).
|
|
82
|
+
- **`/next`**: Dispatch the next queued turn (aborts π first if busy).
|
|
83
|
+
- **`/continue`**: Enqueue a priority `continue` prompt. It waits like normal Telegram work when π is busy and can trigger prompt/skill handling that listens for `continue`.
|
|
85
84
|
- **`/stop`**: Abort the active run and clear all waiting Telegram queue items.
|
|
85
|
+
- **`/abort`**: Abort the active run without touching the queue.
|
|
86
86
|
|
|
87
|
-
Telegram
|
|
87
|
+
Prompt-template commands: π prompt templates are mapped to Telegram-safe aliases (`fix-tests.md` becomes `/fix_tests`) and shown as compact command-only rows between the built-in commands and status rows in `/start`. They are not registered in the Telegram bot command menu, keeping the bot menu focused on bridge controls. Sending `/template_name args` from Telegram expands the matching π prompt-template file and queues the expanded prompt like normal Telegram work.
|
|
88
|
+
|
|
89
|
+
Hidden compatibility shortcuts: `/help` and `/status` open the same main application menu, `/model` opens the model section, `/thinking` opens the thinking section, and `/queue` opens the queue section. They are intentionally not shown in the bot command menu.
|
|
90
|
+
|
|
91
|
+
Telegram command admission is explicit: `/compact`, `/queue`, `/stop`, `/abort`, `/next`, `/help`, `/start`, `/status`, `/model`, and `/thinking` execute immediately. `/continue` is a command shortcut that enqueues a priority Telegram prompt containing `continue`. Prompt-template commands expand before queueing and then follow normal prompt-queue rules. Synthetic model-switch continuation turns still enter the high-priority control lane so they can resume before normal queued prompts when π becomes safe to dispatch.
|
|
88
92
|
|
|
89
93
|
### Pi Commands
|
|
90
94
|
|
|
91
|
-
Run these inside
|
|
95
|
+
Run these inside π, not Telegram:
|
|
92
96
|
|
|
93
97
|
- **`/telegram-setup`**: Configure or update the Telegram bot token.
|
|
94
98
|
- **`/telegram-status`**: Check bridge status, connection, polling, execution, queue, and recent redacted runtime/API failure events.
|
|
95
|
-
- **`/telegram-connect`**: Start polling Telegram updates in the current
|
|
96
|
-
- **`/telegram-disconnect`**: Stop polling in the current
|
|
99
|
+
- **`/telegram-connect`**: Start polling Telegram updates in the current π session, acquire the singleton lock, or interactively move ownership here from another live instance.
|
|
100
|
+
- **`/telegram-disconnect`**: Stop polling in the current π session and release the singleton lock.
|
|
97
101
|
|
|
98
102
|
### Queue, Reactions, and Media
|
|
99
103
|
|
|
100
|
-
- If you send more Telegram messages while
|
|
101
|
-
-
|
|
102
|
-
-
|
|
104
|
+
- If you send more Telegram messages while π is busy, they enter the default prompt queue and are processed in order.
|
|
105
|
+
- `👍`, `⚡️`, `❤️`, 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.
|
|
106
|
+
- `👎`, `👻`, `💔`, 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.
|
|
103
107
|
- 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.
|
|
104
108
|
- 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.
|
|
105
109
|
- 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.
|
|
106
|
-
- 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
|
|
110
|
+
- 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`.
|
|
107
111
|
- Queue reactions depend on Telegram delivering `message_reaction` updates for your bot and chat type.
|
|
108
112
|
|
|
109
113
|
### Inbound Attachment Handlers
|
|
110
114
|
|
|
111
|
-
`telegram.json` can define ordered `attachmentHandlers` for common preprocessing such as voice transcription. Matching handlers run after download and before the Telegram turn enters the
|
|
115
|
+
`telegram.json` can define ordered `attachmentHandlers` for common preprocessing such as voice transcription. Matching handlers run after download and before the Telegram turn enters the π queue. If a matching handler fails, the next matching handler is tried as a fallback.
|
|
112
116
|
|
|
113
117
|
```json
|
|
114
118
|
{
|
|
115
119
|
"attachmentHandlers": [
|
|
116
120
|
{
|
|
117
121
|
"type": "voice",
|
|
118
|
-
"template": "/path/to/stt1 --file {file} --lang {lang=ru}"
|
|
119
|
-
"timeout": 30000
|
|
122
|
+
"template": "/path/to/stt1 --file {file} --lang {lang=ru}"
|
|
120
123
|
},
|
|
121
124
|
{
|
|
122
125
|
"mime": "audio/*",
|
|
123
|
-
"template": "/path/to/stt2 --file {file} --lang {lang=ru}"
|
|
124
|
-
"timeout": 30000
|
|
126
|
+
"template": "/path/to/stt2 --file {file} --lang {lang=ru}"
|
|
125
127
|
}
|
|
126
128
|
]
|
|
127
129
|
}
|
|
@@ -131,11 +133,11 @@ Matching supports `mime`, `type`, or `match`; wildcards like `audio/*` are accep
|
|
|
131
133
|
|
|
132
134
|
### Requesting Files
|
|
133
135
|
|
|
134
|
-
If you ask
|
|
136
|
+
If you ask π for a file or generated artifact (e.g., _"generate a shell script and attach it"_), π can call the `telegram_attach` tool, and the extension will send the file alongside its next Telegram reply. `telegram_attach` is the only π tool registered by `pi-telegram`; use it for ordinary files, not for Telegram-native voice or buttons. Outbound attachments default to a 50 MiB limit and can be adjusted with `PI_TELEGRAM_OUTBOUND_ATTACHMENT_MAX_BYTES` or `TELEGRAM_MAX_ATTACHMENT_SIZE_BYTES`.
|
|
135
137
|
|
|
136
138
|
### Assistant-Authored Outbound Actions
|
|
137
139
|
|
|
138
|
-
Assistant replies can include hidden outbound blocks. `telegram_voice` and `telegram_button` are not
|
|
140
|
+
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.
|
|
139
141
|
|
|
140
142
|
#### Voice
|
|
141
143
|
|
|
@@ -155,7 +157,7 @@ Text to synthesize as a Telegram voice message.
|
|
|
155
157
|
|
|
156
158
|
Outbound voice is disabled unless a matching `outboundHandlers[]` entry is configured. Multiple `telegram_voice` blocks in one reply are synthesized and sent independently, preserving each block's attributes. The bridge uses the same [command-template contract](./docs/command-templates.md) as inbound attachment handlers: split the template into args, substitute placeholders, execute without a shell, and use stdout as the result channel for a single template.
|
|
157
159
|
|
|
158
|
-
A TTS plus MP3-to-OGG setup can be expressed as `template: [...]`. The bridge provides `{text}`, `{mp3}`, and `{ogg}` to every step; top-level `args`/`defaults` apply to all steps unless a step defines private values,
|
|
160
|
+
A TTS plus MP3-to-OGG setup can be expressed as `template: [...]`. The bridge provides `{text}`, `{mp3}`, and `{ogg}` to every step; top-level `args`/`defaults` apply to all steps unless a step defines private values, the default command timeout applies automatically, and each step's stdout is passed to the next step's stdin by default. Use `"output": "ogg"` when the artifact path should come from the generated `{ogg}` value instead of final stdout:
|
|
159
161
|
|
|
160
162
|
```json
|
|
161
163
|
{
|
|
@@ -166,8 +168,7 @@ A TTS plus MP3-to-OGG setup can be expressed as `template: [...]`. The bridge pr
|
|
|
166
168
|
"/path/to/tts --text {text} --lang {lang=ru} --rate {rate=+30%} --write-media {mp3}",
|
|
167
169
|
"ffmpeg -y -i {mp3} -c:a libopus -b:a 32k -ar 16000 -ac 1 -vbr on {ogg}"
|
|
168
170
|
],
|
|
169
|
-
"output": "ogg"
|
|
170
|
-
"timeout": 60000
|
|
171
|
+
"output": "ogg"
|
|
171
172
|
}
|
|
172
173
|
]
|
|
173
174
|
}
|
|
@@ -180,29 +181,29 @@ Button blocks attach inline quick replies to the final text. Use one independent
|
|
|
180
181
|
```md
|
|
181
182
|
I can continue.
|
|
182
183
|
|
|
183
|
-
<!-- telegram_button label=Continue prompt="Continue with the current plan." -->
|
|
184
|
-
|
|
185
184
|
<!-- telegram_button label="Show risks"
|
|
186
185
|
List the main risks first.
|
|
187
186
|
-->
|
|
188
187
|
|
|
188
|
+
<!-- telegram_button label=Continue prompt="Continue with the current plan." -->
|
|
189
|
+
|
|
189
190
|
<!-- telegram_button: OK -->
|
|
190
191
|
```
|
|
191
192
|
|
|
192
|
-
Button prompts are routed back into the normal Telegram queue as prompt turns. Keep the opening comment unclosed until the body-ending `-->` for body-form buttons. Closed heads must use `prompt="..."` or the colon shorthand to create a button. Outbound handler details are documented in [`docs/outbound-handlers.md`](./docs/outbound-handlers.md).
|
|
193
|
+
Button prompts are routed back into the normal Telegram queue as prompt turns. Keep the opening comment unclosed until the body-ending `-->` for body-form buttons. Closed heads must use `prompt="..."` or the colon shorthand to create a button. Unknown inline-button callbacks that do not belong to pi-telegram are forwarded to π as `[callback] <data>` so other extensions can namespace and handle their own Telegram buttons without polling the bot themselves; see the [Callback Namespace Standard](./docs/callback-namespaces.md). Outbound handler details are documented in [`docs/outbound-handlers.md`](./docs/outbound-handlers.md).
|
|
193
194
|
|
|
194
195
|
## Streaming
|
|
195
196
|
|
|
196
|
-
The extension streams assistant previews back to Telegram while
|
|
197
|
+
The extension streams assistant previews back to Telegram while π is generating.
|
|
197
198
|
|
|
198
199
|
Rich previews are sent through editable messages because Telegram drafts are text-only. Closed top-level Markdown blocks can appear with formatting before the answer finishes, while the still-growing tail remains conservative and readable until the preview is replaced with the fully rendered Telegram HTML reply. Editable preview messages are also attached as replies to the source Telegram prompt when possible.
|
|
199
200
|
|
|
200
201
|
## Status bar
|
|
201
202
|
|
|
202
|
-
The
|
|
203
|
+
The π status bar shows the current bridge state plus queued Telegram turns as compact previews. Busy labels distinguish states such as `active`, `dispatching`, `queued`, `tool running`, `model`, and `compacting`.
|
|
203
204
|
|
|
204
205
|
```text
|
|
205
|
-
telegram queued +3: [
|
|
206
|
+
telegram queued +3: [⚡ write a shell script…, summarize this image…, 📎 2 attachments]
|
|
206
207
|
```
|
|
207
208
|
|
|
208
209
|
## Notes
|
package/docs/README.md
CHANGED
|
@@ -9,3 +9,4 @@ Living index of project documentation in `/docs`.
|
|
|
9
9
|
- [attachment-handlers.md](./attachment-handlers.md) — Local `pi-telegram` attachment-handler config, placeholders, and fallbacks
|
|
10
10
|
- [outbound-handlers.md](./outbound-handlers.md) — Local `pi-telegram` outbound-handler config, voice/button markup, artifact outputs, and callback routing
|
|
11
11
|
- [locks.md](./locks.md) — Shared `locks.json` standard for singleton extension ownership
|
|
12
|
+
- [callback-namespaces.md](./callback-namespaces.md) — Shared Telegram `callback_data` namespace standard for layered extensions
|