Skip to content

Commit 4829d30

Browse files
committed
fix(mattermost): bound slash callback env port
1 parent 7a381b8 commit 4829d30

4 files changed

Lines changed: 33 additions & 7 deletions

File tree

extensions/mattermost/src/mattermost/monitor-slash.test.ts

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
22

33
const listSkillCommandsForAgents = vi.hoisted(() => vi.fn());
4-
const parseStrictPositiveInteger = vi.hoisted(() => vi.fn());
4+
const parseTcpPort = vi.hoisted(() => vi.fn());
55
const fetchMattermostUserTeams = vi.hoisted(() => vi.fn());
66
const normalizeMattermostBaseUrl = vi.hoisted(() => vi.fn((value: string | undefined) => value));
77
const isSlashCommandsEnabled = vi.hoisted(() => vi.fn());
@@ -12,7 +12,7 @@ const activateSlashCommands = vi.hoisted(() => vi.fn());
1212

1313
vi.mock("./runtime-api.js", () => ({
1414
listSkillCommandsForAgents,
15-
parseStrictPositiveInteger,
15+
parseTcpPort,
1616
}));
1717

1818
vi.mock("./client.js", async () => {
@@ -59,7 +59,7 @@ describe("mattermost monitor slash", () => {
5959

6060
beforeEach(() => {
6161
listSkillCommandsForAgents.mockReset();
62-
parseStrictPositiveInteger.mockReset();
62+
parseTcpPort.mockReset();
6363
fetchMattermostUserTeams.mockReset();
6464
normalizeMattermostBaseUrl.mockClear();
6565
isSlashCommandsEnabled.mockReset();
@@ -94,7 +94,7 @@ describe("mattermost monitor slash", () => {
9494
vi.stubEnv("OPENCLAW_GATEWAY_PORT", "18888");
9595
resolveSlashCommandConfig.mockReturnValue({ enabled: true, nativeSkills: true });
9696
isSlashCommandsEnabled.mockReturnValue(true);
97-
parseStrictPositiveInteger.mockReturnValue(18888);
97+
parseTcpPort.mockReturnValue(18888);
9898
fetchMattermostUserTeams.mockResolvedValue([{ id: "team-1" }, { id: "team-2" }]);
9999
resolveCallbackUrl.mockReturnValue("https://openclaw.test/slash");
100100
listSkillCommandsForAgents.mockReturnValue([
@@ -166,10 +166,34 @@ describe("mattermost monitor slash", () => {
166166
);
167167
});
168168

169+
it("falls back to the configured gateway port when the env port is out of range", async () => {
170+
vi.stubEnv("OPENCLAW_GATEWAY_PORT", "65536");
171+
resolveSlashCommandConfig.mockReturnValue({ enabled: true, nativeSkills: false });
172+
isSlashCommandsEnabled.mockReturnValue(true);
173+
parseTcpPort.mockReturnValue(null);
174+
fetchMattermostUserTeams.mockResolvedValue([{ id: "team-1" }]);
175+
resolveCallbackUrl.mockReturnValue("https://openclaw.test/slash");
176+
registerSlashCommands.mockResolvedValue([{ token: "token-1", trigger: "ping" }]);
177+
178+
await registerMattermostMonitorSlashCommands({
179+
client: {} as never,
180+
cfg: { gateway: { port: 18789 } } as never,
181+
runtime: { log: vi.fn(), error: vi.fn() } as never,
182+
account: { config: { commands: {} }, accountId: "default" } as never,
183+
baseUrl: "https://chat.example.com",
184+
botUserId: "bot-user",
185+
});
186+
187+
expect(parseTcpPort).toHaveBeenCalledWith("65536");
188+
expect(resolveCallbackUrl).toHaveBeenCalledWith(
189+
expect.objectContaining({ gatewayPort: 18789 }),
190+
);
191+
});
192+
169193
it("warns on loopback callback urls and reports partial team failures", async () => {
170194
resolveSlashCommandConfig.mockReturnValue({ enabled: true, nativeSkills: false });
171195
isSlashCommandsEnabled.mockReturnValue(true);
172-
parseStrictPositiveInteger.mockReturnValue(undefined);
196+
parseTcpPort.mockReturnValue(null);
173197
fetchMattermostUserTeams.mockResolvedValue([{ id: "team-1" }, { id: "team-2" }]);
174198
resolveCallbackUrl.mockReturnValue("http://127.0.0.1:18789/slash");
175199
registerSlashCommands

extensions/mattermost/src/mattermost/monitor-slash.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
} from "./client.js";
88
import {
99
listSkillCommandsForAgents,
10-
parseStrictPositiveInteger,
10+
parseTcpPort,
1111
type OpenClawConfig,
1212
type RuntimeEnv,
1313
} from "./runtime-api.js";
@@ -149,7 +149,7 @@ export async function registerMattermostMonitorSlashCommands(params: {
149149

150150
try {
151151
const teams = await fetchMattermostUserTeams(params.client, params.botUserId);
152-
const envPort = parseStrictPositiveInteger(process.env.OPENCLAW_GATEWAY_PORT?.trim());
152+
const envPort = parseTcpPort(process.env.OPENCLAW_GATEWAY_PORT);
153153
const slashGatewayPort = envPort ?? params.cfg.gateway?.port ?? 18789;
154154
const slashCallbackUrl = resolveCallbackUrl({
155155
config: slashConfig,

extensions/mattermost/src/mattermost/runtime-api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,4 @@ export {
4747
parseStrictPositiveInteger,
4848
resolveClientIp,
4949
} from "openclaw/plugin-sdk/core";
50+
export { parseTcpPort } from "openclaw/plugin-sdk/number-runtime";

src/plugin-sdk/number-runtime.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ export {
1010
parseStrictNonNegativeInteger,
1111
parseStrictPositiveInteger,
1212
} from "../shared/number-coercion.js";
13+
export { MAX_TCP_PORT, parseTcpPort } from "../infra/tcp-port.js";

0 commit comments

Comments
 (0)