diff --git a/CHANGELOG.md b/CHANGELOG.md index 449d81b3ede..c868ccc18c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -318,6 +318,7 @@ Docs: https://docs.openclaw.ai - Plugins/runtime state: share plugin-facing infra singleton state across duplicate module graphs and keep session-binding adapter ownership stable until the active owner unregisters. (#50725) thanks @huntharo. - Discord/pickers: keep `/codex_resume --browse-projects` picker callbacks alive in Discord by sharing component callback state across duplicate module graphs, preserving callback fallbacks, and acknowledging matched plugin interactions before dispatch. (#51260) Thanks @huntharo. - Memory/core tools: register `memory_search` and `memory_get` independently so one unavailable memory tool no longer suppresses the other in new sessions. (#50198) Thanks @artwalker. +- Telegram/Mattermost message tool: keep plugin button schemas optional in isolated and cron sessions so plain sends do not fail validation when no current channel is active. (#52589) Thanks @tylerliu612. ## 2026.3.13 diff --git a/extensions/mattermost/src/channel.test.ts b/extensions/mattermost/src/channel.test.ts index 5c015b9546d..5c600649d27 100644 --- a/extensions/mattermost/src/channel.test.ts +++ b/extensions/mattermost/src/channel.test.ts @@ -1,3 +1,4 @@ +import { Type } from "@sinclair/typebox"; import { beforeEach, describe, expect, it, vi } from "vitest"; import type { OpenClawConfig } from "../runtime-api.js"; import { createChannelReplyPipeline } from "../runtime-api.js"; @@ -181,6 +182,26 @@ describe("mattermostPlugin", () => { expect(actions).toEqual([]); }); + it("keeps buttons optional in message tool schema", () => { + const cfg: OpenClawConfig = { + channels: { + mattermost: { + enabled: true, + botToken: "test-token", + baseUrl: "https://chat.example.com", + }, + }, + }; + + const discovery = mattermostPlugin.actions?.describeMessageTool?.({ cfg }); + const schema = discovery?.schema; + if (!schema || Array.isArray(schema)) { + throw new Error("expected mattermost message-tool schema"); + } + + expect(Type.Object(schema.properties).required).toBeUndefined(); + }); + it("hides react when actions.reactions is false", () => { const cfg: OpenClawConfig = { channels: { diff --git a/extensions/mattermost/src/channel.ts b/extensions/mattermost/src/channel.ts index b91f1c995a3..3827f328464 100644 --- a/extensions/mattermost/src/channel.ts +++ b/extensions/mattermost/src/channel.ts @@ -1,3 +1,4 @@ +import { Type } from "@sinclair/typebox"; import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers"; import { formatNormalizedAllowFromEntries } from "openclaw/plugin-sdk/allow-from"; import { createMessageToolButtonsSchema } from "openclaw/plugin-sdk/channel-actions"; @@ -97,7 +98,7 @@ function describeMattermostMessageTool({ enabledAccounts.length > 0 ? { properties: { - buttons: createMessageToolButtonsSchema(), + buttons: Type.Optional(createMessageToolButtonsSchema()), }, } : null,