Fix Slack canvas action types
This commit is contained in:
parent
6ddef0e869
commit
d421bbeb48
@ -131,10 +131,7 @@ describe("handleSlackAction", () => {
|
|||||||
it("requires canvases to be enabled", async () => {
|
it("requires canvases to be enabled", async () => {
|
||||||
const cfg = { channels: { slack: { botToken: "tok" } } } as ClawdbotConfig;
|
const cfg = { channels: { slack: { botToken: "tok" } } } as ClawdbotConfig;
|
||||||
await expect(
|
await expect(
|
||||||
handleSlackAction(
|
handleSlackAction({ action: "createCanvas", title: "Test", content: "hello" }, cfg),
|
||||||
{ action: "createCanvas", title: "Test", content: "hello" },
|
|
||||||
cfg,
|
|
||||||
),
|
|
||||||
).rejects.toThrow(/Slack canvases are disabled/);
|
).rejects.toThrow(/Slack canvases are disabled/);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -142,10 +139,7 @@ describe("handleSlackAction", () => {
|
|||||||
const cfg = {
|
const cfg = {
|
||||||
channels: { slack: { botToken: "tok", actions: { canvases: true } } },
|
channels: { slack: { botToken: "tok", actions: { canvases: true } } },
|
||||||
} as ClawdbotConfig;
|
} as ClawdbotConfig;
|
||||||
await handleSlackAction(
|
await handleSlackAction({ action: "createCanvas", title: "Test", content: "hello" }, cfg);
|
||||||
{ action: "createCanvas", title: "Test", content: "hello" },
|
|
||||||
cfg,
|
|
||||||
);
|
|
||||||
expect(createSlackCanvas).toHaveBeenCalledWith(
|
expect(createSlackCanvas).toHaveBeenCalledWith(
|
||||||
{ title: "Test", content: "hello", channelId: undefined },
|
{ title: "Test", content: "hello", channelId: undefined },
|
||||||
undefined,
|
undefined,
|
||||||
@ -156,10 +150,7 @@ describe("handleSlackAction", () => {
|
|||||||
const cfg = {
|
const cfg = {
|
||||||
channels: { slack: { botToken: "tok", actions: { canvases: true } } },
|
channels: { slack: { botToken: "tok", actions: { canvases: true } } },
|
||||||
} as ClawdbotConfig;
|
} as ClawdbotConfig;
|
||||||
await handleSlackAction(
|
await handleSlackAction({ action: "updateCanvas", canvasId: "C123", content: "update" }, cfg);
|
||||||
{ action: "updateCanvas", canvasId: "C123", content: "update" },
|
|
||||||
cfg,
|
|
||||||
);
|
|
||||||
expect(updateSlackCanvas).toHaveBeenCalledWith(
|
expect(updateSlackCanvas).toHaveBeenCalledWith(
|
||||||
{ canvasId: "C123", channelId: undefined, content: "update", updateMode: undefined },
|
{ canvasId: "C123", channelId: undefined, content: "update", updateMode: undefined },
|
||||||
undefined,
|
undefined,
|
||||||
|
|||||||
@ -47,6 +47,8 @@ export const CHANNEL_MESSAGE_ACTION_NAMES = [
|
|||||||
"timeout",
|
"timeout",
|
||||||
"kick",
|
"kick",
|
||||||
"ban",
|
"ban",
|
||||||
|
"canvas-create",
|
||||||
|
"canvas-update",
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
export type ChannelMessageActionName = (typeof CHANNEL_MESSAGE_ACTION_NAMES)[number];
|
export type ChannelMessageActionName = (typeof CHANNEL_MESSAGE_ACTION_NAMES)[number];
|
||||||
|
|||||||
@ -56,11 +56,12 @@ describe("extractCanvasRefsFromEvent", () => {
|
|||||||
|
|
||||||
describe("fetchSlackCanvasContent", () => {
|
describe("fetchSlackCanvasContent", () => {
|
||||||
it("downloads and parses JSON canvas content", async () => {
|
it("downloads and parses JSON canvas content", async () => {
|
||||||
const fetchMock = vi.fn(async () =>
|
const fetchMock = vi.fn(
|
||||||
new Response(JSON.stringify({ text: "hello canvas" }), {
|
async () =>
|
||||||
status: 200,
|
new Response(JSON.stringify({ text: "hello canvas" }), {
|
||||||
headers: { "content-type": "application/json" },
|
status: 200,
|
||||||
}),
|
headers: { "content-type": "application/json" },
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
vi.stubGlobal("fetch", fetchMock);
|
vi.stubGlobal("fetch", fetchMock);
|
||||||
|
|
||||||
@ -127,11 +128,12 @@ describe("fetchSlackCanvasContent", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("truncates large payloads", async () => {
|
it("truncates large payloads", async () => {
|
||||||
const fetchMock = vi.fn(async () =>
|
const fetchMock = vi.fn(
|
||||||
new Response(JSON.stringify({ text: "1234567890" }), {
|
async () =>
|
||||||
status: 200,
|
new Response(JSON.stringify({ text: "1234567890" }), {
|
||||||
headers: { "content-type": "application/json" },
|
status: 200,
|
||||||
}),
|
headers: { "content-type": "application/json" },
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
vi.stubGlobal("fetch", fetchMock);
|
vi.stubGlobal("fetch", fetchMock);
|
||||||
|
|
||||||
|
|||||||
@ -173,7 +173,10 @@ function collectJsonText(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function extractTextFromJson(payload: unknown, maxChars: number): { text: string; truncated: boolean } {
|
function extractTextFromJson(
|
||||||
|
payload: unknown,
|
||||||
|
maxChars: number,
|
||||||
|
): { text: string; truncated: boolean } {
|
||||||
const results: string[] = [];
|
const results: string[] = [];
|
||||||
const seen = new Set<string>();
|
const seen = new Set<string>();
|
||||||
collectJsonText(payload, { maxChars, results, seen, depth: 0 });
|
collectJsonText(payload, { maxChars, results, seen, depth: 0 });
|
||||||
@ -197,10 +200,22 @@ export async function fetchSlackCanvasContent(params: {
|
|||||||
return { ok: false, error: "no_file_id" };
|
return { ok: false, error: "no_file_id" };
|
||||||
}
|
}
|
||||||
|
|
||||||
let fileInfo: { file?: SlackFile & { title?: string; name?: string; url_private?: string; url_private_download?: string } };
|
let fileInfo: {
|
||||||
|
file?: SlackFile & {
|
||||||
|
title?: string;
|
||||||
|
name?: string;
|
||||||
|
url_private?: string;
|
||||||
|
url_private_download?: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
try {
|
try {
|
||||||
fileInfo = (await client.files.info({ file: fileId })) as {
|
fileInfo = (await client.files.info({ file: fileId })) as {
|
||||||
file?: SlackFile & { title?: string; name?: string; url_private?: string; url_private_download?: string };
|
file?: SlackFile & {
|
||||||
|
title?: string;
|
||||||
|
name?: string;
|
||||||
|
url_private?: string;
|
||||||
|
url_private_download?: string;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const label = buildErrorLabel(err);
|
const label = buildErrorLabel(err);
|
||||||
@ -242,7 +257,11 @@ export async function fetchSlackCanvasContent(params: {
|
|||||||
let extracted: { text: string; truncated: boolean };
|
let extracted: { text: string; truncated: boolean };
|
||||||
let rawFormat: SlackCanvasContent["rawFormat"] = "unknown";
|
let rawFormat: SlackCanvasContent["rawFormat"] = "unknown";
|
||||||
|
|
||||||
if (contentType.includes("application/json") || text.trim().startsWith("{") || text.trim().startsWith("[")) {
|
if (
|
||||||
|
contentType.includes("application/json") ||
|
||||||
|
text.trim().startsWith("{") ||
|
||||||
|
text.trim().startsWith("[")
|
||||||
|
) {
|
||||||
rawFormat = "json";
|
rawFormat = "json";
|
||||||
try {
|
try {
|
||||||
const payload = JSON.parse(text);
|
const payload = JSON.parse(text);
|
||||||
|
|||||||
@ -151,11 +151,12 @@ describe("slack prepareSlackMessage inbound contract", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("appends canvas content to the inbound body", async () => {
|
it("appends canvas content to the inbound body", async () => {
|
||||||
const fetchMock = vi.fn(async () =>
|
const fetchMock = vi.fn(
|
||||||
new Response(JSON.stringify({ title: "Canvas", text: "hello canvas" }), {
|
async () =>
|
||||||
status: 200,
|
new Response(JSON.stringify({ title: "Canvas", text: "hello canvas" }), {
|
||||||
headers: { "content-type": "application/json" },
|
status: 200,
|
||||||
}),
|
headers: { "content-type": "application/json" },
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
vi.stubGlobal("fetch", fetchMock);
|
vi.stubGlobal("fetch", fetchMock);
|
||||||
|
|
||||||
|
|||||||
@ -371,7 +371,8 @@ export async function prepareSlackMessage(params: {
|
|||||||
}
|
}
|
||||||
const canvasContext = canvasBlocks.length > 0 ? canvasBlocks.join("\n\n") : "";
|
const canvasContext = canvasBlocks.length > 0 ? canvasBlocks.join("\n\n") : "";
|
||||||
|
|
||||||
const baseBody = (message.text ?? "").trim() || media?.placeholder || (canvasContext ? "[Slack canvas]" : "");
|
const baseBody =
|
||||||
|
(message.text ?? "").trim() || media?.placeholder || (canvasContext ? "[Slack canvas]" : "");
|
||||||
if (!baseBody) return null;
|
if (!baseBody) return null;
|
||||||
const rawBody = baseBody;
|
const rawBody = baseBody;
|
||||||
const rawBodyWithCanvas = canvasContext ? `${rawBody}\n\n${canvasContext}` : rawBody;
|
const rawBodyWithCanvas = canvasContext ? `${rawBody}\n\n${canvasContext}` : rawBody;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user