Files
openclaw/src/agents/command/delivery.test.ts
2026-04-04 20:06:32 +01:00

174 lines
5.0 KiB
TypeScript

import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { ChannelOutboundAdapter } from "../../channels/plugins/types.js";
import type { CliDeps } from "../../cli/outbound-send-deps.js";
import type { OpenClawConfig } from "../../config/config.js";
import { setActivePluginRegistry } from "../../plugins/runtime.js";
import { createOutboundTestPlugin, createTestRegistry } from "../../test-utils/channel-plugins.js";
import { deliverAgentCommandResult, normalizeAgentCommandReplyPayloads } from "./delivery.js";
import type { AgentCommandOpts } from "./types.js";
type NormalizeParams = Parameters<typeof normalizeAgentCommandReplyPayloads>[0];
type RunResult = NormalizeParams["result"];
const slackOutboundForTest: ChannelOutboundAdapter = {
deliveryMode: "direct",
sendText: async ({ to, text }) => ({
channel: "slack",
messageId: `${to}:${text}`,
}),
};
const emptyRegistry = createTestRegistry([]);
const slackRegistry = createTestRegistry([
{
pluginId: "slack",
source: "test",
plugin: createOutboundTestPlugin({
id: "slack",
outbound: slackOutboundForTest,
messaging: {
enableInteractiveReplies: ({ cfg }) =>
(cfg.channels?.slack as { capabilities?: { interactiveReplies?: boolean } } | undefined)
?.capabilities?.interactiveReplies === true,
},
}),
},
]);
function createResult(overrides: Partial<RunResult> = {}): RunResult {
return {
meta: {
durationMs: 1,
...overrides.meta,
},
...(overrides.payloads ? { payloads: overrides.payloads } : {}),
} as RunResult;
}
describe("normalizeAgentCommandReplyPayloads", () => {
beforeEach(() => {
setActivePluginRegistry(slackRegistry);
});
afterEach(() => {
setActivePluginRegistry(emptyRegistry);
});
it("keeps Slack directives in text for direct agent deliveries", () => {
const normalized = normalizeAgentCommandReplyPayloads({
cfg: {
channels: {
slack: {
capabilities: { interactiveReplies: true },
},
},
} as OpenClawConfig,
opts: { message: "test" } as AgentCommandOpts,
outboundSession: undefined,
deliveryChannel: "slack",
payloads: [{ text: "Choose [[slack_buttons: Retry:retry]]" }],
result: createResult(),
});
expect(normalized).toMatchObject([
{
text: "Choose [[slack_buttons: Retry:retry]]",
},
]);
});
it("renders response prefix templates with the selected runtime model", () => {
const normalized = normalizeAgentCommandReplyPayloads({
cfg: {
messages: {
responsePrefix: "[{modelFull}]",
},
} as OpenClawConfig,
opts: { message: "test" } as AgentCommandOpts,
outboundSession: undefined,
deliveryChannel: "slack",
payloads: [{ text: "Ready." }],
result: createResult({
meta: {
durationMs: 1,
agentMeta: {
sessionId: "session-1",
provider: "openai-codex",
model: "gpt-5.4",
},
},
}),
});
expect(normalized).toMatchObject([
{
text: "[openai-codex/gpt-5.4] Ready.",
},
]);
});
it("keeps Slack options text intact for local preview when delivery is disabled", async () => {
const runtime = {
log: vi.fn(),
};
const delivered = await deliverAgentCommandResult({
cfg: {
channels: {
slack: {
capabilities: { interactiveReplies: true },
},
},
} as OpenClawConfig,
deps: {} as CliDeps,
runtime: runtime as never,
opts: {
message: "test",
channel: "slack",
} as AgentCommandOpts,
outboundSession: undefined,
sessionEntry: undefined,
payloads: [{ text: "Options: on, off." }],
result: createResult(),
});
expect(runtime.log).toHaveBeenCalledTimes(1);
expect(runtime.log).toHaveBeenCalledWith("Options: on, off.");
expect(delivered.payloads).toMatchObject([{ text: "Options: on, off." }]);
});
it("keeps LINE directive-only replies intact for local preview when delivery is disabled", async () => {
const runtime = {
log: vi.fn(),
};
const delivered = await deliverAgentCommandResult({
cfg: {} as OpenClawConfig,
deps: {} as CliDeps,
runtime: runtime as never,
opts: {
message: "test",
channel: "line",
} as AgentCommandOpts,
outboundSession: undefined,
sessionEntry: undefined,
payloads: [
{
text: "[[buttons: Release menu | Choose an action | Retry:retry, Ignore:ignore]]",
},
],
result: createResult(),
});
expect(runtime.log).toHaveBeenCalledTimes(1);
expect(runtime.log).toHaveBeenCalledWith(
"[[buttons: Release menu | Choose an action | Retry:retry, Ignore:ignore]]",
);
expect(delivered.payloads).toMatchObject([
{
text: "[[buttons: Release menu | Choose an action | Retry:retry, Ignore:ignore]]",
},
]);
});
});