mirror of https://github.com/openclaw/openclaw.git
refactor: share discord exec approval helpers
This commit is contained in:
parent
fd340a88d6
commit
fd5243c27e
|
|
@ -116,6 +116,62 @@ function createHandler(config: DiscordExecApprovalConfig, accountId = "default")
|
|||
});
|
||||
}
|
||||
|
||||
function mockSuccessfulDmDelivery(params?: {
|
||||
noteChannelId?: string;
|
||||
expectedNoteText?: string;
|
||||
throwOnUnexpectedRoute?: boolean;
|
||||
}) {
|
||||
mockRestPost.mockImplementation(
|
||||
async (route: string, requestParams?: { body?: { content?: string } }) => {
|
||||
if (params?.noteChannelId && route === Routes.channelMessages(params.noteChannelId)) {
|
||||
if (params.expectedNoteText) {
|
||||
expect(requestParams?.body?.content).toContain(params.expectedNoteText);
|
||||
}
|
||||
return { id: "note-1", channel_id: params.noteChannelId };
|
||||
}
|
||||
if (route === Routes.userChannels()) {
|
||||
return { id: "dm-1" };
|
||||
}
|
||||
if (route === Routes.channelMessages("dm-1")) {
|
||||
return { id: "msg-1", channel_id: "dm-1" };
|
||||
}
|
||||
if (params?.throwOnUnexpectedRoute) {
|
||||
throw new Error(`unexpected route: ${route}`);
|
||||
}
|
||||
return { id: "msg-unknown" };
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
async function expectGatewayAuthStart(params: {
|
||||
handler: DiscordExecApprovalHandler;
|
||||
expectedUrl: string;
|
||||
expectedSource: "cli" | "env";
|
||||
expectedToken?: string;
|
||||
expectedPassword?: string;
|
||||
}) {
|
||||
await params.handler.start();
|
||||
|
||||
expect(mockResolveGatewayConnectionAuth).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
env: process.env,
|
||||
urlOverride: params.expectedUrl,
|
||||
urlOverrideSource: params.expectedSource,
|
||||
}),
|
||||
);
|
||||
|
||||
const expectedClientParams: Record<string, unknown> = {
|
||||
url: params.expectedUrl,
|
||||
};
|
||||
if (params.expectedToken !== undefined) {
|
||||
expectedClientParams.token = params.expectedToken;
|
||||
}
|
||||
if (params.expectedPassword !== undefined) {
|
||||
expectedClientParams.password = params.expectedPassword;
|
||||
}
|
||||
expect(mockGatewayClientCtor).toHaveBeenCalledWith(expect.objectContaining(expectedClientParams));
|
||||
}
|
||||
|
||||
type ExecApprovalHandlerInternals = {
|
||||
pending: Map<
|
||||
string,
|
||||
|
|
@ -772,15 +828,7 @@ describe("DiscordExecApprovalHandler delivery routing", () => {
|
|||
});
|
||||
const internals = getHandlerInternals(handler);
|
||||
|
||||
mockRestPost.mockImplementation(async (route: string) => {
|
||||
if (route === Routes.userChannels()) {
|
||||
return { id: "dm-1" };
|
||||
}
|
||||
if (route === Routes.channelMessages("dm-1")) {
|
||||
return { id: "msg-1", channel_id: "dm-1" };
|
||||
}
|
||||
return { id: "msg-unknown" };
|
||||
});
|
||||
mockSuccessfulDmDelivery();
|
||||
|
||||
const request = createRequest({ sessionKey: "agent:main:discord:dm:123" });
|
||||
await internals.handleApprovalRequested(request);
|
||||
|
|
@ -809,21 +857,11 @@ describe("DiscordExecApprovalHandler delivery routing", () => {
|
|||
});
|
||||
const internals = getHandlerInternals(handler);
|
||||
|
||||
mockRestPost.mockImplementation(
|
||||
async (route: string, params?: { body?: { content?: string } }) => {
|
||||
if (route === Routes.channelMessages("999888777")) {
|
||||
expect(params?.body?.content).toContain("I sent the allowed approvers DMs");
|
||||
return { id: "note-1", channel_id: "999888777" };
|
||||
}
|
||||
if (route === Routes.userChannels()) {
|
||||
return { id: "dm-1" };
|
||||
}
|
||||
if (route === Routes.channelMessages("dm-1")) {
|
||||
return { id: "msg-1", channel_id: "dm-1" };
|
||||
}
|
||||
throw new Error(`unexpected route: ${route}`);
|
||||
},
|
||||
);
|
||||
mockSuccessfulDmDelivery({
|
||||
noteChannelId: "999888777",
|
||||
expectedNoteText: "I sent the allowed approvers DMs",
|
||||
throwOnUnexpectedRoute: true,
|
||||
});
|
||||
|
||||
await internals.handleApprovalRequested(createRequest());
|
||||
|
||||
|
|
@ -853,15 +891,7 @@ describe("DiscordExecApprovalHandler delivery routing", () => {
|
|||
});
|
||||
const internals = getHandlerInternals(handler);
|
||||
|
||||
mockRestPost.mockImplementation(async (route: string) => {
|
||||
if (route === Routes.userChannels()) {
|
||||
return { id: "dm-1" };
|
||||
}
|
||||
if (route === Routes.channelMessages("dm-1")) {
|
||||
return { id: "msg-1", channel_id: "dm-1" };
|
||||
}
|
||||
throw new Error(`unexpected route: ${route}`);
|
||||
});
|
||||
mockSuccessfulDmDelivery({ throwOnUnexpectedRoute: true });
|
||||
|
||||
await internals.handleApprovalRequested(
|
||||
createRequest({ sessionKey: "agent:main:discord:dm:123" }),
|
||||
|
|
@ -890,22 +920,13 @@ describe("DiscordExecApprovalHandler gateway auth resolution", () => {
|
|||
cfg: { session: { store: STORE_PATH } },
|
||||
});
|
||||
|
||||
await handler.start();
|
||||
|
||||
expect(mockResolveGatewayConnectionAuth).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
env: process.env,
|
||||
urlOverride: "wss://override.example/ws",
|
||||
urlOverrideSource: "cli",
|
||||
}),
|
||||
);
|
||||
expect(mockGatewayClientCtor).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
url: "wss://override.example/ws",
|
||||
token: "resolved-token",
|
||||
password: "resolved-password", // pragma: allowlist secret
|
||||
}),
|
||||
);
|
||||
await expectGatewayAuthStart({
|
||||
handler,
|
||||
expectedUrl: "wss://override.example/ws",
|
||||
expectedSource: "cli",
|
||||
expectedToken: "resolved-token",
|
||||
expectedPassword: "resolved-password", // pragma: allowlist secret
|
||||
});
|
||||
|
||||
await handler.stop();
|
||||
});
|
||||
|
|
@ -921,20 +942,11 @@ describe("DiscordExecApprovalHandler gateway auth resolution", () => {
|
|||
cfg: { session: { store: STORE_PATH } },
|
||||
});
|
||||
|
||||
await handler.start();
|
||||
|
||||
expect(mockResolveGatewayConnectionAuth).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
env: process.env,
|
||||
urlOverride: "wss://gateway-from-env.example/ws",
|
||||
urlOverrideSource: "env",
|
||||
}),
|
||||
);
|
||||
expect(mockGatewayClientCtor).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
url: "wss://gateway-from-env.example/ws",
|
||||
}),
|
||||
);
|
||||
await expectGatewayAuthStart({
|
||||
handler,
|
||||
expectedUrl: "wss://gateway-from-env.example/ws",
|
||||
expectedSource: "env",
|
||||
});
|
||||
|
||||
await handler.stop();
|
||||
} finally {
|
||||
|
|
|
|||
|
|
@ -252,17 +252,30 @@ function formatOptionalCommandPreview(
|
|||
return formatCommandPreview(commandText, maxChars);
|
||||
}
|
||||
|
||||
function resolveExecApprovalPreviews(
|
||||
request: ExecApprovalRequest["request"],
|
||||
maxChars: number,
|
||||
secondaryMaxChars: number,
|
||||
): { commandPreview: string; commandSecondaryPreview: string | null } {
|
||||
const { commandText, commandPreview: secondaryPreview } =
|
||||
resolveExecApprovalCommandDisplay(request);
|
||||
return {
|
||||
commandPreview: formatCommandPreview(commandText, maxChars),
|
||||
commandSecondaryPreview: formatOptionalCommandPreview(secondaryPreview, secondaryMaxChars),
|
||||
};
|
||||
}
|
||||
|
||||
function createExecApprovalRequestContainer(params: {
|
||||
request: ExecApprovalRequest;
|
||||
cfg: OpenClawConfig;
|
||||
accountId: string;
|
||||
actionRow?: Row<Button>;
|
||||
}): ExecApprovalContainer {
|
||||
const { commandText, commandPreview: secondaryPreview } = resolveExecApprovalCommandDisplay(
|
||||
const { commandPreview, commandSecondaryPreview } = resolveExecApprovalPreviews(
|
||||
params.request.request,
|
||||
1000,
|
||||
500,
|
||||
);
|
||||
const commandPreview = formatCommandPreview(commandText, 1000);
|
||||
const commandSecondaryPreview = formatOptionalCommandPreview(secondaryPreview, 500);
|
||||
const expiresAtSeconds = Math.max(0, Math.floor(params.request.expiresAtMs / 1000));
|
||||
|
||||
return new ExecApprovalContainer({
|
||||
|
|
@ -286,11 +299,11 @@ function createResolvedContainer(params: {
|
|||
cfg: OpenClawConfig;
|
||||
accountId: string;
|
||||
}): ExecApprovalContainer {
|
||||
const { commandText, commandPreview: secondaryPreview } = resolveExecApprovalCommandDisplay(
|
||||
const { commandPreview, commandSecondaryPreview } = resolveExecApprovalPreviews(
|
||||
params.request.request,
|
||||
500,
|
||||
300,
|
||||
);
|
||||
const commandPreview = formatCommandPreview(commandText, 500);
|
||||
const commandSecondaryPreview = formatOptionalCommandPreview(secondaryPreview, 300);
|
||||
|
||||
const decisionLabel =
|
||||
params.decision === "allow-once"
|
||||
|
|
@ -323,11 +336,11 @@ function createExpiredContainer(params: {
|
|||
cfg: OpenClawConfig;
|
||||
accountId: string;
|
||||
}): ExecApprovalContainer {
|
||||
const { commandText, commandPreview: secondaryPreview } = resolveExecApprovalCommandDisplay(
|
||||
const { commandPreview, commandSecondaryPreview } = resolveExecApprovalPreviews(
|
||||
params.request.request,
|
||||
500,
|
||||
300,
|
||||
);
|
||||
const commandPreview = formatCommandPreview(commandText, 500);
|
||||
const commandSecondaryPreview = formatOptionalCommandPreview(secondaryPreview, 300);
|
||||
|
||||
return new ExecApprovalContainer({
|
||||
cfg: params.cfg,
|
||||
|
|
|
|||
Loading…
Reference in New Issue