feat: bundle default styles guide
This commit is contained in:
+4
-76
@@ -1,26 +1,17 @@
|
||||
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
||||
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
||||
import { afterEach, describe, expect, test } from "bun:test";
|
||||
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { mkdtempSync, rmSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { dirname, join } from "node:path";
|
||||
import { join } from "node:path";
|
||||
import { type ScenePayload } from "../core/shared";
|
||||
import { createDrawingStore, type DrawingStore } from "../server/db";
|
||||
import {
|
||||
DEFAULT_STYLES_GUIDE_PATH,
|
||||
createExcaliMcpHandler,
|
||||
createMcpToolHandlers,
|
||||
resolvePublicBaseUrl,
|
||||
resolveStylesGuidePath,
|
||||
} from "./server";
|
||||
import { createMcpToolHandlers, resolvePublicBaseUrl } from "./server";
|
||||
|
||||
const cleanup: Array<{ dir: string; store?: DrawingStore; client?: Client }> = [];
|
||||
const cleanup: Array<{ dir: string; store?: DrawingStore }> = [];
|
||||
|
||||
afterEach(async () => {
|
||||
while (cleanup.length > 0) {
|
||||
const item = cleanup.pop();
|
||||
if (item) {
|
||||
await item.client?.close().catch(() => undefined);
|
||||
item.store?.close();
|
||||
rmSync(item.dir, { recursive: true, force: true });
|
||||
}
|
||||
@@ -37,35 +28,6 @@ function createTempTools() {
|
||||
};
|
||||
}
|
||||
|
||||
function createTempStylesGuidePath(content?: string) {
|
||||
const dir = mkdtempSync(join(tmpdir(), "excali-mcp-"));
|
||||
const path = join(dir, DEFAULT_STYLES_GUIDE_PATH.slice(1));
|
||||
mkdirSync(dirname(path), { recursive: true });
|
||||
if (content !== undefined) {
|
||||
writeFileSync(path, content);
|
||||
}
|
||||
cleanup.push({ dir });
|
||||
return path;
|
||||
}
|
||||
|
||||
async function createTempClient(stylesGuidePath?: string) {
|
||||
const dir = mkdtempSync(join(tmpdir(), "excali-mcp-"));
|
||||
const store = createDrawingStore(join(dir, "test.sqlite"));
|
||||
const handler = createExcaliMcpHandler(
|
||||
store,
|
||||
"http://example.test",
|
||||
stylesGuidePath ? resolveStylesGuidePath(stylesGuidePath) : undefined,
|
||||
);
|
||||
const transport = new StreamableHTTPClientTransport(new URL("http://localhost/mcp"), {
|
||||
fetch: async (input, init) => handler(new Request(input, init)),
|
||||
});
|
||||
const client = new Client({ name: "excali-test", version: "1.0.0" });
|
||||
|
||||
await client.connect(transport);
|
||||
cleanup.push({ dir, store, client });
|
||||
return { client, store };
|
||||
}
|
||||
|
||||
function testScene(): ScenePayload {
|
||||
return {
|
||||
elements: [
|
||||
@@ -82,40 +44,6 @@ describe("mcp tool handlers", () => {
|
||||
expect(() => resolvePublicBaseUrl("")).toThrow("PUBLIC_BASE_URL is required");
|
||||
});
|
||||
|
||||
test("missing fixed styles-guide path exposes no styles-guide resource", async () => {
|
||||
const stylesGuidePath = createTempStylesGuidePath();
|
||||
expect(resolveStylesGuidePath(stylesGuidePath)).toBeUndefined();
|
||||
|
||||
const { client } = await createTempClient(stylesGuidePath);
|
||||
|
||||
expect(client.getServerCapabilities()?.resources).toBeUndefined();
|
||||
});
|
||||
|
||||
test("valid fixed styles-guide path registers the styles-guide resource", async () => {
|
||||
const contents = "# Scene style\n\nKeep labels terse.\n";
|
||||
const stylesGuidePath = createTempStylesGuidePath(contents);
|
||||
const resolved = resolveStylesGuidePath(stylesGuidePath);
|
||||
const { client } = await createTempClient(stylesGuidePath);
|
||||
const resources = await client.listResources();
|
||||
const readResult = await client.readResource({ uri: "excali://styles-guide" });
|
||||
|
||||
expect(resolved).toEqual({ path: stylesGuidePath });
|
||||
expect(resources.resources).toContainEqual({
|
||||
name: "styles-guide",
|
||||
uri: "excali://styles-guide",
|
||||
title: "Styles Guide",
|
||||
description: "User-provided drawing styles guide for scene generation",
|
||||
mimeType: "text/markdown",
|
||||
});
|
||||
expect(readResult.contents).toEqual([
|
||||
{
|
||||
uri: "excali://styles-guide",
|
||||
mimeType: "text/markdown",
|
||||
text: contents,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
test("create_drawing writes an explicit scene to a temp SQLite DB", () => {
|
||||
const { store, tools } = createTempTools();
|
||||
const scene = testScene();
|
||||
|
||||
Reference in New Issue
Block a user