@llblab/pi-telegram 0.33.2 → 0.34.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/CHANGELOG.md CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  > Each release keeps at most 8 outcome records of at most 512 characters.
4
4
 
5
+ ## 0.34.1: Compact Stateful Control Surfaces
6
+
7
+ - `Prompt Compression`: Teaches Generated Control Surface to encode the smallest sufficient action delta—such as a coordinate, symbol, identifier, or short verb—when visible conversation establishes unambiguous state, while retaining stable identity when delivery or routing could separate action from context.
8
+ - `Interaction State`: Keeps trivial state conversational, moves large or error-prone state to deterministic task-owned Markdown artifacts, delegates correctness-sensitive rules to small domain-owned transition implementations, and handles repeated clicks as current-state no-ops or selections without assuming transport-level disabled buttons.
9
+ - `Five-Wide UX`: Treats five-column matrices as useful for position-bearing interaction only with short distinct labels, falls back to fewer columns when readability degrades, and proactively offers interactive surfaces when they materially reduce user effort rather than merely decorating a reply.
10
+
11
+ ## 0.34.0: Five-Wide Matrix Controls
12
+
13
+ - `Button Matrix`: Expands compact nested JSON rows from one-to-three to one-to-five buttons for grids, keypads, palettes, games, and other position-bearing controls while preserving full-width top-level rows and existing object, attribute, flat-array, and plural-alias compatibility.
14
+ - `Matrix Boundaries`: Keeps empty rows, rows of six or more buttons, malformed payloads, and deeper nesting fail closed before callback registration; published docs and bundled Skills now expose the five-button boundary.
15
+ - `Interactive Surfaces`: Teaches Generated Control Surface to use five-wide position-bearing matrices for keypads, palettes, calendars, seat maps, directional controls, small games, and runnable demonstrations while keeping each continuation self-contained instead of inventing hidden application state.
16
+
5
17
  ## 0.33.2: Structured Filesystem Surfaces
6
18
 
7
19
  - `Filesystem Ordering`: Sorts generated directory surfaces by visible directories, hidden directories, visible files, then hidden files, with alphabetical ordering inside each category before fixed ten-entry pagination.
package/README.md CHANGED
@@ -192,7 +192,7 @@ Voice notes, audio, images, PDFs, and other media can pass through configured in
192
192
 
193
193
  ### Buttons And Callbacks
194
194
 
195
- Assistant replies can include top-level hidden `telegram_button` comments using a JSON object, JSON matrix, or compact double-quoted attributes; `telegram_buttons` is a plural alias. In a matrix, top-level objects become full-width rows while nested arrays group one to three buttons horizontally. Prefer one array comment for multiple buttons. Buttons use `label` plus `prompt`, or the compact `value` key when both are identical. The action marker is colon-free for every payload form. The bridge strips the comments from visible text, renders inline buttons, and routes callbacks back into Pi as queued prompts or extension-owned callback actions. Button-only replies receive the standard `☑️ **Choose an option:**` heading as automatic visible fallback text. Once a generated prompt button is accepted, only that exact button switches to its optional `selected_style` (`primary` blue by default, `success` green, or `danger` red) without altering its agent-authored label or emoji; every style still queues the selected prompt.
195
+ Assistant replies can include top-level hidden `telegram_button` comments using a JSON object, JSON matrix, or compact double-quoted attributes; `telegram_buttons` is a plural alias. In a matrix, top-level objects become full-width rows while nested arrays group one to five buttons horizontally. Prefer one array comment for multiple buttons. Buttons use `label` plus `prompt`, or the compact `value` key when both are identical. The action marker is colon-free for every payload form. The bridge strips the comments from visible text, renders inline buttons, and routes callbacks back into Pi as queued prompts or extension-owned callback actions. Button-only replies receive the standard `☑️ **Choose an option:**` heading as automatic visible fallback text. Once a generated prompt button is accepted, only that exact button switches to its optional `selected_style` (`primary` blue by default, `success` green, or `danger` red) without altering its agent-authored label or emoji; every style still queues the selected prompt.
196
196
 
197
197
  ### Threaded Mode And Multi-Instance Bus
198
198
 
@@ -327,7 +327,7 @@ Outbound files staged during an active Telegram turn are delivered after that tu
327
327
  Assistant-authored final-message actions use hidden top-level comments with colon-free markers; colon-prefixed payloads are rejected:
328
328
 
329
329
  - `telegram_voice` accepts a JSON object or double-quoted HTML-like attributes and creates voice reply artifacts through configured outbound handlers, programmatic voice handlers, or registered synthesis providers.
330
- - `telegram_button` accepts a JSON object, JSON matrix, or double-quoted attributes; `telegram_buttons` aliases the same parser. Each top-level matrix object creates one full-width row, while a nested array groups one to three buttons horizontally; every callback enqueues its configured prompt text as a normal Telegram prompt turn.
330
+ - `telegram_button` accepts a JSON object, JSON matrix, or double-quoted attributes; `telegram_buttons` aliases the same parser. Each top-level matrix object creates one full-width row, while a nested array groups one to five buttons horizontally; every callback enqueues its configured prompt text as a normal Telegram prompt turn.
331
331
 
332
332
  Preview delivery strips top-level action comments before streaming draft Markdown. Comments inside code fences, quotes, lists, or indented examples stay literal.
333
333
 
@@ -362,7 +362,7 @@ Complete intermediate assistant text blocks from Telegram-originated activity ar
362
362
 
363
363
  `assistant.activity` is an independent bridge-owned projection over normalized Activity events. Each process reloads the shared file-backed setting at `agent-start` before activity admission, so multi-instance mode cannot continue projecting a stale broader process-local selection. Omitted values resolve to `verbose`, while invalid values fail closed to `quiet`; `thinking` and `tools` select one technical class, while `verbose` enables both. Provider-exposed thinking uses persistent ordinary HTML containing only a standard expandable blockquote with a bounded redacted latest-text window and inline Markdown rendered as Telegram HTML. Completed executed tools use native Rich Messages: each closed `<Tool>: <status>` root details node renders snake-case names as title words while preserving an uppercase two- or three-letter repeated prefix per word, then the native disclosure chevron reveals an open-by-default `arguments` child plus closed retained `update N` and `result`/`error` child details with lowercase monospaced, marker-free summaries and JSON pre blocks; known-safe Rich rejections fall back to the previous HTML disclosure. The projection captures the exact target and transport stamp at activity admission, serializes updates, preserves tool-start order, closes coalescing across assistant/thinking boundaries, bounds retained text/update memory plus edit frames and message/tool size, disables previews and HTTP(S) auto-link recognition inside technical evidence, and never replays a possibly committed send. Session generations own independent queues, so replacement drops queued old work without waiting on an old call. Both proactive prose and active-turn final delivery wait for the admitted activity queue inside their extension-owned delivery tasks, preserving technical-before-semantic ordering without delaying Pi lifecycle completion. Settlement, replacement, disconnect, failure, or stale authority clears only local ownership; already-sent activity messages remain in chat.
364
364
 
365
- Telegram prompt guidance is context- and authority-aware. The package and source-checkout extension both contribute `telegram-bridge` plus the optional `generated-control-surface` Skill through Pi resource discovery. The latter treats `interface = f(state, capabilities, intent)` as a renderer-neutral primitive, compiling transient evidence-backed controls over domain-owned workflows, systems, navigation, supervision, and decisions without creating parallel application state. Its filesystem adapter reserves the first full-width row for parent traversal outside root, places available Previous/Next controls together in one compact row immediately afterward, orders visible directories, hidden directories, visible files, and hidden files alphabetically within each category before fixed ten-entry pagination, renders path/range metadata as stacked status-style key-value rows instead of middle-dot prose, emits the complete Telegram control set through one JSON-matrix action, suppresses duplicate plain/monospaced listings and default Refresh unless user preference overrides presentation, and retains an ordinary numbered fallback when buttons are unavailable. Only an exact direct owner or live registered follower exposes the two pi-telegram delivery tools, their active-tool metadata, and the compact routing suffix. Disconnect or authority loss removes those tool surfaces for subsequent requests without touching foreign tools; reconnect/recovery restores only the pi-telegram subset that was active before suspension, including across same-process reload. Telegram-originated turns route to the stable Skill contract and retain dynamic blocks such as `[voice] delivery: automatic voice`; the Skill and public documentation own syntax, target routing, Threaded Mode behavior, and diagnostics.
365
+ Telegram prompt guidance is context- and authority-aware. The package and source-checkout extension both contribute `telegram-bridge` plus the optional `generated-control-surface` Skill through Pi resource discovery. The latter treats `interface = f(state, capabilities, intent)` as a renderer-neutral primitive, compiling transient evidence-backed controls over domain-owned workflows, systems, navigation, supervision, and decisions without creating parallel application state. Repeated controls carry the smallest sufficient action delta when visible conversation is unambiguous; larger or error-prone state moves to a deterministic task-owned Markdown artifact, correctness-sensitive transitions move to a small domain-owned transition implementation, and repeated clicks are adjudicated against current state rather than stale button appearance. Its filesystem adapter reserves the first full-width row for parent traversal outside root, places available Previous/Next controls together in one compact row immediately afterward, orders visible directories, hidden directories, visible files, and hidden files alphabetically within each category before fixed ten-entry pagination, renders path/range metadata as stacked status-style key-value rows instead of middle-dot prose, emits the complete Telegram control set through one JSON-matrix action, suppresses duplicate plain/monospaced listings and default Refresh unless user preference overrides presentation, and retains an ordinary numbered fallback when buttons are unavailable. Only an exact direct owner or live registered follower exposes the two pi-telegram delivery tools, their active-tool metadata, and the compact routing suffix. Disconnect or authority loss removes those tool surfaces for subsequent requests without touching foreign tools; reconnect/recovery restores only the pi-telegram subset that was active before suspension, including across same-process reload. Telegram-originated turns route to the stable Skill contract and retain dynamic blocks such as `[voice] delivery: automatic voice`; the Skill and public documentation own syntax, target routing, Threaded Mode behavior, and diagnostics.
366
366
 
367
367
  ## In-Flight Model Switching
368
368
 
package/docs/outbound.md CHANGED
@@ -166,7 +166,7 @@ Rules:
166
166
  - A colon after either button marker is rejected so every payload form shares one unambiguous action marker.
167
167
  - Use `label` plus `prompt`, or the compact `value` key when both strings are identical. Explicit `label` or `prompt` takes precedence over its `value` fallback. Use JSON with `\n` escapes for multiline prompts.
168
168
  - The opening marker must start at column zero on a top-level line outside fenced code, quotes, lists, and indented examples; otherwise it remains literal Markdown.
169
- - Prefer one JSON array comment for multiple buttons. Each top-level object becomes one full-width inline-keyboard row in source order; a nested array groups one to three button objects into one horizontal row. Empty rows, rows above three buttons, and deeper nesting are rejected. Repeated singular comments remain valid.
169
+ - Prefer one JSON array comment for multiple buttons. Each top-level object becomes one full-width inline-keyboard row in source order; a nested array groups one to five button objects into one horizontal row. Empty rows, rows above five buttons, and deeper nesting are rejected. Repeated singular comments remain valid.
170
170
  - Button actions are stored in memory with short `callback_data`; Telegram never sees the full prompt in the button payload.
171
171
  - After Telegram accepts a generated button callback as a queued prompt, the bridge changes that exact button to its configured selection style without changing agent-authored text or emoji. Set `selected_style` to `primary` (blue), `success` (green), or `danger` (red); omitted or invalid values fall back to `primary`. The style never suppresses queue admission. Other choices stay visually unchanged and remain available; the callback acknowledgement remains the fallback on clients that do not render button styles.
172
172
  - When generated button markup is the entire assistant reply, the bridge supplies the standard `☑️ **Choose an option:**` heading as visible message text so Telegram has a message to which it can attach the inline keyboard.
@@ -65,7 +65,7 @@ This command surface is a mobile companion subset, not a raw terminal-command br
65
65
  - `telegram_message(text, chat_id?, thread_id?)` sends a direct Telegram Markdown message when this Pi instance owns `/telegram-connect` or is registered with the multi-instance bus. During an active Telegram turn, omitted targeting and an explicit target equal to that turn are rejected so the ordinary final-reply path remains the sole current-target response; an explicit different chat/thread target remains allowed for requested cross-target delivery. Outside active turns, paired/default local/TUI delivery remains unchanged. Top-level `telegram_button` comments inside `text` are parsed with the same planner used for normal replies and attached to that message; buttons are never standalone Telegram messages.
66
66
  - The bundled `telegram-bridge` Skill owns action syntax, target routing, Threaded Mode, formatting, and profile-specific debugging guidance. The regular prompt routes applicable turns to that Skill. `telegram_attach` and `telegram_message` remain registered but are model-active only while this instance owns direct transport or holds a live follower registration; disconnect/loss suppresses their schemas and prompt metadata, and recovery restores only the operator's previously active pi-telegram subset.
67
67
  - `telegram_voice` hidden comments request Telegram-native voice delivery through either a JSON object or double-quoted attributes. Equivalent `text` or `value` supplies the spoken payload; explicit `text` takes precedence.
68
- - `telegram_button` hidden comments create inline buttons whose taps enqueue prompts. One marker accepts a JSON object, JSON matrix, or double-quoted attributes; `telegram_buttons` is an exact plural alias. Top-level matrix objects become full-width rows, while nested arrays group one to three buttons horizontally. Prefer one array comment for multiple buttons. Use `label` plus `prompt`, or `value` when both strings are identical. Action markers are colon-free; colon-prefixed payloads are rejected. Use top-level column-zero comments outside code, quotes, lists, and indented examples; do not emit standalone button actions.
68
+ - `telegram_button` hidden comments create inline buttons whose taps enqueue prompts. One marker accepts a JSON object, JSON matrix, or double-quoted attributes; `telegram_buttons` is an exact plural alias. Top-level matrix objects become full-width rows, while nested arrays group one to five buttons horizontally. Prefer one array comment for multiple buttons. Use `label` plus `prompt`, or `value` when both strings are identical. Action markers are colon-free; colon-prefixed payloads are rejected. Use top-level column-zero comments outside code, quotes, lists, and indented examples; do not emit standalone button actions.
69
69
 
70
70
  Prompt guidance is context-aware: local/TUI prompts see only explicit direct-delivery guidance, while Telegram-originated turns receive the full action-comment syntax and phone-width output contract.
71
71
 
@@ -225,7 +225,7 @@ export function parseTelegramActionPayloadRows(
225
225
  if (
226
226
  !Array.isArray(entry) ||
227
227
  entry.length === 0 ||
228
- entry.length > 3 ||
228
+ entry.length > 5 ||
229
229
  !entry.every(isTelegramActionPayload)
230
230
  ) {
231
231
  return undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llblab/pi-telegram",
3
- "version": "0.33.2",
3
+ "version": "0.34.1",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -41,7 +41,7 @@ Console programs are one capability source, not the defining boundary. Use the r
41
41
 
42
42
  - Generate controls from current evidence, an explicit contract, or clearly labeled conversational state.
43
43
  - Keep domain state with its real owner; never invent a shadow navigation tree, task database, or application session.
44
- - Make every button prompt self-contained: identify the target, intended result, relevant constraints, and freshness requirement.
44
+ - Make every button prompt minimally sufficient for a truthful continuation: reuse unambiguous visible conversational context, but include stable target, state, constraint, or freshness identity whenever omission could change the action.
45
45
  - Treat a click as an ordinary user request subject to the same authority, validation, and safety rules as typed text.
46
46
  - Never infer permission for destructive, privileged, credential-bearing, external, or irreversible work merely because a button exists.
47
47
  - Do not encode secrets, hidden reasoning, credentials, private keys, tokens, cookies, wallet material, or sensitive content in labels or prompts.
@@ -118,7 +118,17 @@ Re-check mutable targets immediately before execution. Access denial never autho
118
118
 
119
119
  ## Prompt Buttons
120
120
 
121
- Use the transport's canonical prompt-button syntax. For pi-telegram, one top-level `telegram_button` comment accepts one JSON object, double-quoted attributes, or a JSON matrix. A top-level object becomes one full-width row; a nested array groups one to three objects into one compact horizontal row. Prefer one array comment for multiple controls instead of repeating the marker; `telegram_buttons` is a plural alias, not a different format. Use compact rows only when the controls form one coherent peer group such as Previous/Next, approval alternatives, or view modes; keep ordinary actions full-width.
121
+ Use the transport's canonical prompt-button syntax. For pi-telegram, one top-level `telegram_button` comment accepts one JSON object, double-quoted attributes, or a JSON matrix. A top-level object becomes one full-width row; a nested array groups one to five objects into one compact horizontal row. Prefer one array comment for multiple controls instead of repeating the marker; `telegram_buttons` is a plural alias, not a different format. Use compact rows only when the controls form one coherent peer group such as Previous/Next, approval alternatives, or view modes; keep ordinary actions full-width.
122
+
123
+ Treat the five-wide matrix as an interaction primitive when spatial position carries meaning and acting through the surface communicates better than prose. Five-wide rows are proven usable with short, distinct labels; use fewer columns or full-width rows when labels need explanation, wrap ambiguously, or lose meaning without prose. Preserve the ordinary admission test: proactively offer an interactive surface even when the user did not request buttons when it materially reduces effort or demonstrates an available capability, but do not manufacture decorative interaction.
124
+
125
+ ### Interaction State And Prompt Compression
126
+
127
+ - Encode the smallest sufficient action delta in repeated controls. When the visible surface and immediately preceding conversation establish one unambiguous state, a coordinate, symbol, identifier, or short verb can be the entire prompt; do not duplicate the same board, form, or selection state into every button payload.
128
+ - Keep compact prompts semantically closed over their context. If delivery may be delayed, reordered, routed elsewhere, or separated from the state projection, add a stable target or state identity rather than copying a large volatile snapshot.
129
+ - Keep trivial interaction state in the visible conversation. When state becomes too large, long-lived, or error-prone for reliable conversational reconstruction, persist a small human-auditable Markdown state artifact at a deterministic task-owned path and render from it. The artifact belongs to the underlying task or domain, not to this Skill as shadow application state.
130
+ - When transition rules are non-trivial or correctness-sensitive, use a small deterministic state-transition owner—script, module, tool, or existing domain API—that validates `current state + admitted action → next state`; let the model compile the surface from its result instead of informally simulating every transition. Do not create code or files for a trivial one-step interaction.
131
+ - Treat repeated clicks against current state, not stale button appearance. If an action is already consumed or unavailable, keep state unchanged and say so briefly. Preserve an occupied or selected button when spatial layout matters, using its label or selected style as the visual state; omit unavailable controls when layout does not matter. Transport-level disabled buttons are optional, not assumed.
122
132
 
123
133
  ```html
124
134
  <!-- telegram_button {"label":"🔍 Inspect run","prompt":"Inspect Run run:example read-only, summarize its current status and latest material evidence, then regenerate relevant supervision controls."} -->
@@ -128,8 +138,8 @@ Use the transport's canonical prompt-button syntax. For pi-telegram, one top-lev
128
138
  Button prompts must:
129
139
 
130
140
  - Preserve the user's language.
131
- - Name exact targets where possible.
132
- - Express one coherent next intent.
141
+ - Name exact targets when visible context does not make them unambiguous.
142
+ - Express one coherent next intent with the shortest sufficient action delta.
133
143
  - Carry material safety and scope restrictions.
134
144
  - Request fresh inspection when state may have changed.
135
145
  - Avoid embedding volatile output that should be rediscovered.
@@ -59,7 +59,7 @@ Button forms:
59
59
  <!-- telegram_buttons [[{"value":"Approve"},{"value":"Reject"}]] -->
60
60
  ```
61
61
 
62
- - `telegram_button` accepts one JSON object, a JSON matrix, or double-quoted attributes; `telegram_buttons` is an exact plural alias. In a matrix, each top-level object becomes a full-width row and each nested array groups one to three buttons into one horizontal row. Prefer one array comment for multiple buttons. Keep the complete action in one top-level comment and encode JSON line breaks as `\n`.
62
+ - `telegram_button` accepts one JSON object, a JSON matrix, or double-quoted attributes; `telegram_buttons` is an exact plural alias. In a matrix, each top-level object becomes a full-width row and each nested array groups one to five buttons into one horizontal row. Prefer one array comment for multiple buttons. Keep the complete action in one top-level comment and encode JSON line breaks as `\n`.
63
63
  - Use `label` plus a self-contained `prompt`, or non-empty `value` when both are identical.
64
64
  - Optional `selected_style` is `primary` (default), `success`, or `danger`; style never suppresses prompt admission.
65
65
  - If button comments form the whole reply, the bridge supplies the standard choice heading.