mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 06:00:43 +00:00
fix: guard against undefined event.content in cron agentTurn payload (#66302)
* fix: remove documentation fences from HEARTBEAT.md template The HEARTBEAT.md template wrapped its content in markdown code fences and a doc heading for display purposes. Since loadTemplate() only strips YAML front matter, these artifacts leaked into generated workspace files, causing isHeartbeatContentEffectivelyEmpty() to consider them non-empty and triggering unnecessary API calls. Remove the markdown fences and doc heading so the template produces clean content after front-matter stripping. Closes #66284 * fix: guard against undefined event.content in cron agentTurn payload When a cron job fires with agentTurn payload, event.content is undefined. parseFaceTags(undefined) returned undefined, which propagated to userContent.startsWith("/") causing a TypeError crash. - Fix parseFaceTags and filterInternalMarkers to return "" for falsy input instead of returning the falsy value itself - Add null coalescing fallback at the gateway call site - Add unit tests for undefined/null/empty string inputs Closes #66283 * fix: address review — remove redundant guards, casts, and unrelated HEARTBEAT.md change * fix: guard against undefined event.content in cron agentTurn payload (#66302) (thanks @xinmotlanthua) --------- Co-authored-by: khanhkhanhlele <namkhanh2172@gmail.com> Co-authored-by: sliverp <870080352@qq.com>
This commit is contained in:
@@ -42,6 +42,7 @@ Docs: https://docs.openclaw.ai
|
||||
- fix(bluebubbles): replay missed webhook messages after gateway restart via a persistent per-account cursor and `/api/v1/message/query?after=<ts>` pass, so messages delivered while the gateway was down no longer disappear. Uses the existing `processMessage` path and is deduped by #66816's inbound GUID cache. (#66857, #66721) Thanks @omarshahine.
|
||||
- Telegram/native commands: keep Telegram command-sync cache process-local so gateway restarts re-register the menu instead of trusting stale on-disk sync state after Telegram cleared commands out-of-band. (#66730) Thanks @nightq.
|
||||
- Audio/self-hosted STT: restore `models.providers.*.request.allowPrivateNetwork` for audio transcription so private or LAN speech-to-text endpoints stop tripping SSRF blocks after the v2026.4.14 regression. (#66692) Thanks @jhsmith409.
|
||||
- QQBot/cron: guard against undefined `event.content` in `parseFaceTags` and `filterInternalMarkers` so cron-triggered agent turns with no content payload no longer crash with `TypeError: Cannot read properties of undefined (reading 'startsWith')`. (#66302) Thanks @xinmotlanthua.
|
||||
|
||||
## 2026.4.14
|
||||
|
||||
|
||||
@@ -2,6 +2,18 @@ import { describe, expect, it, vi } from "vitest";
|
||||
import { parseFaceTags } from "./text-parsing.js";
|
||||
|
||||
describe("parseFaceTags", () => {
|
||||
it("returns empty string when input is undefined", () => {
|
||||
expect(parseFaceTags(undefined)).toBe("");
|
||||
});
|
||||
|
||||
it("returns empty string when input is null", () => {
|
||||
expect(parseFaceTags(null)).toBe("");
|
||||
});
|
||||
|
||||
it("returns empty string when input is empty string", () => {
|
||||
expect(parseFaceTags("")).toBe("");
|
||||
});
|
||||
|
||||
it("skips oversized base64 ext payloads before decoding", () => {
|
||||
const oversizedBase64 = "A".repeat(100_000);
|
||||
const tag = `<faceType=1,faceId="1",ext="${oversizedBase64}">`;
|
||||
|
||||
@@ -5,9 +5,9 @@ import type { RefAttachmentSummary } from "../ref-index-store.js";
|
||||
const MAX_FACE_EXT_BYTES = 64 * 1024;
|
||||
|
||||
/** Replace QQ face tags with readable text labels. */
|
||||
export function parseFaceTags(text: string): string {
|
||||
export function parseFaceTags(text: string | undefined | null): string {
|
||||
if (!text) {
|
||||
return text;
|
||||
return "";
|
||||
}
|
||||
|
||||
return text.replace(/<faceType=\d+,faceId="[^"]*",ext="([^"]*)">/g, (_match, ext: string) => {
|
||||
@@ -26,9 +26,9 @@ export function parseFaceTags(text: string): string {
|
||||
}
|
||||
|
||||
/** Remove internal framework markers before sending text outward. */
|
||||
export function filterInternalMarkers(text: string): string {
|
||||
export function filterInternalMarkers(text: string | undefined | null): string {
|
||||
if (!text) {
|
||||
return text;
|
||||
return "";
|
||||
}
|
||||
|
||||
let result = text.replace(/\[\[[a-z_]+:\s*[^\]]*\]\]/gi, "");
|
||||
|
||||
Reference in New Issue
Block a user