This commit is contained in:
wassname
2026-04-19 16:08:23 +08:00
parent 5aa37b7a99
commit c2d25b31fe
7 changed files with 41 additions and 21 deletions
+1
View File
@@ -2,6 +2,7 @@
## Current
- `[Trace Visibility]` Added `/trace` command and status-menu inline button to toggle visibility of thinking and tool-call blocks in Telegram replies. When enabled (default), streaming previews show compact one-line trace summaries and final replies include quoted trace detail. Impact: operators can see what the model is thinking and which tools it calls without leaving Telegram.
- `[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.
- `[Docs]` Added short responsibility header comments to every project `.ts` file. Impact: file boundaries are easier to understand while navigating the growing `/lib` split.
- `[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.
+5 -1
View File
@@ -6,6 +6,9 @@ Telegram DM bridge for pi.
This repository is a fork of the original [`badlogic/pi-telegram`](https://github.com/badlogic/pi-telegram).
It started from upstream commit [`cb34008460b6c1ca036d92322f69d87f626be0fc`](https://github.com/badlogic/pi-telegram/commit/cb34008460b6c1ca036d92322f69d87f626be0fc) and has since diverged substantially.
- then llblab did a bunch of work in llblab
- then wassname:
- show tool calls and thinking
## Start Here
@@ -18,7 +21,7 @@ It started from upstream commit [`cb34008460b6c1ca036d92322f69d87f626be0fc`](htt
Compared to upstream commit `cb34008`, this fork significantly extends and hardens the extension.
- Better Telegram control UI, including an improved `/status` view with inline buttons for model and thinking selection
- Better Telegram control UI, including an improved `/status` view with inline buttons for model and thinking selection, and trace visibility toggle for thinking/tool-call blocks
- Interactive model selection improvements, including scoped model lists, thinking-level control for reasoning-capable models, and in-flight restart on a newly selected model for active Telegram-owned runs
- Queueing and interaction upgrades, including queue previews, reaction-based prioritization/removal, media-group handling, high-priority control actions, and safer dispatch behavior
- Markdown and reply rendering improvements, with richer formatting support, narrow-client-friendly table/list rendering, quote compatibility fixes, and multiple fixes for incorrect Telegram rendering and chunking edge cases
@@ -112,6 +115,7 @@ Additional fork-specific controls:
- `/status` now has a richer view with inline buttons for model and thinking controls, and joins the high-priority control queue when pi is busy
- `/model` opens the interactive model selector, applies idle selections immediately, joins the high-priority control queue when pi is busy, and can restart the active Telegram-owned run on the newly selected model, waiting for the current tool call to finish when needed
- `/compact` starts session compaction when pi and the Telegram queue are idle
- `/trace` toggles visibility of thinking and tool-call blocks in Telegram replies (on by default)
- Queue reactions: `👍` prioritizes a waiting turn, `👎` removes it
### Send text
+9 -3
View File
@@ -30,9 +30,9 @@ Current runtime areas include:
- Telegram attachment queueing and delivery helpers in `/lib/attachments.ts`
- Telegram tool, command, and lifecycle-hook registration helpers in `/lib/registration.ts`
- Setup/token prompt helpers in `/lib/setup.ts`
- Markdown and Telegram message rendering helpers in `/lib/rendering.ts`
- Status rendering helpers in `/lib/status.ts`
- Menu/model-resolution, menu-state construction, 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, interface-polished callback effect ports, status-thinking callback handling, and UI helpers in `/lib/menu.ts`
- Markdown, Telegram message rendering, and trace display block rendering helpers in `/lib/rendering.ts`
- Status rendering helpers (including trace visibility indicator) in `/lib/status.ts`
- Menu/model-resolution, menu-state construction, 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, interface-polished callback effect ports, status-thinking callback handling, trace-toggle callback handling, and UI helpers in `/lib/menu.ts`
- Model-switch guard, continuation, and restart helpers in `/lib/model-switch.ts`
- Telegram API-bound reply transport wiring and broader event-side orchestration in `index.ts`
- Additional domains can be extracted into `/lib/*.ts` as the bridge grows, while keeping `index.ts` as the single entrypoint
@@ -103,6 +103,12 @@ Key rules:
The renderer is a Telegram-specific formatter, not a general Markdown engine, so rendering changes should be treated as regression-prone.
### Trace Visibility
When trace visibility is on (default), thinking blocks and tool-call blocks from the assistant are included in both streaming previews and final replies. During streaming, trace blocks appear as compact one-line summaries (e.g. `🧠 Thinking...`, `🔧 tool_name`). In the final transcript, they render as quoted Markdown blocks with more detail.
Trace visibility is toggled per session via `/trace` or the inline button on the `/status` menu. The state is stored in `traceVisible` (boolean, default `true`) and flows through the rendering helpers in `/lib/rendering.ts`.
## Streaming And Delivery
During generation, the bridge streams previews back to Telegram.
+13
View File
@@ -2022,6 +2022,12 @@ export default function (pi: ExtensionAPI) {
onMessageStart: async (event, _ctx) => {
const nextEvent = event as { message: AgentMessage };
if (!activeTelegramTurn || !isAssistantMessage(nextEvent.message)) return;
{
const rawContent = (nextEvent.message as unknown as Record<string, unknown>).content;
const rawBlocks = Array.isArray(rawContent) ? rawContent : [];
const blockTypes = rawBlocks.map((b: Record<string, unknown>) => b?.type ?? "unknown");
console.log(`${TELEGRAM_PREFIX} [trace-debug] messageStart role=${(nextEvent.message as unknown as Record<string, unknown>).role} blockTypes=${JSON.stringify(blockTypes)}`);
}
if (traceVisible) {
if (activeTelegramMessageBlocks.length > 0) {
activeTelegramTraceBlocks.push(...activeTelegramMessageBlocks);
@@ -2056,6 +2062,13 @@ export default function (pi: ExtensionAPI) {
previewState = createPreviewState();
}
if (traceVisible) {
const rawContent = (nextEvent.message as unknown as Record<string, unknown>).content;
const rawBlocks = Array.isArray(rawContent) ? rawContent : [];
const blockTypes = rawBlocks.map((b: Record<string, unknown>) => b?.type ?? "unknown");
if (blockTypes.some((t: string) => t !== "text")) {
console.log(`${TELEGRAM_PREFIX} [trace-debug] message block types: ${JSON.stringify(blockTypes)}`);
console.log(`${TELEGRAM_PREFIX} [trace-debug] non-text blocks: ${JSON.stringify(rawBlocks.filter((b: Record<string, unknown>) => b?.type !== "text").map((b: Record<string, unknown>) => ({ type: b?.type, keys: Object.keys(b ?? {}) })))}`);
}
activeTelegramMessageBlocks = getMessageBlocks(nextEvent.message);
previewState.pendingText = buildTelegramAssistantPreviewText(
getActiveTracePreviewBlocks(),
+8 -14
View File
@@ -55,21 +55,15 @@ export function buildTelegramAssistantPreviewText(
traceVisible: boolean,
): string {
const sections: string[] = [];
const text = blocks
.filter((block): block is Extract<TelegramAssistantDisplayBlock, { type: "text" }> => block.type === "text")
.map((block) => block.text)
.join("")
.trim();
if (text) {
sections.push(text);
}
if (traceVisible) {
const traceLines = blocks
.map(renderTracePreviewLine)
.filter((line): line is string => !!line);
if (traceLines.length > 0) {
sections.push(traceLines.join("\n"));
for (const block of blocks) {
if (block.type === "text") {
const trimmed = block.text.trim();
if (trimmed) sections.push(trimmed);
continue;
}
if (!traceVisible) continue;
const line = renderTracePreviewLine(block);
if (line) sections.push(line);
}
return sections.join("\n\n").trim();
}
+1 -1
View File
@@ -21,7 +21,7 @@
"url": "https://github.com/llblab/pi-telegram/issues"
},
"scripts": {
"test": "node --experimental-strip-types --test tests/*.test.ts"
"test": "node --experimental-strip-types --test --test-force-exit tests/*.test.ts"
},
"publishConfig": {
"access": "public"
+4 -2
View File
@@ -27,8 +27,10 @@ test("Assistant trace helpers build compact previews and fuller transcripts", ()
assert.equal(
buildTelegramAssistantPreviewText(blocks as never, true),
[
"Answer intro\n\nFinal answer.",
'[thinking] Need to inspect the config first.\n[tool] read_config {"path":"config.json"}',
"Answer intro",
"[thinking] Need to inspect the config first.",
'[tool] read_config {"path":"config.json"}',
"Final answer.",
].join("\n\n"),
);
assert.equal(