mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-02 09:11:34 +00:00
fix(telegram): surface draft stream delivery failures at warn level (#111065)
* fix(telegram): surface draft stream delivery failures at warn level
createTelegramDraftController wired the draft stream's warn callback to
logVerbose, so preview send/edit/cleanup failures ("telegram stream
preview failed: ...", "telegram stream preview cleanup failed: ...")
were only emitted when verbose logging was enabled. In the default
configuration a dying preview/draft stream left no operator-visible
trace: the bot just went quiet, especially in progress stream mode
where the activity window is the only delivery surface.
Route the warn callback through the telegram subsystem logger
(telegram/draft-stream) at warn level with lane, chatId, and threadId
context so draft delivery failures show up in default logs. The
verbose log callback is unchanged.
Co-authored-by: Claude <noreply@anthropic.com>
* test(telegram): simplify draft warning logger proof
Co-authored-by: Arseniy Palagin <valeradzigurda3@gmail.com>
* fix(telegram): emit draft terminal delivery diagnostics
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: d1bd0f71-7638-463a-958d-d5b3e2da1047
* fix(telegram): keep draft visibility change scoped
Remove the diagnostic expansion so this contributor PR remains focused on its original warn-level logging repair.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: d1bd0f71-7638-463a-958d-d5b3e2da1047
---------
Co-authored-by: Arseniy Palagin <valeradzigurda3@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Gio Della-Libera <giodl73@gmail.com>
Copilot-Session: d1bd0f71-7638-463a-958d-d5b3e2da1047
This commit is contained in:
@@ -8,7 +8,7 @@ import type {
|
||||
} from "openclaw/plugin-sdk/config-contracts";
|
||||
import type { ReplyPayload } from "openclaw/plugin-sdk/reply-payload";
|
||||
import type { BlockReplyContext } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { createSubsystemLogger, logVerbose } from "openclaw/plugin-sdk/runtime-env";
|
||||
import type { TelegramBotDeps } from "./bot-deps.js";
|
||||
import { resolveMarkdownTableMode } from "./bot-message-dispatch.runtime.js";
|
||||
import type {
|
||||
@@ -26,6 +26,8 @@ import { recordOutboundMessageForPromptContext } from "./outbound-message-contex
|
||||
import { splitTelegramReasoningText } from "./reasoning-lane-coordinator.js";
|
||||
import { buildTelegramRichMarkdown, TELEGRAM_RICH_TEXT_LIMIT } from "./rich-message.js";
|
||||
|
||||
const draftLogger = createSubsystemLogger("telegram/draft-stream");
|
||||
|
||||
const DRAFT_MIN_INITIAL_CHARS = 30;
|
||||
|
||||
type DraftPartialTextUpdate = {
|
||||
@@ -161,7 +163,15 @@ export function createTelegramDraftController(params: {
|
||||
});
|
||||
},
|
||||
log: logVerbose,
|
||||
warn: logVerbose,
|
||||
// Draft delivery failures must stay operator-visible: verbose-only
|
||||
// logging hid preview send/edit/cleanup errors, so a dead progress
|
||||
// stream looked like the bot silently ignoring the user.
|
||||
warn: (message) =>
|
||||
draftLogger.warn(message, {
|
||||
lane: laneName,
|
||||
chatId: params.chatId,
|
||||
threadId: params.threadSpec.id,
|
||||
}),
|
||||
})
|
||||
: undefined;
|
||||
return {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { expect, it } from "vitest";
|
||||
import { expect, it, vi } from "vitest";
|
||||
import {
|
||||
describeTelegramDispatch,
|
||||
createContext,
|
||||
createDirectSessionPayload,
|
||||
createReasoningStreamContext,
|
||||
createTelegramDraftStream,
|
||||
deliverReplies,
|
||||
dispatchReplyWithBufferedBlockDispatcher,
|
||||
dispatchWithContext,
|
||||
@@ -11,12 +12,48 @@ import {
|
||||
expectDeliveredReply,
|
||||
expectDeliverRepliesParams,
|
||||
expectWindowCollapsedTo,
|
||||
mockCallArg,
|
||||
requireInvocationOrder,
|
||||
setupDraftStreams,
|
||||
telegramProgressPreview,
|
||||
} from "./bot-message-dispatch.test-harness.js";
|
||||
|
||||
const draftWarn = vi.hoisted(() => vi.fn());
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/runtime-env", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/runtime-env")>();
|
||||
return {
|
||||
...actual,
|
||||
createSubsystemLogger: (subsystem: string) => {
|
||||
const logger = actual.createSubsystemLogger(subsystem);
|
||||
return subsystem === "telegram/draft-stream" ? { ...logger, warn: draftWarn } : logger;
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
describeTelegramDispatch("dispatchTelegramMessage draft-failures-progress", () => {
|
||||
it("routes draft stream failures to the warn-level telegram logger with lane context", async () => {
|
||||
setupDraftStreams({ answerMessageId: 2001 });
|
||||
dispatchReplyWithBufferedBlockDispatcher.mockImplementation(async ({ dispatcherOptions }) => {
|
||||
await dispatcherOptions.deliver({ text: "Final answer" }, { kind: "final" });
|
||||
return { queuedFinal: true };
|
||||
});
|
||||
|
||||
await dispatchWithContext({ context: createContext() });
|
||||
|
||||
const draftParams = mockCallArg(createTelegramDraftStream) as {
|
||||
warn?: (message: string) => void;
|
||||
};
|
||||
expect(typeof draftParams.warn).toBe("function");
|
||||
draftWarn.mockClear();
|
||||
draftParams.warn?.("telegram stream preview failed: 400: Bad Request: chat not found");
|
||||
|
||||
expect(draftWarn).toHaveBeenCalledWith(
|
||||
"telegram stream preview failed: 400: Bad Request: chat not found",
|
||||
{ lane: "answer", chatId: 123, threadId: 777 },
|
||||
);
|
||||
});
|
||||
|
||||
it("sends an error fallback when dispatch fails after only partial output", async () => {
|
||||
dispatchReplyWithBufferedBlockDispatcher.mockImplementation(async ({ dispatcherOptions }) => {
|
||||
await dispatcherOptions.deliver({ text: "partial answer" }, { kind: "block" });
|
||||
|
||||
Reference in New Issue
Block a user