import { CloseBotClient, err } from "../client.js";
import type { ToolDefinition, ToolResult, BotDto } from "../types.js";
export const tools: ToolDefinition[] = [
{
name: "bot_dashboard_app",
description: "Rich dashboard showing all bots in a grid with status, versions, source count, and details. Returns HTML visualization.",
inputSchema: {
type: "object",
properties: {
botId: { type: "string", description: "Optional: show details for a specific bot instead of the grid" },
},
},
},
];
function escapeHtml(s: string): string {
return s.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """);
}
function renderBotGrid(bots: BotDto[]): string {
const botCards = bots.map((bot) => {
const latestVersion = bot.versions?.find((v) => v.published) || bot.versions?.[0];
const versionLabel = latestVersion?.version || "draft";
const published = latestVersion?.published ? "🟢" : "🟡";
const sourceCount = bot.sources?.length || 0;
const locked = bot.locked ? "🔒" : "";
const fav = bot.favorited ? "⭐" : "";
const category = bot.category || "—";
const modified = bot.modifiedAt ? new Date(bot.modifiedAt).toLocaleDateString() : "—";
return `
${fav} ${escapeHtml(bot.name || "Unnamed")} ${locked}
${escapeHtml(category)}
${published} v${escapeHtml(versionLabel)}
📡 ${sourceCount} source${sourceCount !== 1 ? "s" : ""}
Modified: ${escapeHtml(modified)}
ID: ${escapeHtml(bot.id || "")}
${bot.followUpActive ? '
↻ Follow-ups active
' : ""}
${bot.tools && bot.tools.length > 0 ? `
🔧 ${bot.tools.length} tool(s)
` : ""}
`;
}).join("");
return `
🤖 Bot Dashboard (${bots.length} bots)
${botCards}
`;
}
function renderBotDetail(bot: BotDto): string {
const versions = (bot.versions || [])
.map(
(v) =>
`| ${escapeHtml(v.version || "")} | ${v.published ? "✅ Published" : "📝 Draft"} | ${escapeHtml(v.name || "—")} | ${v.modifiedAt ? new Date(v.modifiedAt).toLocaleString() : "—"} |
`
)
.join("");
const sources = (bot.sources || [])
.map(
(s) =>
`| ${escapeHtml(s.name || "Unnamed")} | ${escapeHtml(s.category || "—")} | ${s.enabled ? "✅" : "❌"} | ${escapeHtml(s.id || "")} |
`
)
.join("");
return `
🤖 ${escapeHtml(bot.name || "Unnamed")}
ID: ${escapeHtml(bot.id || "")}
${bot.sources?.length || 0}
Sources
${bot.versions?.length || 0}
Versions
${bot.locked ? "🔒" : "🔓"}
${bot.locked ? "Locked" : "Unlocked"}
${bot.followUpActive ? "✅" : "❌"}
Follow-ups
📋 Versions
| Version | Status | Name | Modified |
${versions || '| No versions |
'}
📡 Sources
| Name | Category | Enabled | ID |
${sources || '| No sources attached |
'}
`;
}
export async function handler(
client: CloseBotClient,
name: string,
args: Record
): Promise {
try {
if (args.botId) {
const bot = await client.get(`/bot/${args.botId}`);
const html = renderBotDetail(bot);
return {
content: [{ type: "text", text: `Bot details for ${bot.name || bot.id}` }],
structuredContent: { type: "html", html },
};
}
const bots = await client.get("/bot");
const html = renderBotGrid(bots);
return {
content: [{ type: "text", text: `Dashboard showing ${bots.length} bots` }],
structuredContent: { type: "html", html },
};
} catch (error) {
return err(error);
}
}