@llblab/pi-telegram 0.27.5 → 0.27.7

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
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.27.7: Bidirectional Thread Messaging Hotfix
4
+
5
+ - `Follower-to-Leader Agent Turns`: Internal cross-instance turns now bypass ownership lookup for the already-sent Telegram message id while retaining that id as reply context. Impact: a follower targeting the leader reaches the leader queue instead of ownership routing the synthetic turn back to the sending follower.
6
+
7
+ ## 0.27.6: Autonomous Follow-Up Delivery Hotfix
8
+
9
+ - `Follow-Up Finals`: Completed public assistant blocks from unclassified Pi turns now follow the default-enabled Proactive Push path, alongside explicitly local and autonomous turns. Impact: actor terminal follow-ups and comparable extension-triggered continuations no longer show reasoning/activity in Telegram while silently dropping the final answer.
10
+ - `Safety and Coverage`: Telegram-originated finals remain exclusively owned by active-turn settlement, while unclassified output still requires Proactive Push policy plus fresh direct/follower transport authority. Regression coverage proves unclassified finals deliver once when enabled and remain suppressed when disabled.
11
+
3
12
  ## 0.27.5: Cross-Instance Agent Turns
4
13
 
5
14
  - `Live Thread Addressing`: `telegram_message` now accepts `thread` as a case-insensitive live thread name or numeric id. Resolution uses leader-owned live registrations and rejects unknown, ambiguous, same-target, offline, and cross-chat destinations before visible Telegram mutation.
package/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  It is a **runtime adapter**, not a remote terminal. Start or supervise work in the Pi TUI, then continue from Telegram while away from the keyboard. Each Telegram destination follows a running Pi instance and sends prompts into that instance's currently active session; it is not permanently bound to one session file or session identity. The bridge preserves Pi session semantics instead of pretending Telegram is a PTY, shell, process launcher, or session browser. That boundary is the product: Telegram gets safe runtime handles, not raw terminal power.
10
10
 
11
- Every completed intermediate commentary block from a Telegram-originated turn is delivered once as its own message before the existing final reply. Proactive push is enabled by default for local and autonomous work: `assistant.proactivePush` projects visible checkpoints and the final answer to the authorized Telegram target once and in order; set it explicitly to `false` to disable only that local/autonomous projection. Neither path mirrors local prompts, thinking, tool traffic, token deltas, or stale-generation work. The separate `Activity` setting defaults to `verbose` so new installations discover collapsed provider-exposed thinking and tool evidence immediately; operators can narrow it to one class or choose `quiet`. See [Outbound](docs/outbound.md#public-assistant-output) and the [configuration reference](docs/public-api.md#configuration-api).
11
+ Every completed intermediate commentary block from a Telegram-originated turn is delivered once as its own message before the existing final reply. Proactive push is enabled by default for local, autonomous, and unclassified extension follow-up work: `assistant.proactivePush` projects visible checkpoints and the final answer to the authorized Telegram target once and in order; set it explicitly to `false` to disable only that local/autonomous projection. Neither path mirrors local prompts, thinking, tool traffic, token deltas, or stale-generation work. The separate `Activity` setting defaults to `verbose` so new installations discover collapsed provider-exposed thinking and tool evidence immediately; operators can narrow it to one class or choose `quiet`. See [Outbound](docs/outbound.md#public-assistant-output) and the [configuration reference](docs/public-api.md#configuration-api).
12
12
 
13
13
  This repository is an actively maintained fork of [`badlogic/pi-telegram`](https://github.com/badlogic/pi-telegram). It started from upstream commit [`cb34008`](https://github.com/badlogic/pi-telegram/commit/cb34008460b6c1ca036d92322f69d87f626be0fc) and has since diverged substantially.
14
14
 
package/docs/activity.md CHANGED
@@ -236,7 +236,7 @@ The Delivery API independently serializes concrete Telegram operations per targe
236
236
 
237
237
  ### Core assistant-output projection
238
238
 
239
- Activity's built-in assistant-output projection uses the same normalized `assistant-segment` boundary exposed to public handlers. For `telegram` activity it always projects complete `intermediate` commentary to the immutable originating target, while final and terminal-partial segments remain with active-turn settlement. For `local` or `autonomous` activity, `assistant.proactivePush` enables projection of every completed public block, including intermediate commentary/checkpoints and the final block. It never projects text token deltas, reasoning events, tool events or payloads, unknown-source activity, or empty text.
239
+ Activity's built-in assistant-output projection uses the same normalized `assistant-segment` boundary exposed to public handlers. For `telegram` activity it always projects complete `intermediate` commentary to the immutable originating target, while final and terminal-partial segments remain with active-turn settlement. For `local`, `autonomous`, or unclassified extension follow-up activity, `assistant.proactivePush` enables projection of every completed public block, including intermediate commentary/checkpoints and the final block. This closes actor-follow-up delivery without reclassifying it as direct user input. It never projects text token deltas, reasoning events, tool events or payloads, or empty text.
240
240
 
241
241
  The projection does not delay Activity dispatch or Pi lifecycle. Its ordered admission tail deduplicates normalized event identity, while existing routing and outbound owners revalidate the immutable admission-time target, profile/token transport generation, direct leader epoch or follower registration generation, and session generation immediately before each send. Active-turn final delivery waits for admitted commentary inside its existing background task. A replacement or stale owner drops queued work rather than rerouting it, and an already-started non-idempotent Bot API mutation follows the normal `commit-unknown` no-replay contract.
242
242
 
package/docs/outbound.md CHANGED
@@ -10,7 +10,7 @@ Text handlers use the portable [Command Template Standard](./command-templates.m
10
10
 
11
11
  Every completed `assistant-segment` with `placement: "intermediate"` from a Telegram-originated turn is delivered as its own message to the immutable originating target before the ordinary active-turn final reply. This commentary path always applies; `assistant.proactivePush` does not disable it. Final and terminal-partial Telegram segments remain owned by active-turn settlement so the final answer, voice, buttons, previews, and artifacts are not duplicated.
12
12
 
13
- Proactive projection defaults on for local and autonomous Pi work. With `assistant.proactivePush` omitted or set to `true`, every completed public block—including visible commentary/checkpoints and the final answer—is projected to the instance's authorized target in source order; set it explicitly to `false` to opt out of only this local/autonomous projection. Both paths consume normalized complete Activity segments rather than raw token deltas, reasoning, or tool traffic.
13
+ Proactive projection defaults on for local, autonomous, and unclassified extension follow-up Pi work. With `assistant.proactivePush` omitted or set to `true`, every completed public block—including visible commentary/checkpoints and the final answer—is projected to the instance's authorized target in source order; set it explicitly to `false` to opt out of only this local/autonomous projection. Both paths consume normalized complete Activity segments rather than raw token deltas, reasoning, or tool traffic.
14
14
 
15
15
  Projected blocks use `assistant.rendering` independently of voice policy. Rich mode sends native Rich Markdown and HTML mode keeps the established HTML renderer; projection does not synthesize voice or attach queued files merely because Rich rendering is active. Ordered admission revalidates the exact target, profile/token transport generation, leader epoch or follower registration generation, and session generation before each send. Active-turn final delivery waits for admitted commentary inside its existing background delivery task, preserving commentary-before-final order without blocking Pi lifecycle completion. A `commit-unknown` outcome never permits replay.
16
16
 
package/lib/activity.ts CHANGED
@@ -732,7 +732,9 @@ export function createTelegramAssistantOutputRuntime<TAuthority = undefined>(dep
732
732
  const admitted = new Set<string>();
733
733
  const isEligibleEvent = (event: TelegramAssistantSegmentEvent): boolean =>
734
734
  (event.source === "telegram" && event.placement === "intermediate") ||
735
- ((event.source === "local" || event.source === "autonomous") &&
735
+ ((event.source === "local" ||
736
+ event.source === "autonomous" ||
737
+ event.source === "unknown") &&
736
738
  deps.isEnabled());
737
739
 
738
740
  return {
@@ -11,6 +11,7 @@ import type {
11
11
  } from "./bus.ts";
12
12
  import type { TelegramRoutedMessage } from "./routing.ts";
13
13
  import type { TelegramTarget } from "./target.ts";
14
+ import { TELEGRAM_INTERNAL_AGENT_MESSAGE } from "./updates.ts";
14
15
 
15
16
  export interface TelegramAgentMessageRuntimeDeps<TContext, TUpdate> {
16
17
  instanceId: string;
@@ -110,7 +111,10 @@ export function createTelegramAgentMessageRuntime<TContext, TUpdate>(
110
111
  message_thread_id: target.threadId,
111
112
  text: `[agent|from-thread:${sourceLabel}]\n\n${input.message.text}`,
112
113
  } as TelegramRoutedMessage;
113
- await deps.handleUpdate({ message } as TUpdate, ctx);
114
+ await deps.handleUpdate(
115
+ { message, [TELEGRAM_INTERNAL_AGENT_MESSAGE]: true } as TUpdate,
116
+ ctx,
117
+ );
114
118
  },
115
119
  };
116
120
  }
package/lib/updates.ts CHANGED
@@ -303,9 +303,14 @@ export interface TelegramMessageReactionUpdated {
303
303
  new_reaction: TelegramReactionType[];
304
304
  }
305
305
 
306
+ export const TELEGRAM_INTERNAL_AGENT_MESSAGE = Symbol(
307
+ "telegram.internalAgentMessage",
308
+ );
309
+
306
310
  export interface TelegramUpdateFlow
307
311
  extends TelegramUpdateRouting, TelegramUpdateDeletion {
308
312
  message_reaction?: TelegramMessageReactionUpdated;
313
+ [TELEGRAM_INTERNAL_AGENT_MESSAGE]?: true;
309
314
  }
310
315
 
311
316
  export type TelegramUpdateFlowAction<
@@ -807,9 +812,17 @@ export async function executeTelegramUpdate<
807
812
  NonNullable<TUpdate["message"] | TUpdate["edited_message"]>
808
813
  >,
809
814
  ): Promise<void> {
815
+ const runtimeDeps = update[TELEGRAM_INTERNAL_AGENT_MESSAGE]
816
+ ? {
817
+ ...deps,
818
+ getMessageOwnership: undefined,
819
+ getTargetOwnership: undefined,
820
+ recordMessageOwnership: undefined,
821
+ }
822
+ : deps;
810
823
  await executeTelegramUpdatePlan(
811
824
  buildTelegramUpdateExecutionPlanFromUpdate(update, allowedUserId),
812
- deps,
825
+ runtimeDeps,
813
826
  );
814
827
  }
815
828
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llblab/pi-telegram",
3
- "version": "0.27.5",
3
+ "version": "0.27.7",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"