@openclaw/mattermost 2026.7.2-beta.1 → 2026.7.2-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,20 +1,22 @@
1
- import { a as normalizeMattermostAllowList, b as readRequestBodyWithLimit, d as createChannelMessageReplyPipeline, g as loadOutboundMediaFromUrl, l as buildModelsProviderData, m as isTrustedProxyAddress, p as isRequestBodyLimitError, t as authorizeMattermostCommandInvocation, v as logTypingFailure, w as resolveClientIp } from "./monitor-auth-BiDuyvOc.js";
2
- import { b as updateMattermostPost, c as createMattermostPost, d as fetchMattermostChannelByName, f as fetchMattermostMe, g as normalizeMattermostBaseUrl, h as fetchMattermostUserTeams, m as fetchMattermostUserByUsername, o as createMattermostClient, p as fetchMattermostUser, r as resolveMattermostAccount, s as createMattermostDirectChannelWithRetry, u as fetchMattermostChannel, v as resolveMattermostReplyDeliveryBarrierTimeoutMs, x as uploadMattermostFile, y as sendMattermostTyping } from "./accounts-B2NRPlqr.js";
3
1
  import { t as getMattermostRuntime } from "./runtime-CNB4YGqJ.js";
2
+ import { _ as uploadMattermostFile, c as fetchMattermostMe, d as fetchMattermostUserTeams, f as normalizeMattermostBaseUrl, h as sendMattermostTyping, i as createMattermostPost, l as fetchMattermostUser, m as resolveMattermostReplyDeliveryBarrierTimeoutMs, n as createMattermostClient, o as fetchMattermostChannel, r as createMattermostDirectChannelWithRetry, s as fetchMattermostChannelByName, u as fetchMattermostUserByUsername } from "./client-BzLj4dyf.js";
3
+ import { a as normalizeMattermostAllowList, b as readRequestBodyWithLimit, d as createChannelMessageReplyPipeline, g as loadOutboundMediaFromUrl, l as buildModelsProviderData, p as isRequestBodyLimitError, t as authorizeMattermostCommandInvocation, v as logTypingFailure } from "./monitor-auth-dEHa1_On.js";
4
+ import { c as setInteractionSecret, n as buildButtonProps, o as resolveInteractionCallbackUrl } from "./interactions-DO7J-ND1.js";
5
+ import { r as resolveMattermostAccount } from "./accounts-C4Azn6rA.js";
6
+ import { createHash } from "node:crypto";
7
+ import { safeEqualSecret } from "openclaw/plugin-sdk/security-runtime";
4
8
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString, normalizeStringifiedOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
9
+ import { asDateTimestampMs, parseStrictInteger, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
10
+ import { isPrivateNetworkOptInEnabled } from "openclaw/plugin-sdk/ssrf-runtime";
5
11
  import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-outbound";
6
12
  import { resolveStoredModelOverride } from "openclaw/plugin-sdk/command-auth-native";
7
13
  import { getAgentScopedMediaLocalRoots } from "openclaw/plugin-sdk/media-runtime";
8
- import { asDateTimestampMs, parseStrictInteger, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
9
14
  import { deliverTextOrMediaReply, isReasoningReplyPayload, resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload";
10
- import { isPrivateNetworkOptInEnabled } from "openclaw/plugin-sdk/ssrf-runtime";
11
15
  import { convertMarkdownTables } from "openclaw/plugin-sdk/text-chunking";
12
16
  import { getSessionEntry, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
13
17
  import { normalizeProviderId } from "openclaw/plugin-sdk/provider-model-shared";
14
18
  import { Readable } from "node:stream";
15
- import { safeEqualSecret } from "openclaw/plugin-sdk/security-runtime";
16
19
  import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
17
- import { createHash, createHmac } from "node:crypto";
18
20
  import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
19
21
  import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
20
22
  import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
@@ -687,374 +689,6 @@ async function deliverMattermostReplyPayload(params) {
687
689
  });
688
690
  }
689
691
  //#endregion
690
- //#region extensions/mattermost/src/mattermost/interactions.ts
691
- const INTERACTION_MAX_BODY_BYTES = 64 * 1024;
692
- const INTERACTION_BODY_TIMEOUT_MS = 1e4;
693
- const SIGNED_CHANNEL_ID_CONTEXT_KEY = "__openclaw_channel_id";
694
- const callbackUrls = /* @__PURE__ */ new Map();
695
- function setInteractionCallbackUrl(accountId, url) {
696
- callbackUrls.set(accountId, url);
697
- }
698
- function resolveInteractionCallbackPath(accountId) {
699
- return `/mattermost/interactions/${accountId}`;
700
- }
701
- function isWildcardBindHost(rawHost) {
702
- const trimmed = rawHost.trim();
703
- if (!trimmed) return false;
704
- const host = trimmed.startsWith("[") && trimmed.endsWith("]") ? trimmed.slice(1, -1) : trimmed;
705
- return host === "0.0.0.0" || host === "::" || host === "0:0:0:0:0:0:0:0" || host === "::0";
706
- }
707
- function normalizeCallbackBaseUrl(baseUrl) {
708
- return baseUrl.trim().replace(/\/+$/, "");
709
- }
710
- function headerValue(value) {
711
- if (Array.isArray(value)) return normalizeOptionalString(value[0]);
712
- return normalizeOptionalString(value);
713
- }
714
- function isAllowedInteractionSource(params) {
715
- const { allowedSourceIps } = params;
716
- if (!allowedSourceIps?.length) return true;
717
- return isTrustedProxyAddress(resolveClientIp({
718
- remoteAddr: params.req.socket?.remoteAddress,
719
- forwardedFor: headerValue(params.req.headers["x-forwarded-for"]),
720
- realIp: headerValue(params.req.headers["x-real-ip"]),
721
- trustedProxies: params.trustedProxies,
722
- allowRealIpFallback: params.allowRealIpFallback
723
- }), allowedSourceIps);
724
- }
725
- /**
726
- * Resolve the interaction callback URL for an account.
727
- * Falls back to computing it from interactions.callbackBaseUrl or gateway host config.
728
- */
729
- function computeInteractionCallbackUrl(accountId, cfg) {
730
- const path = resolveInteractionCallbackPath(accountId);
731
- const callbackBaseUrl = normalizeOptionalString(cfg?.interactions?.callbackBaseUrl) ?? normalizeOptionalString(cfg?.channels?.mattermost?.interactions?.callbackBaseUrl);
732
- if (callbackBaseUrl) return `${normalizeCallbackBaseUrl(callbackBaseUrl)}${path}`;
733
- const port = typeof cfg?.gateway?.port === "number" ? cfg.gateway.port : 18789;
734
- let host = cfg?.gateway?.customBindHost && !isWildcardBindHost(cfg.gateway.customBindHost) ? cfg.gateway.customBindHost.trim() : "localhost";
735
- if (host.includes(":") && !(host.startsWith("[") && host.endsWith("]"))) host = `[${host}]`;
736
- return `http://${host}:${port}${path}`;
737
- }
738
- /**
739
- * Resolve the interaction callback URL for an account.
740
- * Prefers the in-memory registered URL (set by the gateway monitor) so callers outside the
741
- * monitor lifecycle can reuse the runtime-validated callback destination.
742
- */
743
- function resolveInteractionCallbackUrl(accountId, cfg) {
744
- const cached = callbackUrls.get(accountId);
745
- if (cached) return cached;
746
- return computeInteractionCallbackUrl(accountId, cfg);
747
- }
748
- const interactionSecrets = /* @__PURE__ */ new Map();
749
- let defaultInteractionSecret;
750
- function deriveInteractionSecret(botToken) {
751
- return createHmac("sha256", "openclaw-mattermost-interactions").update(botToken).digest("hex");
752
- }
753
- function setInteractionSecret(accountIdOrBotToken, botToken) {
754
- if (typeof botToken === "string") {
755
- interactionSecrets.set(accountIdOrBotToken, deriveInteractionSecret(botToken));
756
- return;
757
- }
758
- defaultInteractionSecret = deriveInteractionSecret(accountIdOrBotToken);
759
- }
760
- function getInteractionSecret(accountId) {
761
- const scoped = accountId ? interactionSecrets.get(accountId) : void 0;
762
- if (scoped) return scoped;
763
- if (defaultInteractionSecret) return defaultInteractionSecret;
764
- if (interactionSecrets.size === 1) {
765
- const first = interactionSecrets.values().next().value;
766
- if (typeof first === "string") return first;
767
- }
768
- throw new Error("Interaction secret not initialized — call setInteractionSecret(accountId, botToken) first");
769
- }
770
- function canonicalizeInteractionContext(value) {
771
- if (Array.isArray(value)) return value.map((item) => canonicalizeInteractionContext(item));
772
- if (value && typeof value === "object") {
773
- const entries = Object.entries(value).filter(([, entryValue]) => entryValue !== void 0).toSorted(([left], [right]) => left.localeCompare(right)).map(([key, entryValue]) => [key, canonicalizeInteractionContext(entryValue)]);
774
- return Object.fromEntries(entries);
775
- }
776
- return value;
777
- }
778
- function generateInteractionToken(context, accountId) {
779
- const secret = getInteractionSecret(accountId);
780
- const payload = JSON.stringify(canonicalizeInteractionContext(context));
781
- return createHmac("sha256", secret).update(payload).digest("hex");
782
- }
783
- function verifyInteractionToken(context, token, accountId) {
784
- return safeEqualSecret(generateInteractionToken(context, accountId), token);
785
- }
786
- /**
787
- * Build Mattermost `props.attachments` with interactive buttons.
788
- *
789
- * Each button includes an HMAC token in its integration context so the
790
- * callback handler can verify the request originated from a legitimate
791
- * button click (Mattermost's recommended security pattern).
792
- */
793
- /**
794
- * Sanitize a button ID so Mattermost's action router can match it.
795
- * Mattermost uses the action ID in the URL path `/api/v4/posts/{id}/actions/{actionId}`
796
- * and IDs containing hyphens or underscores break the server-side routing.
797
- * See: https://github.com/mattermost/mattermost/issues/25747
798
- */
799
- function sanitizeActionId(id) {
800
- return id.replace(/[-_]/g, "");
801
- }
802
- function buildButtonAttachments(params) {
803
- const actions = params.buttons.map((btn) => {
804
- const safeId = sanitizeActionId(btn.id);
805
- const context = {
806
- action_id: safeId,
807
- ...btn.context
808
- };
809
- const token = generateInteractionToken(context, params.accountId);
810
- return {
811
- id: safeId,
812
- type: "button",
813
- name: btn.name,
814
- style: btn.style,
815
- integration: {
816
- url: params.callbackUrl,
817
- context: {
818
- ...context,
819
- _token: token
820
- }
821
- }
822
- };
823
- });
824
- return [{
825
- text: params.text ?? "",
826
- actions
827
- }];
828
- }
829
- function buildButtonProps(params) {
830
- const buttons = params.buttons.flatMap((item) => Array.isArray(item) ? item : [item]).map((btn) => ({
831
- id: normalizeStringifiedOptionalString(btn.id ?? btn.callback_data) ?? "",
832
- name: normalizeStringifiedOptionalString(btn.text ?? btn.name ?? btn.label) ?? "",
833
- style: btn.style ?? "default",
834
- context: typeof btn.context === "object" && btn.context !== null ? {
835
- ...btn.context,
836
- [SIGNED_CHANNEL_ID_CONTEXT_KEY]: params.channelId
837
- } : { [SIGNED_CHANNEL_ID_CONTEXT_KEY]: params.channelId }
838
- })).filter((btn) => btn.id && btn.name);
839
- if (buttons.length === 0) return;
840
- return { attachments: buildButtonAttachments({
841
- callbackUrl: params.callbackUrl,
842
- accountId: params.accountId,
843
- buttons,
844
- text: params.text
845
- }) };
846
- }
847
- function readInteractionBody(req) {
848
- return readRequestBodyWithLimit(req, {
849
- maxBytes: INTERACTION_MAX_BODY_BYTES,
850
- timeoutMs: INTERACTION_BODY_TIMEOUT_MS
851
- });
852
- }
853
- function createMattermostInteractionHandler(params) {
854
- const { client, accountId, log } = params;
855
- const core = getMattermostRuntime();
856
- function parseInteractionPayload(raw) {
857
- try {
858
- return JSON.parse(raw);
859
- } catch {
860
- throw new Error("Mattermost interaction body was malformed JSON");
861
- }
862
- }
863
- return async (req, res) => {
864
- if (req.method !== "POST") {
865
- res.statusCode = 405;
866
- res.setHeader("Allow", "POST");
867
- res.setHeader("Content-Type", "application/json");
868
- res.end(JSON.stringify({ error: "Method Not Allowed" }));
869
- return;
870
- }
871
- if (!isAllowedInteractionSource({
872
- req,
873
- allowedSourceIps: params.allowedSourceIps,
874
- trustedProxies: params.trustedProxies,
875
- allowRealIpFallback: params.allowRealIpFallback
876
- })) {
877
- log?.(`mattermost interaction: rejected callback source remote=${req.socket?.remoteAddress ?? "?"}`);
878
- res.statusCode = 403;
879
- res.setHeader("Content-Type", "application/json");
880
- res.end(JSON.stringify({ error: "Forbidden origin" }));
881
- return;
882
- }
883
- let payload;
884
- try {
885
- payload = parseInteractionPayload(await readInteractionBody(req));
886
- } catch (err) {
887
- log?.(`mattermost interaction: failed to parse body: ${String(err)}`);
888
- res.statusCode = 400;
889
- res.setHeader("Content-Type", "application/json");
890
- res.end(JSON.stringify({ error: "Invalid request body" }));
891
- return;
892
- }
893
- const context = payload.context;
894
- if (!context) {
895
- res.statusCode = 400;
896
- res.setHeader("Content-Type", "application/json");
897
- res.end(JSON.stringify({ error: "Missing context" }));
898
- return;
899
- }
900
- const token = context["_token"];
901
- if (typeof token !== "string") {
902
- log?.("mattermost interaction: missing _token in context");
903
- res.statusCode = 403;
904
- res.setHeader("Content-Type", "application/json");
905
- res.end(JSON.stringify({ error: "Missing token" }));
906
- return;
907
- }
908
- const { _token, ...contextWithoutToken } = context;
909
- if (!verifyInteractionToken(contextWithoutToken, token, accountId)) {
910
- log?.("mattermost interaction: invalid _token");
911
- res.statusCode = 403;
912
- res.setHeader("Content-Type", "application/json");
913
- res.end(JSON.stringify({ error: "Invalid token" }));
914
- return;
915
- }
916
- const actionId = context.action_id;
917
- if (typeof actionId !== "string") {
918
- res.statusCode = 400;
919
- res.setHeader("Content-Type", "application/json");
920
- res.end(JSON.stringify({ error: "Missing action_id in context" }));
921
- return;
922
- }
923
- const signedChannelId = typeof contextWithoutToken[SIGNED_CHANNEL_ID_CONTEXT_KEY] === "string" ? contextWithoutToken[SIGNED_CHANNEL_ID_CONTEXT_KEY].trim() : "";
924
- if (signedChannelId && signedChannelId !== payload.channel_id) {
925
- log?.(`mattermost interaction: signed channel mismatch payload=${payload.channel_id} signed=${signedChannelId}`);
926
- res.statusCode = 403;
927
- res.setHeader("Content-Type", "application/json");
928
- res.end(JSON.stringify({ error: "Channel mismatch" }));
929
- return;
930
- }
931
- const userName = payload.user_name ?? payload.user_id;
932
- let originalMessage;
933
- let originalPost;
934
- let clickedButtonName = null;
935
- try {
936
- originalPost = await client.request(`/posts/${payload.post_id}`);
937
- const postChannelId = originalPost.channel_id?.trim();
938
- if (!postChannelId || postChannelId !== payload.channel_id) {
939
- log?.(`mattermost interaction: post channel mismatch payload=${payload.channel_id} post=${postChannelId ?? "<missing>"}`);
940
- res.statusCode = 403;
941
- res.setHeader("Content-Type", "application/json");
942
- res.end(JSON.stringify({ error: "Post/channel mismatch" }));
943
- return;
944
- }
945
- originalMessage = originalPost.message ?? "";
946
- const postAttachments = Array.isArray(originalPost?.props?.attachments) ? originalPost.props.attachments : [];
947
- for (const att of postAttachments) {
948
- const match = att.actions?.find((a) => a.id === actionId);
949
- if (match?.name) {
950
- clickedButtonName = match.name;
951
- break;
952
- }
953
- }
954
- if (clickedButtonName === null) {
955
- log?.(`mattermost interaction: action ${actionId} not found in post ${payload.post_id}`);
956
- res.statusCode = 403;
957
- res.setHeader("Content-Type", "application/json");
958
- res.end(JSON.stringify({ error: "Unknown action" }));
959
- return;
960
- }
961
- } catch (err) {
962
- log?.(`mattermost interaction: failed to validate post ${payload.post_id}: ${String(err)}`);
963
- res.statusCode = 500;
964
- res.setHeader("Content-Type", "application/json");
965
- res.end(JSON.stringify({ error: "Failed to validate interaction" }));
966
- return;
967
- }
968
- if (!originalPost) {
969
- log?.(`mattermost interaction: missing fetched post ${payload.post_id}`);
970
- res.statusCode = 500;
971
- res.setHeader("Content-Type", "application/json");
972
- res.end(JSON.stringify({ error: "Failed to load interaction post" }));
973
- return;
974
- }
975
- log?.(`mattermost interaction: action=${actionId} user=${payload.user_name ?? payload.user_id} post=${payload.post_id} channel=${payload.channel_id}`);
976
- if (params.authorizeButtonClick) try {
977
- const authorization = await params.authorizeButtonClick({
978
- payload,
979
- post: originalPost
980
- });
981
- if (!authorization.ok) {
982
- res.statusCode = authorization.statusCode ?? 200;
983
- res.setHeader("Content-Type", "application/json");
984
- res.end(JSON.stringify(authorization.response ?? { ephemeral_text: "You are not allowed to use this action here." }));
985
- return;
986
- }
987
- } catch (err) {
988
- log?.(`mattermost interaction: authorization failed: ${String(err)}`);
989
- res.statusCode = 500;
990
- res.setHeader("Content-Type", "application/json");
991
- res.end(JSON.stringify({ error: "Interaction authorization failed" }));
992
- return;
993
- }
994
- if (params.handleInteraction) try {
995
- const response = await params.handleInteraction({
996
- payload,
997
- userName,
998
- actionId,
999
- actionName: clickedButtonName,
1000
- originalMessage,
1001
- context: contextWithoutToken,
1002
- post: originalPost
1003
- });
1004
- if (response !== null) {
1005
- res.statusCode = 200;
1006
- res.setHeader("Content-Type", "application/json");
1007
- res.end(JSON.stringify(response));
1008
- return;
1009
- }
1010
- } catch (err) {
1011
- log?.(`mattermost interaction: custom handler failed: ${String(err)}`);
1012
- res.statusCode = 500;
1013
- res.setHeader("Content-Type", "application/json");
1014
- res.end(JSON.stringify({ error: "Interaction handler failed" }));
1015
- return;
1016
- }
1017
- try {
1018
- const eventLabel = `Mattermost button click: action="${actionId}" by ${payload.user_name ?? payload.user_id} in channel ${payload.channel_id}`;
1019
- const sessionKey = params.resolveSessionKey ? await params.resolveSessionKey({
1020
- channelId: payload.channel_id,
1021
- userId: payload.user_id,
1022
- post: originalPost
1023
- }) : `agent:main:mattermost:${accountId}:${payload.channel_id}`;
1024
- core.system.enqueueSystemEvent(eventLabel, {
1025
- sessionKey,
1026
- contextKey: `mattermost:interaction:${payload.post_id}:${actionId}`
1027
- });
1028
- } catch (err) {
1029
- log?.(`mattermost interaction: system event dispatch failed: ${String(err)}`);
1030
- }
1031
- try {
1032
- await updateMattermostPost(client, payload.post_id, {
1033
- message: originalMessage,
1034
- props: { attachments: [{ text: `✓ **${clickedButtonName}** selected by @${userName}` }] }
1035
- });
1036
- } catch (err) {
1037
- log?.(`mattermost interaction: failed to update post ${payload.post_id}: ${String(err)}`);
1038
- }
1039
- res.statusCode = 200;
1040
- res.setHeader("Content-Type", "application/json");
1041
- res.end("{}");
1042
- if (params.dispatchButtonClick) try {
1043
- await params.dispatchButtonClick({
1044
- channelId: payload.channel_id,
1045
- userId: payload.user_id,
1046
- userName,
1047
- actionId,
1048
- actionName: clickedButtonName,
1049
- postId: payload.post_id,
1050
- post: originalPost
1051
- });
1052
- } catch (err) {
1053
- log?.(`mattermost interaction: dispatchButtonClick failed: ${String(err)}`);
1054
- }
1055
- };
1056
- }
1057
- //#endregion
1058
692
  //#region extensions/mattermost/src/mattermost/target-resolution.ts
1059
693
  const MATTERMOST_OPAQUE_TARGET_CACHE_MAX_ENTRIES = 1024;
1060
694
  const mattermostOpaqueTargetCache = /* @__PURE__ */ new Map();
@@ -1154,6 +788,7 @@ async function resolveMattermostOpaqueTarget(params) {
1154
788
  cfg: params.cfg,
1155
789
  accountId: params.accountId
1156
790
  }) : null;
791
+ if (account && !account.enabled) throw new Error(`Mattermost account "${account.accountId}" is disabled`);
1157
792
  const token = normalizeOptionalString(params.token) ?? normalizeOptionalString(account?.botToken);
1158
793
  const baseUrl = normalizeMattermostBaseUrl(params.baseUrl ?? account?.baseUrl);
1159
794
  if (!token || !baseUrl) return null;
@@ -2289,4 +1924,4 @@ function registerSlashCommandRoute(api) {
2289
1924
  });
2290
1925
  }
2291
1926
  //#endregion
2292
- export { registerSlashCommands as C, isSlashCommandsEnabled as S, resolveSlashCommandConfig as T, renderMattermostModelsPickerView as _, sendMessageMattermost as a, DEFAULT_COMMAND_SPECS as b, computeInteractionCallbackUrl as c, setInteractionCallbackUrl as d, setInteractionSecret as f, parseMattermostModelPickerContext as g, buildMattermostAllowedModelRefs as h, registerSlashCommandRoute as i, createMattermostInteractionHandler as l, deliverMattermostReplyPayload as m, deactivateSlashCommands as n, resolveMattermostOpaqueTarget as o, createMattermostReplyDeliveryBarrier as p, getSlashCommandState as r, buildButtonProps as s, activateSlashCommands as t, resolveInteractionCallbackPath as u, renderMattermostProviderPickerView as v, resolveCallbackUrl as w, cleanupSlashCommands as x, resolveMattermostModelPickerCurrentModel as y };
1927
+ export { registerSlashCommands as _, sendMessageMattermost as a, deliverMattermostReplyPayload as c, renderMattermostModelsPickerView as d, renderMattermostProviderPickerView as f, isSlashCommandsEnabled as g, cleanupSlashCommands as h, registerSlashCommandRoute as i, buildMattermostAllowedModelRefs as l, DEFAULT_COMMAND_SPECS as m, deactivateSlashCommands as n, resolveMattermostOpaqueTarget as o, resolveMattermostModelPickerCurrentModel as p, getSlashCommandState as r, createMattermostReplyDeliveryBarrier as s, activateSlashCommands as t, parseMattermostModelPickerContext as u, resolveCallbackUrl as v, resolveSlashCommandConfig as y };
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@openclaw/mattermost",
3
- "version": "2026.7.2-beta.1",
3
+ "version": "2026.7.2-beta.2",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@openclaw/mattermost",
9
- "version": "2026.7.2-beta.1",
9
+ "version": "2026.7.2-beta.2",
10
10
  "dependencies": {
11
11
  "ws": "8.21.0",
12
12
  "zod": "4.4.3"
13
13
  },
14
14
  "peerDependencies": {
15
- "openclaw": ">=2026.7.2-beta.1"
15
+ "openclaw": ">=2026.7.2-beta.2"
16
16
  },
17
17
  "peerDependenciesMeta": {
18
18
  "openclaw": {
@@ -229,6 +229,13 @@
229
229
  "properties": {
230
230
  "toolProgress": {
231
231
  "type": "boolean"
232
+ },
233
+ "commandText": {
234
+ "type": "string",
235
+ "enum": [
236
+ "raw",
237
+ "status"
238
+ ]
232
239
  }
233
240
  },
234
241
  "additionalProperties": false
@@ -265,6 +272,13 @@
265
272
  },
266
273
  "toolProgress": {
267
274
  "type": "boolean"
275
+ },
276
+ "commandText": {
277
+ "type": "string",
278
+ "enum": [
279
+ "raw",
280
+ "status"
281
+ ]
268
282
  }
269
283
  },
270
284
  "additionalProperties": false
@@ -668,6 +682,13 @@
668
682
  "properties": {
669
683
  "toolProgress": {
670
684
  "type": "boolean"
685
+ },
686
+ "commandText": {
687
+ "type": "string",
688
+ "enum": [
689
+ "raw",
690
+ "status"
691
+ ]
671
692
  }
672
693
  },
673
694
  "additionalProperties": false
@@ -704,6 +725,13 @@
704
725
  },
705
726
  "toolProgress": {
706
727
  "type": "boolean"
728
+ },
729
+ "commandText": {
730
+ "type": "string",
731
+ "enum": [
732
+ "raw",
733
+ "status"
734
+ ]
707
735
  }
708
736
  },
709
737
  "additionalProperties": false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/mattermost",
3
- "version": "2026.7.2-beta.1",
3
+ "version": "2026.7.2-beta.2",
4
4
  "description": "OpenClaw Mattermost channel plugin",
5
5
  "repository": {
6
6
  "type": "git",
@@ -12,7 +12,7 @@
12
12
  "zod": "4.4.3"
13
13
  },
14
14
  "peerDependencies": {
15
- "openclaw": ">=2026.7.2-beta.1"
15
+ "openclaw": ">=2026.7.2-beta.2"
16
16
  },
17
17
  "peerDependenciesMeta": {
18
18
  "openclaw": {
@@ -41,10 +41,10 @@
41
41
  "allowInvalidConfigRecovery": true
42
42
  },
43
43
  "compat": {
44
- "pluginApi": ">=2026.7.2-beta.1"
44
+ "pluginApi": ">=2026.7.2-beta.2"
45
45
  },
46
46
  "build": {
47
- "openclawVersion": "2026.7.2-beta.1",
47
+ "openclawVersion": "2026.7.2-beta.2",
48
48
  "bundledDist": false
49
49
  },
50
50
  "release": {
@@ -1,6 +1,5 @@
1
- import { parseAccessGroupAllowFromEntry } from "openclaw/plugin-sdk/access-groups";
2
- import { resolveStableChannelMessageIngress } from "openclaw/plugin-sdk/channel-ingress-runtime";
3
1
  import { normalizeLowercaseStringOrEmpty, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
2
+ import { parseTcpPort } from "openclaw/plugin-sdk/number-runtime";
4
3
  import { buildAgentMediaPayload } from "openclaw/plugin-sdk/agent-media-payload";
5
4
  import { resolveAllowlistMatchSimple } from "openclaw/plugin-sdk/allow-from";
6
5
  import { logInboundDrop } from "openclaw/plugin-sdk/channel-inbound";
@@ -17,7 +16,8 @@ import { DEFAULT_GROUP_HISTORY_LIMIT, createChannelHistoryWindow } from "opencla
17
16
  import { registerPluginHttpRoute } from "openclaw/plugin-sdk/webhook-targets";
18
17
  import { isRequestBodyLimitError, readRequestBodyWithLimit } from "openclaw/plugin-sdk/webhook-ingress";
19
18
  import { isTrustedProxyAddress, resolveClientIp } from "openclaw/plugin-sdk/core";
20
- import { parseTcpPort } from "openclaw/plugin-sdk/number-runtime";
19
+ import { parseAccessGroupAllowFromEntry } from "openclaw/plugin-sdk/access-groups";
20
+ import { resolveStableChannelMessageIngress } from "openclaw/plugin-sdk/channel-ingress-runtime";
21
21
  //#region extensions/mattermost/src/mattermost/monitor-auth.ts
22
22
  const mattermostIngressIdentity = {
23
23
  key: "sender-id",