@openclaw/mattermost 2026.7.1-beta.6 → 2026.7.2-beta.1
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.
- package/dist/{accounts-ITTlduDO.js → accounts-B2NRPlqr.js} +56 -26
- package/dist/channel-plugin-api.js +3 -3
- package/dist/{channel-plugin-runtime-DhS8rwfs.js → channel-plugin-runtime-BkzZgYxP.js} +61 -82
- package/dist/channel-plugin-runtime.js +1 -1
- package/dist/{channel.runtime-D0SJSEei.js → channel.runtime-Cbs451W2.js} +499 -278
- package/dist/doctor-contract-BaUvVh8e.js +19 -0
- package/dist/doctor-contract-api.js +1 -1
- package/dist/gateway-auth-api.js +1 -1
- package/dist/{gateway-auth-bypass-BIXLORHU.js → gateway-auth-bypass-CL1PxV3z.js} +3 -2
- package/dist/secret-contract-B4R5Bmhv.js +28 -0
- package/dist/secret-contract-api.js +1 -1
- package/dist/slash-route-api.js +1 -1
- package/dist/{slash-state-BfOSlkmn.js → slash-state-Cr58Xd12.js} +118 -99
- package/npm-shrinkwrap.json +3 -3
- package/openclaw.plugin.json +189 -217
- package/package.json +4 -4
- package/dist/doctor-contract-ttH0DCuq.js +0 -7
- package/dist/secret-contract-Cx0LUNXy.js +0 -44
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
2
2
|
import { resolveChannelPreviewStreamMode, resolveChannelStreamingBlockCoalesce, resolveChannelStreamingBlockEnabled, resolveChannelStreamingChunkMode } from "openclaw/plugin-sdk/channel-outbound";
|
|
3
3
|
import { resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
4
|
+
import { buildTimeoutAbortSignal } from "openclaw/plugin-sdk/extension-shared";
|
|
4
5
|
import { fetchWithSsrFGuard, ssrfPolicyFromPrivateNetworkOptIn } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
5
6
|
import { createAccountListHelpers, hasConfiguredAccountValue } from "openclaw/plugin-sdk/account-helpers";
|
|
6
7
|
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
|
|
@@ -8,10 +9,11 @@ import { resolveMergedAccountConfig } from "openclaw/plugin-sdk/account-resoluti
|
|
|
8
9
|
import { buildSecretInputSchema, hasConfiguredSecretInput, normalizeResolvedSecretInputString, normalizeSecretInputString } from "openclaw/plugin-sdk/secret-input";
|
|
9
10
|
import { readProviderJsonResponse, readResponseTextLimited } from "openclaw/plugin-sdk/provider-http";
|
|
10
11
|
import { readResponseWithLimit } from "openclaw/plugin-sdk/response-limit-runtime";
|
|
11
|
-
import {
|
|
12
|
+
import { retryAsync } from "openclaw/plugin-sdk/retry-runtime";
|
|
12
13
|
import { z } from "zod";
|
|
13
14
|
//#region extensions/mattermost/src/mattermost/client.ts
|
|
14
15
|
const MATTERMOST_ERROR_BODY_LIMIT_BYTES = 8 * 1024;
|
|
16
|
+
const MATTERMOST_REQUEST_TIMEOUT_MS = 3e4;
|
|
15
17
|
const MATTERMOST_TEXT_RESPONSE_LIMIT_BYTES = 64 * 1024;
|
|
16
18
|
const NULL_BODY_STATUSES = /* @__PURE__ */ new Set([
|
|
17
19
|
101,
|
|
@@ -103,17 +105,42 @@ function createMattermostClient(params) {
|
|
|
103
105
|
if (!baseUrl) throw new Error("Mattermost baseUrl is required");
|
|
104
106
|
const apiBaseUrl = `${baseUrl}/api/v4`;
|
|
105
107
|
const token = params.botToken.trim();
|
|
108
|
+
const requestTimeoutMs = resolveTimerTimeoutMs(params.timeoutMs, MATTERMOST_REQUEST_TIMEOUT_MS);
|
|
106
109
|
const externalFetchImpl = params.fetchImpl;
|
|
107
110
|
const guardedFetchImpl = async (input, init) => {
|
|
111
|
+
const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
|
|
112
|
+
const { timeoutMs: initTimeoutMs, ...requestInit } = init ?? {};
|
|
113
|
+
const timeoutMs = resolveTimerTimeoutMs(initTimeoutMs, requestTimeoutMs);
|
|
108
114
|
const { response, release } = await fetchWithSsrFGuard({
|
|
109
|
-
url
|
|
110
|
-
init,
|
|
115
|
+
url,
|
|
116
|
+
init: requestInit,
|
|
111
117
|
auditContext: "mattermost-api",
|
|
112
|
-
policy: ssrfPolicyFromPrivateNetworkOptIn(params.allowPrivateNetwork)
|
|
118
|
+
policy: ssrfPolicyFromPrivateNetworkOptIn(params.allowPrivateNetwork),
|
|
119
|
+
signal: requestInit.signal ?? void 0,
|
|
120
|
+
timeoutMs
|
|
113
121
|
});
|
|
114
122
|
return responseWithRelease(response, release);
|
|
115
123
|
};
|
|
116
|
-
const fetchImpl = externalFetchImpl
|
|
124
|
+
const fetchImpl = (externalFetchImpl ? async (input, init) => {
|
|
125
|
+
const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
|
|
126
|
+
const { timeoutMs: initTimeoutMs, ...requestInit } = init ?? {};
|
|
127
|
+
const { signal: timeoutSignal, cleanup } = buildTimeoutAbortSignal({
|
|
128
|
+
timeoutMs: resolveTimerTimeoutMs(initTimeoutMs, requestTimeoutMs),
|
|
129
|
+
operation: "mattermost-api",
|
|
130
|
+
url
|
|
131
|
+
});
|
|
132
|
+
const callerSignal = requestInit.signal ?? void 0;
|
|
133
|
+
const signal = callerSignal && timeoutSignal ? AbortSignal.any([callerSignal, timeoutSignal]) : callerSignal ?? timeoutSignal;
|
|
134
|
+
try {
|
|
135
|
+
return responseWithRelease(await externalFetchImpl(input, {
|
|
136
|
+
...requestInit,
|
|
137
|
+
signal
|
|
138
|
+
}), async () => cleanup());
|
|
139
|
+
} catch (error) {
|
|
140
|
+
cleanup();
|
|
141
|
+
throw error;
|
|
142
|
+
}
|
|
143
|
+
} : void 0) ?? guardedFetchImpl;
|
|
117
144
|
const request = async (path, init) => {
|
|
118
145
|
const url = buildMattermostApiUrl(baseUrl, path);
|
|
119
146
|
const headers = new Headers(init?.headers);
|
|
@@ -163,11 +190,12 @@ async function sendMattermostTyping(client, params) {
|
|
|
163
190
|
body: JSON.stringify(payload)
|
|
164
191
|
});
|
|
165
192
|
}
|
|
166
|
-
async function createMattermostDirectChannel(client, userIds, signal) {
|
|
193
|
+
async function createMattermostDirectChannel(client, userIds, signal, timeoutMs) {
|
|
167
194
|
return await client.request("/channels/direct", {
|
|
168
195
|
method: "POST",
|
|
169
196
|
body: JSON.stringify(userIds),
|
|
170
|
-
signal
|
|
197
|
+
signal,
|
|
198
|
+
timeoutMs
|
|
171
199
|
});
|
|
172
200
|
}
|
|
173
201
|
const DM_REPLY_DELIVERY_BARRIER_SLACK_MS = 6e4;
|
|
@@ -229,26 +257,24 @@ const RETRYABLE_NETWORK_MESSAGE_SNIPPETS = [
|
|
|
229
257
|
async function createMattermostDirectChannelWithRetry(client, userIds, options = {}) {
|
|
230
258
|
const { maxRetries = 3, initialDelayMs = 1e3, maxDelayMs = 1e4, timeoutMs: rawTimeoutMs = 3e4, onRetry } = options;
|
|
231
259
|
const timeoutMs = resolveTimerTimeoutMs(rawTimeoutMs, 3e4);
|
|
232
|
-
|
|
233
|
-
for (let attempt = 0; attempt <= maxRetries; attempt++) try {
|
|
260
|
+
return await retryAsync(async () => {
|
|
234
261
|
const controller = new AbortController();
|
|
235
262
|
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
236
263
|
try {
|
|
237
|
-
return await createMattermostDirectChannel(client, userIds, controller.signal);
|
|
264
|
+
return await createMattermostDirectChannel(client, userIds, controller.signal, timeoutMs);
|
|
265
|
+
} catch (err) {
|
|
266
|
+
throw err instanceof Error ? err : new Error(String(err));
|
|
238
267
|
} finally {
|
|
239
268
|
clearTimeout(timeoutId);
|
|
240
269
|
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
await sleep(delayMs);
|
|
250
|
-
}
|
|
251
|
-
throw lastError ?? /* @__PURE__ */ new Error("Failed to create DM channel after retries");
|
|
270
|
+
}, {
|
|
271
|
+
attempts: maxRetries + 1,
|
|
272
|
+
minDelayMs: Math.min(initialDelayMs, maxDelayMs),
|
|
273
|
+
maxDelayMs,
|
|
274
|
+
jitter: "full",
|
|
275
|
+
shouldRetry: (err) => isRetryableError(err),
|
|
276
|
+
onRetry: (info) => onRetry?.(info.attempt, info.delayMs, info.err)
|
|
277
|
+
});
|
|
252
278
|
}
|
|
253
279
|
function isRetryableError(error) {
|
|
254
280
|
const candidates = collectErrorCandidates(error);
|
|
@@ -258,7 +284,9 @@ function isRetryableError(error) {
|
|
|
258
284
|
for (const message of messages) {
|
|
259
285
|
const clientErrorMatch = message.match(/mattermost api (4\d{2})\b/);
|
|
260
286
|
if (!clientErrorMatch) continue;
|
|
261
|
-
const
|
|
287
|
+
const statusCodeText = clientErrorMatch[1];
|
|
288
|
+
if (!statusCodeText) continue;
|
|
289
|
+
const statusCode = Number.parseInt(statusCodeText, 10);
|
|
262
290
|
if (statusCode >= 400 && statusCode < 500) return false;
|
|
263
291
|
}
|
|
264
292
|
if (messages.some((message) => /mattermost api \d{3}\b/.test(message))) return false;
|
|
@@ -418,17 +446,19 @@ function resolveMattermostAccount(params) {
|
|
|
418
446
|
oncharPrefixes: merged.oncharPrefixes,
|
|
419
447
|
requireMention,
|
|
420
448
|
textChunkLimit: merged.textChunkLimit,
|
|
421
|
-
chunkMode: resolveChannelStreamingChunkMode(merged)
|
|
449
|
+
chunkMode: resolveChannelStreamingChunkMode(merged),
|
|
422
450
|
streamingMode: resolveChannelPreviewStreamMode(merged, "partial"),
|
|
423
|
-
blockStreaming: resolveChannelStreamingBlockEnabled(merged)
|
|
424
|
-
blockStreamingCoalesce: resolveChannelStreamingBlockCoalesce(merged)
|
|
451
|
+
blockStreaming: resolveChannelStreamingBlockEnabled(merged),
|
|
452
|
+
blockStreamingCoalesce: resolveChannelStreamingBlockCoalesce(merged)
|
|
425
453
|
};
|
|
426
454
|
}
|
|
427
455
|
/**
|
|
428
456
|
* Resolve the effective replyToMode for a given chat type.
|
|
429
|
-
*
|
|
457
|
+
* Direct messages stay flat unless explicitly opted into a per-chat-type mode.
|
|
430
458
|
*/
|
|
431
459
|
function resolveMattermostReplyToMode(account, kind) {
|
|
460
|
+
const scopedMode = account.config.replyToModeByChatType?.[kind];
|
|
461
|
+
if (scopedMode !== void 0) return scopedMode;
|
|
432
462
|
if (kind === "direct") return "off";
|
|
433
463
|
return account.config.replyToMode ?? "off";
|
|
434
464
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as describeMattermostAccount, c as mattermostMeta, i as MattermostChannelConfigSchema, n as mattermostSetupWizard, o as isMattermostConfigured, r as mattermostSetupAdapter, s as mattermostConfigAdapter, t as mattermostPlugin } from "./channel-plugin-runtime-
|
|
2
|
-
import { t as resolveMattermostGatewayAuthBypassPaths } from "./gateway-auth-bypass-
|
|
1
|
+
import { a as describeMattermostAccount, c as mattermostMeta, i as MattermostChannelConfigSchema, n as mattermostSetupWizard, o as isMattermostConfigured, r as mattermostSetupAdapter, s as mattermostConfigAdapter, t as mattermostPlugin } from "./channel-plugin-runtime-BkzZgYxP.js";
|
|
2
|
+
import { t as resolveMattermostGatewayAuthBypassPaths } from "./gateway-auth-bypass-CL1PxV3z.js";
|
|
3
3
|
//#region extensions/mattermost/src/channel.setup.ts
|
|
4
4
|
const mattermostSetupPlugin = {
|
|
5
5
|
id: "mattermost",
|
|
@@ -23,7 +23,7 @@ const mattermostSetupPlugin = {
|
|
|
23
23
|
isConfigured: isMattermostConfigured,
|
|
24
24
|
describeAccount: describeMattermostAccount
|
|
25
25
|
},
|
|
26
|
-
gateway: { resolveGatewayAuthBypassPaths:
|
|
26
|
+
gateway: { resolveGatewayAuthBypassPaths: resolveMattermostGatewayAuthBypassPaths },
|
|
27
27
|
setup: mattermostSetupAdapter,
|
|
28
28
|
setupWizard: mattermostSetupWizard
|
|
29
29
|
};
|
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
import { C as hasConfiguredSecretInput, S as buildSecretInputSchema, g as normalizeMattermostBaseUrl, i as resolveMattermostReplyToMode, n as resolveDefaultMattermostAccountId, r as resolveMattermostAccount, t as listMattermostAccountIds } from "./accounts-
|
|
2
|
-
import { t as resolveMattermostGatewayAuthBypassPaths } from "./gateway-auth-bypass-
|
|
3
|
-
import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-
|
|
4
|
-
import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-
|
|
1
|
+
import { C as hasConfiguredSecretInput, S as buildSecretInputSchema, g as normalizeMattermostBaseUrl, i as resolveMattermostReplyToMode, n as resolveDefaultMattermostAccountId, r as resolveMattermostAccount, t as listMattermostAccountIds } from "./accounts-B2NRPlqr.js";
|
|
2
|
+
import { t as resolveMattermostGatewayAuthBypassPaths } from "./gateway-auth-bypass-CL1PxV3z.js";
|
|
3
|
+
import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-BaUvVh8e.js";
|
|
4
|
+
import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-B4R5Bmhv.js";
|
|
5
5
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
6
6
|
import { formatNormalizedAllowFromEntries } from "openclaw/plugin-sdk/allow-from";
|
|
7
7
|
import { createLoggedPairingApprovalNotifier } from "openclaw/plugin-sdk/channel-pairing";
|
|
8
8
|
import { createAccountStatusSink, createChannelMessageAdapterFromOutbound } from "openclaw/plugin-sdk/channel-outbound";
|
|
9
9
|
import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1, buildChannelOutboundSessionRoute, buildThreadAwareOutboundSessionRoute, stripChannelTargetPrefix, stripTargetKindPrefix } from "openclaw/plugin-sdk/core";
|
|
10
|
-
import { createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core";
|
|
11
|
-
import { createDangerousNameMatchingMutableAllowlistWarningCollector, createRestrictSendersChannelSecurity,
|
|
10
|
+
import { createChannelConfigUiHints, createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core";
|
|
11
|
+
import { buildChannelGroupsScopeTree, createDangerousNameMatchingMutableAllowlistWarningCollector, createRestrictSendersChannelSecurity, resolveScopeRequireMention } from "openclaw/plugin-sdk/channel-policy";
|
|
12
12
|
import { attachChannelToResult, createAttachedChannelResultAdapter } from "openclaw/plugin-sdk/channel-send-result";
|
|
13
13
|
import { createChannelDirectoryAdapter } from "openclaw/plugin-sdk/directory-runtime";
|
|
14
14
|
import { buildPassiveProbedChannelStatusSummary } from "openclaw/plugin-sdk/extension-shared";
|
|
15
|
-
import { normalizeMessagePresentation, renderMessagePresentationFallbackText, resolveMessagePresentationControlValue } from "openclaw/plugin-sdk/interactive-runtime";
|
|
15
|
+
import { normalizeMessagePresentation, renderMessagePresentationFallbackText, resolveMessagePresentationButtonAction, resolveMessagePresentationControlValue } from "openclaw/plugin-sdk/interactive-runtime";
|
|
16
16
|
import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
|
|
17
17
|
import { resolvePayloadMediaUrls, sendTextMediaPayload } from "openclaw/plugin-sdk/reply-payload";
|
|
18
18
|
import { isPrivateNetworkOptInEnabled } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
19
19
|
import { createComputedAccountStatusAdapter, createDefaultChannelRuntimeState } from "openclaw/plugin-sdk/status-helpers";
|
|
20
20
|
import { chunkTextForOutbound, sanitizeAssistantVisibleText } from "openclaw/plugin-sdk/text-chunking";
|
|
21
|
-
import {
|
|
21
|
+
import { createChannelApprovalAuth } from "openclaw/plugin-sdk/approval-auth-runtime";
|
|
22
22
|
import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
|
|
23
23
|
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
|
|
24
24
|
import { z } from "zod";
|
|
25
25
|
import { adaptScopedAccountAccessor, createScopedChannelConfigAdapter } from "openclaw/plugin-sdk/channel-config-helpers";
|
|
26
|
-
import { BlockStreamingCoalesceSchema, DmPolicySchema, GroupPolicySchema, MarkdownConfigSchema, buildChannelConfigSchema, requireOpenAllowFrom } from "openclaw/plugin-sdk/channel-config-
|
|
26
|
+
import { BlockStreamingCoalesceSchema, DmPolicySchema, GroupPolicySchema, MarkdownConfigSchema, buildChannelConfigSchema, requireOpenAllowFrom } from "openclaw/plugin-sdk/channel-config-schema";
|
|
27
27
|
import { applyAccountNameToChannelSection, applySetupAccountConfigPatch, createSetupTranslator, createStandardChannelSetupStatus, formatDocsLink, migrateBaseNameToDefaultAccount } from "openclaw/plugin-sdk/setup";
|
|
28
28
|
import { createSetupInputPresenceValidator } from "openclaw/plugin-sdk/setup-runtime";
|
|
29
29
|
//#region extensions/mattermost/src/approval-auth.ts
|
|
@@ -32,20 +32,16 @@ function normalizeMattermostApproverId(value) {
|
|
|
32
32
|
const lowered = normalizeLowercaseStringOrEmpty(String(value).trim().replace(/^(mattermost|user):/i, "").replace(/^@/, "").trim());
|
|
33
33
|
return MATTERMOST_USER_ID_RE.test(lowered) ? lowered : void 0;
|
|
34
34
|
}
|
|
35
|
-
const mattermostApprovalAuth =
|
|
35
|
+
const mattermostApprovalAuth = createChannelApprovalAuth({
|
|
36
36
|
channelLabel: "Mattermost",
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
resolveInputs: ({ cfg, accountId }) => {
|
|
38
|
+
return { allowFrom: resolveMattermostAccount({
|
|
39
39
|
cfg,
|
|
40
40
|
accountId
|
|
41
|
-
}).config;
|
|
42
|
-
return resolveApprovalApprovers({
|
|
43
|
-
allowFrom: account.allowFrom,
|
|
44
|
-
normalizeApprover: normalizeMattermostApproverId
|
|
45
|
-
});
|
|
41
|
+
}).config.allowFrom };
|
|
46
42
|
},
|
|
47
|
-
|
|
48
|
-
});
|
|
43
|
+
normalizeApprover: normalizeMattermostApproverId
|
|
44
|
+
}).approvalAuth;
|
|
49
45
|
//#endregion
|
|
50
46
|
//#region extensions/mattermost/src/channel-config-shared.ts
|
|
51
47
|
const mattermostMeta = {
|
|
@@ -162,17 +158,24 @@ const MattermostStreamingBlockSchema = z.object({
|
|
|
162
158
|
enabled: z.boolean().optional(),
|
|
163
159
|
coalesce: BlockStreamingCoalesceSchema.optional()
|
|
164
160
|
}).strict();
|
|
165
|
-
const MattermostStreamingSchema = z.
|
|
166
|
-
MattermostStreamingModeSchema,
|
|
167
|
-
z.
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
161
|
+
const MattermostStreamingSchema = z.object({
|
|
162
|
+
mode: MattermostStreamingModeSchema.optional(),
|
|
163
|
+
chunkMode: z.enum(["length", "newline"]).optional(),
|
|
164
|
+
preview: MattermostStreamingPreviewSchema.optional(),
|
|
165
|
+
progress: MattermostStreamingProgressSchema.optional(),
|
|
166
|
+
block: MattermostStreamingBlockSchema.optional()
|
|
167
|
+
}).strict();
|
|
168
|
+
const MattermostReplyToModeSchema = z.enum([
|
|
169
|
+
"off",
|
|
170
|
+
"first",
|
|
171
|
+
"all",
|
|
172
|
+
"batched"
|
|
175
173
|
]);
|
|
174
|
+
const MattermostReplyToModeByChatTypeSchema = z.object({
|
|
175
|
+
direct: MattermostReplyToModeSchema.optional(),
|
|
176
|
+
group: MattermostReplyToModeSchema.optional(),
|
|
177
|
+
channel: MattermostReplyToModeSchema.optional()
|
|
178
|
+
}).strict();
|
|
176
179
|
const MattermostAccountSchemaBase = z.object({
|
|
177
180
|
name: z.string().optional(),
|
|
178
181
|
capabilities: z.array(z.string()).optional(),
|
|
@@ -194,16 +197,9 @@ const MattermostAccountSchemaBase = z.object({
|
|
|
194
197
|
groupAllowFrom: z.array(z.union([z.string(), z.number()])).optional(),
|
|
195
198
|
groupPolicy: GroupPolicySchema.optional().default("allowlist"),
|
|
196
199
|
textChunkLimit: z.number().int().positive().optional(),
|
|
197
|
-
chunkMode: z.enum(["length", "newline"]).optional(),
|
|
198
200
|
streaming: MattermostStreamingSchema.optional(),
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
replyToMode: z.enum([
|
|
202
|
-
"off",
|
|
203
|
-
"first",
|
|
204
|
-
"all",
|
|
205
|
-
"batched"
|
|
206
|
-
]).optional(),
|
|
201
|
+
replyToMode: MattermostReplyToModeSchema.optional(),
|
|
202
|
+
replyToModeByChatType: MattermostReplyToModeByChatTypeSchema.optional(),
|
|
207
203
|
responsePrefix: z.string().optional(),
|
|
208
204
|
actions: z.object({ reactions: z.boolean().optional() }).optional(),
|
|
209
205
|
commands: MattermostSlashCommandsSchema,
|
|
@@ -241,10 +237,10 @@ const MattermostChannelConfigSchema = buildChannelConfigSchema(MattermostAccount
|
|
|
241
237
|
label: "Mattermost",
|
|
242
238
|
help: "Mattermost channel provider configuration for bot auth, access policy, slash commands, and preview streaming."
|
|
243
239
|
},
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
},
|
|
240
|
+
...createChannelConfigUiHints({
|
|
241
|
+
channelLabel: "Mattermost",
|
|
242
|
+
dmPolicy: { channelKey: "mattermost" }
|
|
243
|
+
}),
|
|
248
244
|
streaming: {
|
|
249
245
|
label: "Mattermost Streaming Mode",
|
|
250
246
|
help: "Unified Mattermost stream preview mode: \"off\" | \"partial\" | \"block\" | \"progress\". \"progress\" keeps a single editable progress draft until final delivery."
|
|
@@ -253,30 +249,10 @@ const MattermostChannelConfigSchema = buildChannelConfigSchema(MattermostAccount
|
|
|
253
249
|
label: "Mattermost Streaming Mode",
|
|
254
250
|
help: "Canonical Mattermost preview mode: \"off\" | \"partial\" | \"block\" | \"progress\"."
|
|
255
251
|
},
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
},
|
|
260
|
-
"streaming.progress.labels": {
|
|
261
|
-
label: "Mattermost Progress Label Pool",
|
|
262
|
-
help: "Candidate labels for streaming.progress.label=\"auto\". Leave unset to use OpenClaw built-in progress labels."
|
|
263
|
-
},
|
|
264
|
-
"streaming.progress.maxLines": {
|
|
265
|
-
label: "Mattermost Progress Max Lines",
|
|
266
|
-
help: "Maximum number of compact progress lines to keep below the draft label (default: 8)."
|
|
267
|
-
},
|
|
268
|
-
"streaming.progress.maxLineChars": {
|
|
269
|
-
label: "Mattermost Progress Max Line Chars",
|
|
270
|
-
help: "Maximum characters per compact progress line before truncation (default: 120). Prose cuts at word boundaries; commands and paths keep useful suffixes."
|
|
271
|
-
},
|
|
272
|
-
"streaming.progress.toolProgress": {
|
|
273
|
-
label: "Mattermost Progress Tool Lines",
|
|
274
|
-
help: "Show compact tool/progress lines in progress draft mode (default: true). Set false to keep only the label until final delivery."
|
|
275
|
-
},
|
|
276
|
-
"streaming.progress.commandText": {
|
|
277
|
-
label: "Mattermost Progress Command Text",
|
|
278
|
-
help: "Command/exec detail in progress draft lines: \"raw\" preserves released behavior; \"status\" shows only the tool label."
|
|
279
|
-
},
|
|
252
|
+
...createChannelConfigUiHints({
|
|
253
|
+
channelLabel: "Mattermost",
|
|
254
|
+
progress: {}
|
|
255
|
+
}),
|
|
280
256
|
"streaming.preview.toolProgress": {
|
|
281
257
|
label: "Mattermost Draft Tool Progress",
|
|
282
258
|
help: "Show tool/progress activity in the live draft preview post (default: true). Set false to hide interim tool updates while the draft preview stays active."
|
|
@@ -325,13 +301,11 @@ function resolveMattermostGroupRequireMention(params) {
|
|
|
325
301
|
cfg: params.cfg,
|
|
326
302
|
accountId: params.accountId
|
|
327
303
|
});
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
accountId: params.accountId,
|
|
334
|
-
requireMentionOverride
|
|
304
|
+
return resolveScopeRequireMention({
|
|
305
|
+
tree: buildChannelGroupsScopeTree(params.cfg, "mattermost", params.accountId),
|
|
306
|
+
path: params.groupId ? [params.groupId] : [],
|
|
307
|
+
requireMentionOverride: params.requireMentionOverride ?? account.requireMention,
|
|
308
|
+
overrideOrder: "after-config"
|
|
335
309
|
});
|
|
336
310
|
}
|
|
337
311
|
//#endregion
|
|
@@ -568,7 +542,7 @@ const mattermostSetupWizard = {
|
|
|
568
542
|
};
|
|
569
543
|
//#endregion
|
|
570
544
|
//#region extensions/mattermost/src/channel.ts
|
|
571
|
-
const loadMattermostChannelRuntime = createLazyRuntimeModule(() => import("./channel.runtime-
|
|
545
|
+
const loadMattermostChannelRuntime = createLazyRuntimeModule(() => import("./channel.runtime-Cbs451W2.js"));
|
|
572
546
|
function buildMattermostPresentationButtons(presentation) {
|
|
573
547
|
return presentation.blocks.filter((block) => block.type === "buttons").map((block) => block.buttons.flatMap((button) => {
|
|
574
548
|
if (button.action) return [];
|
|
@@ -590,8 +564,11 @@ const MATTERMOST_PRESENTATION_CAPABILITIES = {
|
|
|
590
564
|
divider: false,
|
|
591
565
|
limits: { text: { markdownDialect: "markdown" } }
|
|
592
566
|
};
|
|
593
|
-
function
|
|
594
|
-
return
|
|
567
|
+
function hasMattermostPresentationNavigation(presentation) {
|
|
568
|
+
return presentation.blocks.some((block) => block.type === "buttons" && block.buttons.some((button) => {
|
|
569
|
+
const action = resolveMessagePresentationButtonAction(button);
|
|
570
|
+
return action?.type === "url" || action?.type === "web-app";
|
|
571
|
+
}));
|
|
595
572
|
}
|
|
596
573
|
function readMattermostPresentationButtons(payload) {
|
|
597
574
|
const buttons = (payload.channelData?.mattermost)?.presentationButtons;
|
|
@@ -902,20 +879,21 @@ const mattermostOutbound = {
|
|
|
902
879
|
renderPresentation: ({ payload, presentation }) => {
|
|
903
880
|
if (payload.mediaUrls && payload.mediaUrls.length > 1) return null;
|
|
904
881
|
const buttons = buildMattermostPresentationButtons(presentation);
|
|
905
|
-
|
|
882
|
+
const hasButtons = buttons.some((row) => row.length > 0);
|
|
883
|
+
if (!hasButtons && !hasMattermostPresentationNavigation(presentation)) return null;
|
|
906
884
|
return {
|
|
907
885
|
...payload,
|
|
908
886
|
text: renderMessagePresentationFallbackText({
|
|
909
887
|
text: payload.text,
|
|
910
888
|
presentation
|
|
911
889
|
}),
|
|
912
|
-
channelData: {
|
|
890
|
+
...hasButtons ? { channelData: {
|
|
913
891
|
...payload.channelData,
|
|
914
892
|
mattermost: {
|
|
915
893
|
...payload.channelData?.mattermost,
|
|
916
894
|
presentationButtons: buttons
|
|
917
895
|
}
|
|
918
|
-
}
|
|
896
|
+
} } : {}
|
|
919
897
|
};
|
|
920
898
|
},
|
|
921
899
|
sendPayload: async (ctx) => {
|
|
@@ -1100,7 +1078,7 @@ const mattermostPlugin = createChatChannelPlugin({
|
|
|
1100
1078
|
})
|
|
1101
1079
|
}),
|
|
1102
1080
|
gateway: {
|
|
1103
|
-
resolveGatewayAuthBypassPaths:
|
|
1081
|
+
resolveGatewayAuthBypassPaths: resolveMattermostGatewayAuthBypassPaths,
|
|
1104
1082
|
startAccount: async (ctx) => {
|
|
1105
1083
|
const account = ctx.account;
|
|
1106
1084
|
const statusSink = createAccountStatusSink({
|
|
@@ -1150,9 +1128,10 @@ const mattermostPlugin = createChatChannelPlugin({
|
|
|
1150
1128
|
}),
|
|
1151
1129
|
resolveReplyTransport: ({ threadId, replyToId, replyToIsExplicit, replyDelivery }) => {
|
|
1152
1130
|
const ambientThreadId = threadId != null ? String(threadId) : void 0;
|
|
1153
|
-
const
|
|
1131
|
+
const isFlatDirect = replyDelivery?.chatType === "direct" && replyDelivery.replyToMode === "off";
|
|
1132
|
+
const resolvedThreadId = isFlatDirect ? void 0 : replyDelivery ? replyToIsExplicit ? replyToId ?? ambientThreadId : ambientThreadId ?? replyToId ?? void 0 : ambientThreadId ?? replyToId;
|
|
1154
1133
|
return {
|
|
1155
|
-
replyToId:
|
|
1134
|
+
replyToId: isFlatDirect ? null : resolvedThreadId,
|
|
1156
1135
|
threadId: resolvedThreadId ?? null
|
|
1157
1136
|
};
|
|
1158
1137
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as mattermostPlugin } from "./channel-plugin-runtime-
|
|
1
|
+
import { t as mattermostPlugin } from "./channel-plugin-runtime-BkzZgYxP.js";
|
|
2
2
|
export { mattermostPlugin };
|