mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-29 01:52:04 +00:00
fix: break mattermost runtime cycle
This commit is contained in:
@@ -1,2 +1,3 @@
|
||||
export { mattermostPlugin } from "./src/channel.js";
|
||||
// Keep this barrel helper-only so plugin-sdk facades do not pull the full
|
||||
// channel plugin (and its runtime state) into tests or other shared surfaces.
|
||||
export { isMattermostSenderAllowed } from "./src/mattermost/monitor-auth.js";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createAccountListHelpers } from "openclaw/plugin-sdk/account-helpers";
|
||||
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
|
||||
import { resolveMergedAccountConfig } from "openclaw/plugin-sdk/account-resolution";
|
||||
import { createAccountListHelpers, type OpenClawConfig } from "../runtime-api.js";
|
||||
import { normalizeResolvedSecretInputString, normalizeSecretInputString } from "../secret-input.js";
|
||||
import type {
|
||||
MattermostAccountConfig,
|
||||
@@ -9,6 +9,7 @@ import type {
|
||||
MattermostReplyToMode,
|
||||
} from "../types.js";
|
||||
import { normalizeMattermostBaseUrl } from "./client.js";
|
||||
import type { OpenClawConfig } from "./runtime-api.js";
|
||||
|
||||
export type MattermostTokenSource = "env" | "config" | "none";
|
||||
export type MattermostBaseUrlSource = "env" | "config" | "none";
|
||||
@@ -30,11 +31,15 @@ export type ResolvedMattermostAccount = {
|
||||
blockStreamingCoalesce?: MattermostAccountConfig["blockStreamingCoalesce"];
|
||||
};
|
||||
|
||||
const {
|
||||
listAccountIds: listMattermostAccountIds,
|
||||
resolveDefaultAccountId: resolveDefaultMattermostAccountId,
|
||||
} = createAccountListHelpers("mattermost");
|
||||
export { listMattermostAccountIds, resolveDefaultMattermostAccountId };
|
||||
const mattermostAccountHelpers = createAccountListHelpers("mattermost");
|
||||
|
||||
export function listMattermostAccountIds(cfg: OpenClawConfig): string[] {
|
||||
return mattermostAccountHelpers.listAccountIds(cfg);
|
||||
}
|
||||
|
||||
export function resolveDefaultMattermostAccountId(cfg: OpenClawConfig): string {
|
||||
return mattermostAccountHelpers.resolveDefaultAccountId(cfg);
|
||||
}
|
||||
|
||||
function mergeMattermostAccountConfig(
|
||||
cfg: OpenClawConfig,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import type { ChannelDirectoryEntry, OpenClawConfig, RuntimeEnv } from "../runtime-api.js";
|
||||
import { listMattermostAccountIds, resolveMattermostAccount } from "./accounts.js";
|
||||
import {
|
||||
createMattermostClient,
|
||||
@@ -7,6 +6,7 @@ import {
|
||||
type MattermostClient,
|
||||
type MattermostUser,
|
||||
} from "./client.js";
|
||||
import type { ChannelDirectoryEntry, OpenClawConfig, RuntimeEnv } from "./runtime-api.js";
|
||||
|
||||
export type MattermostDirectoryParams = {
|
||||
cfg: OpenClawConfig;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { createHmac, timingSafeEqual } from "node:crypto";
|
||||
import type { IncomingMessage, ServerResponse } from "node:http";
|
||||
import { isTrustedProxyAddress, resolveClientIp, type OpenClawConfig } from "../runtime-api.js";
|
||||
import { getMattermostRuntime } from "../runtime.js";
|
||||
import { updateMattermostPost, type MattermostClient, type MattermostPost } from "./client.js";
|
||||
import { isTrustedProxyAddress, resolveClientIp, type OpenClawConfig } from "./runtime-api.js";
|
||||
|
||||
const INTERACTION_MAX_BODY_BYTES = 64 * 1024;
|
||||
const INTERACTION_BODY_TIMEOUT_MS = 10_000;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { createHash } from "node:crypto";
|
||||
import type { MattermostInteractiveButtonInput } from "./interactions.js";
|
||||
import {
|
||||
loadSessionStore,
|
||||
normalizeProviderId,
|
||||
@@ -6,8 +7,7 @@ import {
|
||||
resolveStoredModelOverride,
|
||||
type ModelsProviderData,
|
||||
type OpenClawConfig,
|
||||
} from "../runtime-api.js";
|
||||
import type { MattermostInteractiveButtonInput } from "./interactions.js";
|
||||
} from "./runtime-api.js";
|
||||
|
||||
const MATTERMOST_MODEL_PICKER_CONTEXT_KEY = "oc_model_picker";
|
||||
const MODELS_PAGE_SIZE = 8;
|
||||
|
||||
@@ -6,13 +6,17 @@ const resolveAllowlistMatchSimple = vi.hoisted(() => vi.fn());
|
||||
const resolveControlCommandGate = vi.hoisted(() => vi.fn());
|
||||
const resolveEffectiveAllowFromLists = vi.hoisted(() => vi.fn());
|
||||
|
||||
vi.mock("../runtime-api.js", () => ({
|
||||
evaluateSenderGroupAccessForPolicy,
|
||||
isDangerousNameMatchingEnabled,
|
||||
resolveAllowlistMatchSimple,
|
||||
resolveControlCommandGate,
|
||||
resolveEffectiveAllowFromLists,
|
||||
}));
|
||||
vi.mock("./runtime-api.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("./runtime-api.js")>();
|
||||
return {
|
||||
...actual,
|
||||
evaluateSenderGroupAccessForPolicy,
|
||||
isDangerousNameMatchingEnabled,
|
||||
resolveAllowlistMatchSimple,
|
||||
resolveControlCommandGate,
|
||||
resolveEffectiveAllowFromLists,
|
||||
};
|
||||
});
|
||||
|
||||
describe("mattermost monitor auth", () => {
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import type { OpenClawConfig } from "../runtime-api.js";
|
||||
import type { ResolvedMattermostAccount } from "./accounts.js";
|
||||
import type { MattermostChannel } from "./client.js";
|
||||
import type { OpenClawConfig } from "./runtime-api.js";
|
||||
import {
|
||||
evaluateSenderGroupAccessForPolicy,
|
||||
isDangerousNameMatchingEnabled,
|
||||
resolveAllowlistMatchSimple,
|
||||
resolveControlCommandGate,
|
||||
resolveEffectiveAllowFromLists,
|
||||
} from "../runtime-api.js";
|
||||
import type { ResolvedMattermostAccount } from "./accounts.js";
|
||||
import type { MattermostChannel } from "./client.js";
|
||||
} from "./runtime-api.js";
|
||||
|
||||
export function normalizeMattermostAllowEntry(entry: string): string {
|
||||
const trimmed = entry.trim();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ChatType, OpenClawConfig } from "../runtime-api.js";
|
||||
import type { ChatType, OpenClawConfig } from "./runtime-api.js";
|
||||
|
||||
export function mapMattermostChannelTypeToChatType(channelType?: string | null): ChatType {
|
||||
if (!channelType) {
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import {
|
||||
createDedupeCache,
|
||||
formatInboundFromLabel as formatInboundFromLabelShared,
|
||||
rawDataToString,
|
||||
resolveThreadSessionKeys as resolveThreadSessionKeysShared,
|
||||
type OpenClawConfig,
|
||||
} from "../runtime-api.js";
|
||||
export { createDedupeCache, rawDataToString } from "../runtime-api.js";
|
||||
} from "./runtime-api.js";
|
||||
|
||||
export { createDedupeCache, rawDataToString };
|
||||
|
||||
export type ResponsePrefixContext = {
|
||||
model?: string;
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import {
|
||||
listSkillCommandsForAgents,
|
||||
parseStrictPositiveInteger,
|
||||
type OpenClawConfig,
|
||||
type RuntimeEnv,
|
||||
} from "../runtime-api.js";
|
||||
import type { ResolvedMattermostAccount } from "./accounts.js";
|
||||
import {
|
||||
fetchMattermostUserTeams,
|
||||
normalizeMattermostBaseUrl,
|
||||
type MattermostClient,
|
||||
} from "./client.js";
|
||||
import {
|
||||
listSkillCommandsForAgents,
|
||||
parseStrictPositiveInteger,
|
||||
type OpenClawConfig,
|
||||
type RuntimeEnv,
|
||||
} from "./runtime-api.js";
|
||||
import {
|
||||
DEFAULT_COMMAND_SPECS,
|
||||
isSlashCommandsEnabled,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { safeParseJsonWithSchema, safeParseWithSchema } from "openclaw/plugin-sdk/extension-shared";
|
||||
import { z } from "openclaw/plugin-sdk/zod";
|
||||
import WebSocket from "ws";
|
||||
import type { ChannelAccountSnapshot, RuntimeEnv } from "../runtime-api.js";
|
||||
import { MattermostPostSchema, type MattermostPost } from "./client.js";
|
||||
import { rawDataToString } from "./monitor-helpers.js";
|
||||
import type { ChannelAccountSnapshot, RuntimeEnv } from "./runtime-api.js";
|
||||
|
||||
export type MattermostEventPayload = {
|
||||
event?: string;
|
||||
|
||||
@@ -1,33 +1,3 @@
|
||||
import type {
|
||||
ChannelAccountSnapshot,
|
||||
ChatType,
|
||||
OpenClawConfig,
|
||||
ReplyPayload,
|
||||
RuntimeEnv,
|
||||
} from "../runtime-api.js";
|
||||
import {
|
||||
buildAgentMediaPayload,
|
||||
buildModelsProviderData,
|
||||
DM_GROUP_ACCESS_REASON,
|
||||
createChannelPairingController,
|
||||
createChannelReplyPipeline,
|
||||
logInboundDrop,
|
||||
logTypingFailure,
|
||||
buildPendingHistoryContextFromMap,
|
||||
clearHistoryEntriesIfEnabled,
|
||||
DEFAULT_GROUP_HISTORY_LIMIT,
|
||||
recordPendingHistoryEntryIfEnabled,
|
||||
isDangerousNameMatchingEnabled,
|
||||
registerPluginHttpRoute,
|
||||
resolveControlCommandGate,
|
||||
readStoreAllowFromForDmPolicy,
|
||||
resolveDmGroupAccessWithLists,
|
||||
resolveAllowlistProviderRuntimeGroupPolicy,
|
||||
resolveDefaultGroupPolicy,
|
||||
resolveChannelMediaMaxBytes,
|
||||
warnMissingProviderGroupPolicyFallbackOnce,
|
||||
type HistoryEntry,
|
||||
} from "../runtime-api.js";
|
||||
import { getMattermostRuntime } from "../runtime.js";
|
||||
import { resolveMattermostAccount, resolveMattermostReplyToMode } from "./accounts.js";
|
||||
import {
|
||||
@@ -82,6 +52,36 @@ import {
|
||||
} from "./monitor-websocket.js";
|
||||
import { runWithReconnect } from "./reconnect.js";
|
||||
import { deliverMattermostReplyPayload } from "./reply-delivery.js";
|
||||
import type {
|
||||
ChannelAccountSnapshot,
|
||||
ChatType,
|
||||
OpenClawConfig,
|
||||
ReplyPayload,
|
||||
RuntimeEnv,
|
||||
} from "./runtime-api.js";
|
||||
import {
|
||||
buildAgentMediaPayload,
|
||||
buildModelsProviderData,
|
||||
DM_GROUP_ACCESS_REASON,
|
||||
createChannelPairingController,
|
||||
createChannelReplyPipeline,
|
||||
logInboundDrop,
|
||||
logTypingFailure,
|
||||
buildPendingHistoryContextFromMap,
|
||||
clearHistoryEntriesIfEnabled,
|
||||
DEFAULT_GROUP_HISTORY_LIMIT,
|
||||
recordPendingHistoryEntryIfEnabled,
|
||||
isDangerousNameMatchingEnabled,
|
||||
registerPluginHttpRoute,
|
||||
resolveControlCommandGate,
|
||||
readStoreAllowFromForDmPolicy,
|
||||
resolveDmGroupAccessWithLists,
|
||||
resolveAllowlistProviderRuntimeGroupPolicy,
|
||||
resolveDefaultGroupPolicy,
|
||||
resolveChannelMediaMaxBytes,
|
||||
warnMissingProviderGroupPolicyFallbackOnce,
|
||||
type HistoryEntry,
|
||||
} from "./runtime-api.js";
|
||||
import { sendMessageMattermost } from "./send.js";
|
||||
import { cleanupSlashCommands } from "./slash-commands.js";
|
||||
import { deactivateSlashCommands, getSlashCommandState } from "./slash-state.js";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { BaseProbeResult } from "../runtime-api.js";
|
||||
import { normalizeMattermostBaseUrl, readMattermostError, type MattermostUser } from "./client.js";
|
||||
import type { BaseProbeResult } from "./runtime-api.js";
|
||||
|
||||
export type MattermostProbe = BaseProbeResult & {
|
||||
status?: number | null;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import type { OpenClawConfig } from "../runtime-api.js";
|
||||
import { resolveMattermostAccount } from "./accounts.js";
|
||||
import {
|
||||
createMattermostClient,
|
||||
@@ -6,6 +5,7 @@ import {
|
||||
type MattermostClient,
|
||||
type MattermostFetch,
|
||||
} from "./client.js";
|
||||
import type { OpenClawConfig } from "./runtime-api.js";
|
||||
|
||||
type Result = { ok: true } | { ok: false; error: string };
|
||||
type ReactionParams = {
|
||||
|
||||
@@ -2,8 +2,12 @@ import {
|
||||
deliverTextOrMediaReply,
|
||||
resolveSendableOutboundReplyParts,
|
||||
} from "openclaw/plugin-sdk/reply-payload";
|
||||
import type { OpenClawConfig, PluginRuntime, ReplyPayload } from "../runtime-api.js";
|
||||
import { getAgentScopedMediaLocalRoots } from "../runtime-api.js";
|
||||
import {
|
||||
getAgentScopedMediaLocalRoots,
|
||||
type OpenClawConfig,
|
||||
type PluginRuntime,
|
||||
type ReplyPayload,
|
||||
} from "./runtime-api.js";
|
||||
|
||||
type MarkdownTableMode = Parameters<PluginRuntime["channel"]["text"]["convertMarkdownTables"]>[1];
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { convertMarkdownTables } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { loadOutboundMediaFromUrl, type OpenClawConfig } from "../runtime-api.js";
|
||||
import { getMattermostRuntime } from "../runtime.js";
|
||||
import { resolveMattermostAccount } from "./accounts.js";
|
||||
import {
|
||||
@@ -22,6 +21,7 @@ import {
|
||||
setInteractionSecret,
|
||||
type MattermostInteractiveButtonInput,
|
||||
} from "./interactions.js";
|
||||
import { loadOutboundMediaFromUrl, type OpenClawConfig } from "./runtime-api.js";
|
||||
import { isMattermostId, resolveMattermostOpaqueTarget } from "./target-resolution.js";
|
||||
|
||||
export type MattermostSendOpts = {
|
||||
|
||||
@@ -39,14 +39,18 @@ const mockState = vi.hoisted(() => ({
|
||||
normalizeMattermostAllowList: vi.fn((value: unknown) => value),
|
||||
}));
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/mattermost", () => ({
|
||||
buildModelsProviderData: mockState.buildModelsProviderData,
|
||||
createReplyPrefixOptions: vi.fn(() => ({})),
|
||||
createTypingCallbacks: vi.fn(() => ({ onReplyStart: vi.fn() })),
|
||||
isRequestBodyLimitError: vi.fn(() => false),
|
||||
logTypingFailure: vi.fn(),
|
||||
readRequestBodyWithLimit: mockState.readRequestBodyWithLimit,
|
||||
}));
|
||||
vi.mock("./runtime-api.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("./runtime-api.js")>();
|
||||
return {
|
||||
...actual,
|
||||
buildModelsProviderData: mockState.buildModelsProviderData,
|
||||
createReplyPrefixOptions: vi.fn(() => ({})),
|
||||
createTypingCallbacks: vi.fn(() => ({ onReplyStart: vi.fn() })),
|
||||
isRequestBodyLimitError: vi.fn(() => false),
|
||||
logTypingFailure: vi.fn(),
|
||||
readRequestBodyWithLimit: mockState.readRequestBodyWithLimit,
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../runtime.js", () => ({
|
||||
getMattermostRuntime: () => ({
|
||||
|
||||
@@ -7,16 +7,6 @@
|
||||
|
||||
import type { IncomingMessage, ServerResponse } from "node:http";
|
||||
import type { ResolvedMattermostAccount } from "../mattermost/accounts.js";
|
||||
import {
|
||||
buildModelsProviderData,
|
||||
createChannelReplyPipeline,
|
||||
isRequestBodyLimitError,
|
||||
logTypingFailure,
|
||||
readRequestBodyWithLimit,
|
||||
type OpenClawConfig,
|
||||
type ReplyPayload,
|
||||
type RuntimeEnv,
|
||||
} from "../runtime-api.js";
|
||||
import { getMattermostRuntime } from "../runtime.js";
|
||||
import {
|
||||
createMattermostClient,
|
||||
@@ -37,6 +27,16 @@ import {
|
||||
normalizeMattermostAllowList,
|
||||
} from "./monitor-auth.js";
|
||||
import { deliverMattermostReplyPayload } from "./reply-delivery.js";
|
||||
import {
|
||||
buildModelsProviderData,
|
||||
createChannelReplyPipeline,
|
||||
isRequestBodyLimitError,
|
||||
logTypingFailure,
|
||||
readRequestBodyWithLimit,
|
||||
type OpenClawConfig,
|
||||
type ReplyPayload,
|
||||
type RuntimeEnv,
|
||||
} from "./runtime-api.js";
|
||||
import { sendMessageMattermost } from "./send.js";
|
||||
import {
|
||||
parseSlashCommandPayload,
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
*/
|
||||
|
||||
import type { IncomingMessage, ServerResponse } from "node:http";
|
||||
import type { OpenClawPluginApi } from "../runtime-api.js";
|
||||
import type { MattermostConfig } from "../types.js";
|
||||
import type { ResolvedMattermostAccount } from "./accounts.js";
|
||||
import type { OpenClawPluginApi } from "./runtime-api.js";
|
||||
import { resolveSlashCommandConfig, type MattermostRegisteredCommand } from "./slash-commands.js";
|
||||
import { createSlashCommandHttpHandler } from "./slash-http.js";
|
||||
|
||||
@@ -87,8 +87,8 @@ export function activateSlashCommands(params: {
|
||||
registeredCommands: MattermostRegisteredCommand[];
|
||||
triggerMap?: Map<string, string>;
|
||||
api: {
|
||||
cfg: import("../runtime-api.js").OpenClawConfig;
|
||||
runtime: import("../runtime-api.js").RuntimeEnv;
|
||||
cfg: import("./runtime-api.js").OpenClawConfig;
|
||||
runtime: import("./runtime-api.js").RuntimeEnv;
|
||||
};
|
||||
log?: (msg: string) => void;
|
||||
}) {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { OpenClawConfig } from "../runtime-api.js";
|
||||
import { resolveMattermostAccount } from "./accounts.js";
|
||||
import {
|
||||
createMattermostClient,
|
||||
fetchMattermostUser,
|
||||
normalizeMattermostBaseUrl,
|
||||
} from "./client.js";
|
||||
import type { OpenClawConfig } from "./runtime-api.js";
|
||||
|
||||
export type MattermostOpaqueTargetResolution = {
|
||||
kind: "user" | "channel";
|
||||
|
||||
@@ -19,9 +19,13 @@ async function loadExecApprovalSurfaceModule() {
|
||||
normalizeMessageChannelMock.mockImplementation((value?: string | null) =>
|
||||
typeof value === "string" ? value.trim().toLowerCase() : undefined,
|
||||
);
|
||||
vi.doMock("../config/config.js", () => ({
|
||||
loadConfig: (...args: unknown[]) => loadConfigMock(...args),
|
||||
}));
|
||||
vi.doMock("../config/config.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../config/config.js")>();
|
||||
return {
|
||||
...actual,
|
||||
loadConfig: (...args: unknown[]) => loadConfigMock(...args),
|
||||
};
|
||||
});
|
||||
vi.doMock("../channels/plugins/index.js", () => ({
|
||||
getChannelPlugin: (...args: unknown[]) => getChannelPluginMock(...args),
|
||||
listChannelPlugins: (...args: unknown[]) => listChannelPluginsMock(...args),
|
||||
|
||||
@@ -2,9 +2,13 @@ import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const loadConfigMock = vi.hoisted(() => vi.fn());
|
||||
|
||||
vi.mock("../config/config.js", () => ({
|
||||
loadConfig: () => loadConfigMock(),
|
||||
}));
|
||||
vi.mock("../config/config.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../config/config.js")>();
|
||||
return {
|
||||
...actual,
|
||||
loadConfig: () => loadConfigMock(),
|
||||
};
|
||||
});
|
||||
|
||||
const originalArgv = process.argv;
|
||||
|
||||
|
||||
@@ -96,4 +96,3 @@ export { getAgentScopedMediaLocalRoots } from "../media/local-roots.js";
|
||||
export { loadOutboundMediaFromUrl } from "./outbound-media.js";
|
||||
export { createChannelPairingController } from "./channel-pairing.js";
|
||||
export { isRequestBodyLimitError, readRequestBodyWithLimit } from "../infra/http-body.js";
|
||||
export { isMattermostSenderAllowed } from "./mattermost-policy.js";
|
||||
|
||||
Reference in New Issue
Block a user