Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,25 @@ describe("Slack platform bridge", () => {
expect(view.blocks.some((b) => b.type === "header")).toBe(false);
});

test("falls back to a minimal home view if the rich view is rejected", async () => {
const h = makeHomeChat();
registerSlackAppHome(h.chat, connection(), {});
let calls = 0;
const publishHomeView = mock(async () => {
calls += 1;
if (calls === 1) throw new Error("invalid_blocks");
});
await h.open("U123", publishHomeView);
expect(publishHomeView).toHaveBeenCalledTimes(2);
const fallback = publishHomeView.mock.calls[1]![1] as {
type: string;
blocks: Array<Record<string, unknown>>;
};
expect(fallback.type).toBe("home");
expect(fallback.blocks.length).toBe(1);
expect(blocksText(fallback)).toContain("/lobu help");
});

test("renders the preview-workspace home tab without touching the MCP config", async () => {
const h = makeHomeChat();
const getMcpStatus = mock(async () => mcpStatus);
Expand Down
43 changes: 41 additions & 2 deletions packages/server/src/gateway/connections/slack-platform-bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,28 @@ async function loadIntegrationStatusesScoped(
return result;
}

/** Extract something useful out of a Slack `WebAPIPlatformError` (or anything). */
function errorDetail(error: unknown): Record<string, unknown> {
if (error instanceof Error) {
const data = (error as { data?: unknown }).data;
return {
message: error.message,
...(data && typeof data === "object" ? { slack: data } : {}),
};
}
return { message: String(error) };
}

const HOME_FALLBACK_BLOCKS: unknown[] = [
{
type: "section",
text: {
type: "mrkdwn",
text: "*Lobu* :wave:\n\nMention me in any channel, or send me a DM, to start a thread. Use `/lobu help` for the built-in commands.",
},
},
];

async function publishHome(
adapter: SlackHomeAdapter | undefined,
params: HomeViewParams
Expand All @@ -355,12 +377,29 @@ async function publishHome(
} catch (error) {
logger.warn(
{
error,
error: errorDetail(error),
connectionId: params.connection.id,
userId: params.userId,
},
"Failed to publish Slack home tab"
"Failed to publish Slack home tab; falling back to a minimal view"
);
// The rich view failed (likely Block Kit validation). Don't leave the user
// staring at a stale cached view — publish a plain text-only home tab.
try {
await publishHomeView(params.userId, {
type: "home",
blocks: HOME_FALLBACK_BLOCKS,
});
} catch (fallbackError) {
logger.warn(
{
error: errorDetail(fallbackError),
connectionId: params.connection.id,
userId: params.userId,
},
"Failed to publish fallback Slack home tab"
);
}
}
}

Expand Down
Loading