diff --git a/CHANGELOG.md b/CHANGELOG.md index 82003acd086..745bf921b37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ Docs: https://docs.openclaw.ai - Feishu/Group session routing: add configurable group session scopes (`group`, `group_sender`, `group_topic`, `group_topic_sender`) with legacy `topicSessionMode=enabled` compatibility so Feishu group conversations can isolate sessions by sender/topic as configured. (#17798) - Feishu/Reply-in-thread routing: add `replyInThread` config (`disabled|enabled`) for group replies, propagate `reply_in_thread` across text/card/media/streaming sends, and align topic-scoped session routing so newly created reply threads stay on the same session root. (#27325) - Feishu/Typing backoff: re-throw Feishu typing add/remove rate-limit and quota errors (`429`, `99991400`, `99991403`) and detect SDK non-throwing backoff responses so the typing keepalive circuit breaker can stop retries instead of looping indefinitely. (#28494) +- Feishu/Zalo runtime logging: replace direct `console.log/error` usage in Feishu typing-indicator paths and Zalo monitor paths with runtime-gated logger calls so verbosity controls are respected while preserving typing backoff behavior. (#18841) Thanks @Clawborn. - Feishu/Probe status caching: cache successful `probeFeishu()` bot-info results for 10 minutes (bounded cache with per-account keying) to reduce repeated status/onboarding probe API calls, while bypassing cache for failures and exceptions. (#28907) Thanks @Glucksberg. - Feishu/Opus media send type: send `.opus` attachments with `msg_type: "audio"` (instead of `"media"`) so Feishu voice messages deliver correctly while `.mp4` remains `msg_type: "media"` and documents remain `msg_type: "file"`. (#28269) Thanks @Glucksberg. - Feishu/Mobile video media type: treat inbound `message_type: "media"` as video-equivalent for media key extraction, placeholder inference, and media download resolution so mobile-app video sends ingest correctly. (#25502) Thanks @4ier. diff --git a/extensions/feishu/src/reply-dispatcher.ts b/extensions/feishu/src/reply-dispatcher.ts index cda4e6e506e..faff6b25ff6 100644 --- a/extensions/feishu/src/reply-dispatcher.ts +++ b/extensions/feishu/src/reply-dispatcher.ts @@ -59,13 +59,18 @@ export function createFeishuReplyDispatcher(params: CreateFeishuReplyDispatcherP if (!replyToMessageId) { return; } - typingState = await addTypingIndicator({ cfg, messageId: replyToMessageId, accountId }); + typingState = await addTypingIndicator({ + cfg, + messageId: replyToMessageId, + accountId, + runtime: params.runtime, + }); }, stop: async () => { if (!typingState) { return; } - await removeTypingIndicator({ cfg, state: typingState, accountId }); + await removeTypingIndicator({ cfg, state: typingState, accountId, runtime: params.runtime }); typingState = null; }, onStartError: (err) => diff --git a/extensions/feishu/src/typing.ts b/extensions/feishu/src/typing.ts index 7dba5fc29f6..5e47a0085ac 100644 --- a/extensions/feishu/src/typing.ts +++ b/extensions/feishu/src/typing.ts @@ -1,6 +1,7 @@ -import type { ClawdbotConfig } from "openclaw/plugin-sdk"; +import type { ClawdbotConfig, RuntimeEnv } from "openclaw/plugin-sdk"; import { resolveFeishuAccount } from "./accounts.js"; import { createFeishuClient } from "./client.js"; +import { getFeishuRuntime } from "./runtime.js"; // Feishu emoji types for typing indicator // See: https://open.feishu.cn/document/server-docs/im-v1/message-reaction/emojis-introduce @@ -103,8 +104,9 @@ export async function addTypingIndicator(params: { cfg: ClawdbotConfig; messageId: string; accountId?: string; + runtime?: RuntimeEnv; }): Promise { - const { cfg, messageId, accountId } = params; + const { cfg, messageId, accountId, runtime } = params; const account = resolveFeishuAccount({ cfg, accountId }); if (!account.configured) { return { messageId, reactionId: null }; @@ -124,9 +126,11 @@ export async function addTypingIndicator(params: { // instead of throwing. Detect backoff codes and throw to trip the breaker. const backoffCode = getBackoffCodeFromResponse(response); if (backoffCode !== undefined) { - console.log( - `[feishu] typing indicator response contains backoff code ${backoffCode}, stopping keepalive`, - ); + if (getFeishuRuntime().logging.shouldLogVerbose()) { + runtime?.log?.( + `[feishu] typing indicator response contains backoff code ${backoffCode}, stopping keepalive`, + ); + } throw new FeishuBackoffError(backoffCode); } @@ -135,11 +139,15 @@ export async function addTypingIndicator(params: { return { messageId, reactionId }; } catch (err) { if (isFeishuBackoffError(err)) { - console.log(`[feishu] typing indicator hit rate-limit/quota, stopping keepalive`); + if (getFeishuRuntime().logging.shouldLogVerbose()) { + runtime?.log?.("[feishu] typing indicator hit rate-limit/quota, stopping keepalive"); + } throw err; } // Silently fail for other non-critical errors (e.g. message deleted, permission issues) - console.log(`[feishu] failed to add typing indicator: ${err}`); + if (getFeishuRuntime().logging.shouldLogVerbose()) { + runtime?.log?.(`[feishu] failed to add typing indicator: ${String(err)}`); + } return { messageId, reactionId: null }; } } @@ -153,8 +161,9 @@ export async function removeTypingIndicator(params: { cfg: ClawdbotConfig; state: TypingIndicatorState; accountId?: string; + runtime?: RuntimeEnv; }): Promise { - const { cfg, state, accountId } = params; + const { cfg, state, accountId, runtime } = params; if (!state.reactionId) { return; } @@ -177,17 +186,25 @@ export async function removeTypingIndicator(params: { // Check for backoff codes in non-throwing SDK responses const backoffCode = getBackoffCodeFromResponse(result); if (backoffCode !== undefined) { - console.log( - `[feishu] typing indicator removal response contains backoff code ${backoffCode}, stopping keepalive`, - ); + if (getFeishuRuntime().logging.shouldLogVerbose()) { + runtime?.log?.( + `[feishu] typing indicator removal response contains backoff code ${backoffCode}, stopping keepalive`, + ); + } throw new FeishuBackoffError(backoffCode); } } catch (err) { if (isFeishuBackoffError(err)) { - console.log(`[feishu] typing indicator removal hit rate-limit/quota, stopping keepalive`); + if (getFeishuRuntime().logging.shouldLogVerbose()) { + runtime?.log?.( + "[feishu] typing indicator removal hit rate-limit/quota, stopping keepalive", + ); + } throw err; } // Silently fail for other non-critical errors - console.log(`[feishu] failed to remove typing indicator: ${err}`); + if (getFeishuRuntime().logging.shouldLogVerbose()) { + runtime?.log?.(`[feishu] failed to remove typing indicator: ${String(err)}`); + } } } diff --git a/extensions/zalo/src/monitor.ts b/extensions/zalo/src/monitor.ts index 3063e231a21..e1887c488fd 100644 --- a/extensions/zalo/src/monitor.ts +++ b/extensions/zalo/src/monitor.ts @@ -143,7 +143,7 @@ function startPollingLoop(params: { if (err instanceof ZaloApiError && err.isPollingTimeout) { // no updates } else if (!isStopped() && !abortSignal.aborted) { - console.error(`[${account.accountId}] Zalo polling error:`, err); + runtime.error?.(`[${account.accountId}] Zalo polling error: ${String(err)}`); await new Promise((resolve) => setTimeout(resolve, 5000)); } } @@ -190,10 +190,12 @@ async function processUpdate( ); break; case "message.sticker.received": - console.log(`[${account.accountId}] Received sticker from ${message.from.id}`); + logVerbose(core, runtime, `[${account.accountId}] Received sticker from ${message.from.id}`); break; case "message.unsupported.received": - console.log( + logVerbose( + core, + runtime, `[${account.accountId}] Received unsupported message type from ${message.from.id}`, ); break; @@ -259,7 +261,7 @@ async function handleImageMessage( mediaPath = saved.path; mediaType = saved.contentType; } catch (err) { - console.error(`[${account.accountId}] Failed to download Zalo image:`, err); + runtime.error?.(`[${account.accountId}] Failed to download Zalo image: ${String(err)}`); } }