mirror of
https://github.com/wassname/pi-telegram.git
synced 2026-06-27 16:46:21 +08:00
fix: defer non-text block emission until message completes
Tool call blocks (and thinking) arrive in streaming updates before their
args are populated — emitting immediately gave `Tool call bash {}`.
Buffer non-text blocks during onMessageUpdate; flush them in
onMessageStart (previous message now complete, args fully populated)
and onAgentEnd (single-message turns that never trigger onMessageStart).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -403,7 +403,7 @@ export default function (pi: ExtensionAPI) {
|
|||||||
let setupInProgress = false;
|
let setupInProgress = false;
|
||||||
let previewState: TelegramPreviewState | undefined;
|
let previewState: TelegramPreviewState | undefined;
|
||||||
let displayMode: DisplayMode = "compact";
|
let displayMode: DisplayMode = "compact";
|
||||||
let emittedNonTextBlockCount = 0;
|
let pendingNonTextBlocks: TelegramAssistantDisplayBlock[] = [];
|
||||||
let draftSupport: "unknown" | "supported" | "unsupported" = "unknown";
|
let draftSupport: "unknown" | "supported" | "unsupported" = "unknown";
|
||||||
let nextDraftId = 0;
|
let nextDraftId = 0;
|
||||||
let currentTelegramModel: Model<any> | undefined;
|
let currentTelegramModel: Model<any> | undefined;
|
||||||
@@ -2042,7 +2042,7 @@ export default function (pi: ExtensionAPI) {
|
|||||||
}
|
}
|
||||||
if (startPlan.activeTurn) {
|
if (startPlan.activeTurn) {
|
||||||
activeTelegramTurn = { ...startPlan.activeTurn };
|
activeTelegramTurn = { ...startPlan.activeTurn };
|
||||||
emittedNonTextBlockCount = 0;
|
pendingNonTextBlocks = [];
|
||||||
previewState = createPreviewState();
|
previewState = createPreviewState();
|
||||||
startTypingLoop(ctx);
|
startTypingLoop(ctx);
|
||||||
}
|
}
|
||||||
@@ -2074,7 +2074,12 @@ export default function (pi: ExtensionAPI) {
|
|||||||
await finalizePreview(activeTelegramTurn.chatId);
|
await finalizePreview(activeTelegramTurn.chatId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
emittedNonTextBlockCount = 0;
|
// Flush non-text blocks from the completed previous message now that args are fully populated
|
||||||
|
for (const block of pendingNonTextBlocks) {
|
||||||
|
const msg = renderBlockMessage(block, displayMode);
|
||||||
|
if (msg) void sendMarkdownReply(activeTelegramTurn.chatId, activeTelegramTurn.replyToMessageId, msg);
|
||||||
|
}
|
||||||
|
pendingNonTextBlocks = [];
|
||||||
previewState = createPreviewState();
|
previewState = createPreviewState();
|
||||||
},
|
},
|
||||||
onMessageUpdate: async (event, _ctx) => {
|
onMessageUpdate: async (event, _ctx) => {
|
||||||
@@ -2083,17 +2088,10 @@ export default function (pi: ExtensionAPI) {
|
|||||||
if (!previewState) previewState = createPreviewState();
|
if (!previewState) previewState = createPreviewState();
|
||||||
|
|
||||||
const allBlocks = getMessageBlocks(nextEvent.message);
|
const allBlocks = getMessageBlocks(nextEvent.message);
|
||||||
const nonTextBlocks = allBlocks.filter((b) => b.type !== "text");
|
|
||||||
|
|
||||||
// Emit each new non-text block as its own Telegram message
|
// Buffer non-text blocks; emit after the message completes (in onMessageStart / onAgentEnd)
|
||||||
for (let i = emittedNonTextBlockCount; i < nonTextBlocks.length; i++) {
|
// so tool_call blocks have their args fully populated before being sent
|
||||||
const block = nonTextBlocks[i]!;
|
pendingNonTextBlocks = allBlocks.filter((b) => b.type !== "text");
|
||||||
const msg = renderBlockMessage(block, displayMode);
|
|
||||||
if (msg) {
|
|
||||||
void sendMarkdownReply(activeTelegramTurn.chatId, activeTelegramTurn.replyToMessageId, msg);
|
|
||||||
}
|
|
||||||
emittedNonTextBlockCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stream text content in the preview message
|
// Stream text content in the preview message
|
||||||
const textContent = allBlocks
|
const textContent = allBlocks
|
||||||
@@ -2111,7 +2109,6 @@ export default function (pi: ExtensionAPI) {
|
|||||||
currentAbort = undefined;
|
currentAbort = undefined;
|
||||||
stopTypingLoop();
|
stopTypingLoop();
|
||||||
activeTelegramTurn = undefined;
|
activeTelegramTurn = undefined;
|
||||||
emittedNonTextBlockCount = 0;
|
|
||||||
activeTelegramToolExecutions = 0;
|
activeTelegramToolExecutions = 0;
|
||||||
pendingTelegramModelSwitch = undefined;
|
pendingTelegramModelSwitch = undefined;
|
||||||
telegramTurnDispatchPending = false;
|
telegramTurnDispatchPending = false;
|
||||||
@@ -2145,6 +2142,13 @@ export default function (pi: ExtensionAPI) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Flush any non-text blocks from the final message (single-message turns never trigger onMessageStart)
|
||||||
|
for (const block of pendingNonTextBlocks) {
|
||||||
|
const msg = renderBlockMessage(block, displayMode);
|
||||||
|
if (msg) void sendMarkdownReply(turn.chatId, turn.replyToMessageId, msg);
|
||||||
|
}
|
||||||
|
pendingNonTextBlocks = [];
|
||||||
|
|
||||||
// Finalize the streaming text preview (only for normal completions, not abort/empty)
|
// Finalize the streaming text preview (only for normal completions, not abort/empty)
|
||||||
if (endPlan.kind === "text") {
|
if (endPlan.kind === "text") {
|
||||||
const finalText = previewState?.pendingText.trim() || assistant.text?.trim();
|
const finalText = previewState?.pendingText.trim() || assistant.text?.trim();
|
||||||
|
|||||||
Reference in New Issue
Block a user