frameshot-mcp 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-6OTGZDUU.js → chunk-AF64XFKX.js} +1 -1
- package/dist/{chunk-WACVDBUF.js → chunk-FQ3BVCX7.js} +6 -3
- package/dist/cli.js +2 -2
- package/dist/index.js +32 -26
- package/dist/renderer.d.ts +2 -0
- package/dist/renderer.js +1 -1
- package/package.json +1 -1
- package/scripts/render-changed.mjs +9 -4
|
@@ -1476,6 +1476,7 @@ var RenderUseCase = class {
|
|
|
1476
1476
|
const opts = this.resolveOptions(options);
|
|
1477
1477
|
const ext = extname2(filePath).toLowerCase();
|
|
1478
1478
|
const framework = EXT_TO_FRAMEWORK[ext] ?? "react";
|
|
1479
|
+
let fallbackReason;
|
|
1479
1480
|
if (this.viteBundler) {
|
|
1480
1481
|
try {
|
|
1481
1482
|
const { url } = await this.viteBundler.getUrl(filePath, {
|
|
@@ -1488,16 +1489,18 @@ var RenderUseCase = class {
|
|
|
1488
1489
|
);
|
|
1489
1490
|
return { results: results2, mode: "vite" };
|
|
1490
1491
|
} catch (err) {
|
|
1491
|
-
|
|
1492
|
+
fallbackReason = err instanceof Error ? err.message : String(err);
|
|
1492
1493
|
process.stderr.write(
|
|
1493
|
-
`[frameshot] Vite pipeline failed (${
|
|
1494
|
+
`[frameshot] Vite pipeline failed (${fallbackReason}), falling back to CDN
|
|
1494
1495
|
`
|
|
1495
1496
|
);
|
|
1496
1497
|
}
|
|
1498
|
+
} else {
|
|
1499
|
+
fallbackReason = "Vite bundler not available";
|
|
1497
1500
|
}
|
|
1498
1501
|
const code = readFileSync3(filePath, "utf-8");
|
|
1499
1502
|
const results = await this.render(code, framework, options);
|
|
1500
|
-
return { results, mode: "cdn" };
|
|
1503
|
+
return { results, mode: "cdn", fallbackReason };
|
|
1501
1504
|
}
|
|
1502
1505
|
async renderInteraction(code, framework, interactions, options = {}) {
|
|
1503
1506
|
const opts = this.resolveOptions(options);
|
package/dist/cli.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
createContainer
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-AF64XFKX.js";
|
|
5
5
|
import {
|
|
6
6
|
EXT_TO_FRAMEWORK
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-FQ3BVCX7.js";
|
|
8
8
|
|
|
9
9
|
// src/cli.ts
|
|
10
10
|
import { mkdirSync } from "fs";
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
createContainer
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-AF64XFKX.js";
|
|
5
5
|
import {
|
|
6
6
|
DEVICE_PRESETS,
|
|
7
7
|
EXT_TO_FRAMEWORK,
|
|
8
8
|
__export
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-FQ3BVCX7.js";
|
|
10
10
|
|
|
11
11
|
// src/index.ts
|
|
12
12
|
import { execSync } from "child_process";
|
|
@@ -14907,19 +14907,25 @@ function registerRenderFileTools(server2, useCase) {
|
|
|
14907
14907
|
mock
|
|
14908
14908
|
}) => {
|
|
14909
14909
|
const start = performance.now();
|
|
14910
|
-
const { results, mode } = await useCase.renderFile(
|
|
14911
|
-
|
|
14912
|
-
|
|
14913
|
-
|
|
14914
|
-
|
|
14915
|
-
|
|
14916
|
-
|
|
14917
|
-
|
|
14918
|
-
|
|
14919
|
-
|
|
14910
|
+
const { results, mode, fallbackReason } = await useCase.renderFile(
|
|
14911
|
+
path,
|
|
14912
|
+
{
|
|
14913
|
+
props,
|
|
14914
|
+
viewport: { width, height },
|
|
14915
|
+
fullPage: true,
|
|
14916
|
+
engines: ["chromium"],
|
|
14917
|
+
darkMode,
|
|
14918
|
+
tailwindVersion,
|
|
14919
|
+
projectRoot,
|
|
14920
|
+
mock
|
|
14921
|
+
}
|
|
14922
|
+
);
|
|
14920
14923
|
const elapsed = Math.round(performance.now() - start);
|
|
14921
14924
|
const ext = extname(path).toLowerCase();
|
|
14922
14925
|
const framework = EXT_TO_FRAMEWORK[ext] ?? "react";
|
|
14926
|
+
const fallbackNote = mode === "cdn" && fallbackReason ? `
|
|
14927
|
+
\u2139\uFE0F Fell back to CDN pipeline: ${fallbackReason}
|
|
14928
|
+
Imports from node_modules may not resolve. To fix: install vite as a devDep and add a minimal vite.config.` : "";
|
|
14923
14929
|
const content = results.flatMap((r) => [
|
|
14924
14930
|
{
|
|
14925
14931
|
type: "image",
|
|
@@ -14930,7 +14936,7 @@ function registerRenderFileTools(server2, useCase) {
|
|
|
14930
14936
|
type: "text",
|
|
14931
14937
|
text: `[${mode}/${framework}] ${r.width}x${r.height} (${elapsed}ms)${r.consoleErrors.length ? `
|
|
14932
14938
|
\u26A0\uFE0F Console errors:
|
|
14933
|
-
${r.consoleErrors.join("\n")}` : ""}`
|
|
14939
|
+
${r.consoleErrors.join("\n")}` : ""}${fallbackNote}`
|
|
14934
14940
|
}
|
|
14935
14941
|
]);
|
|
14936
14942
|
return { content };
|
|
@@ -15569,21 +15575,9 @@ function registerAllTools(server2, useCases) {
|
|
|
15569
15575
|
|
|
15570
15576
|
// src/index.ts
|
|
15571
15577
|
var container = createContainer();
|
|
15572
|
-
async function ensureBrowser() {
|
|
15573
|
-
try {
|
|
15574
|
-
await container.pool.warmup(["chromium"]);
|
|
15575
|
-
} catch {
|
|
15576
|
-
try {
|
|
15577
|
-
execSync("npx playwright install chromium", { stdio: "pipe" });
|
|
15578
|
-
await container.pool.warmup(["chromium"]);
|
|
15579
|
-
} catch {
|
|
15580
|
-
}
|
|
15581
|
-
}
|
|
15582
|
-
}
|
|
15583
|
-
await ensureBrowser();
|
|
15584
15578
|
var server = new McpServer({
|
|
15585
15579
|
name: "frameshot",
|
|
15586
|
-
version: "0.
|
|
15580
|
+
version: "0.10.0"
|
|
15587
15581
|
});
|
|
15588
15582
|
registerAllTools(server, {
|
|
15589
15583
|
render: container.renderUseCase,
|
|
@@ -15596,6 +15590,18 @@ registerAllTools(server, {
|
|
|
15596
15590
|
});
|
|
15597
15591
|
var transport = new StdioServerTransport();
|
|
15598
15592
|
await server.connect(transport);
|
|
15593
|
+
void (async () => {
|
|
15594
|
+
try {
|
|
15595
|
+
await container.pool.warmup(["chromium"]);
|
|
15596
|
+
} catch {
|
|
15597
|
+
try {
|
|
15598
|
+
execSync("npx playwright install chromium", { stdio: "pipe" });
|
|
15599
|
+
await container.pool.warmup(["chromium"]).catch(() => {
|
|
15600
|
+
});
|
|
15601
|
+
} catch {
|
|
15602
|
+
}
|
|
15603
|
+
}
|
|
15604
|
+
})();
|
|
15599
15605
|
process.on("SIGINT", async () => {
|
|
15600
15606
|
await container.shutdown();
|
|
15601
15607
|
process.exit(0);
|
package/dist/renderer.d.ts
CHANGED
|
@@ -218,6 +218,8 @@ declare class RenderUseCase {
|
|
|
218
218
|
renderFile(filePath: string, options?: Partial<FileRenderOptions>): Promise<{
|
|
219
219
|
results: ScreenshotResult[];
|
|
220
220
|
mode: "vite" | "cdn";
|
|
221
|
+
/** If we fell back to CDN, the reason the Vite pipeline was skipped. */
|
|
222
|
+
fallbackReason?: string;
|
|
221
223
|
}>;
|
|
222
224
|
renderInteraction(code: string, framework: Framework, interactions: Interaction[], options?: Partial<RenderOptions>): Promise<{
|
|
223
225
|
image: string;
|
package/dist/renderer.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "frameshot-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Zero-config visual testing for AI agents. Render project components with full Vite dependency resolution — no stories, no config.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -259,12 +259,17 @@ async function main() {
|
|
|
259
259
|
try {
|
|
260
260
|
// Render current (after) version
|
|
261
261
|
console.log(` Rendering (after): ${filePath}`);
|
|
262
|
-
const {
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
262
|
+
const {
|
|
263
|
+
results: afterResults,
|
|
264
|
+
mode,
|
|
265
|
+
fallbackReason,
|
|
266
|
+
} = await renderUseCase.renderFile(filePath, renderOpts);
|
|
266
267
|
const afterResult = afterResults[0];
|
|
267
268
|
|
|
269
|
+
if (mode === "cdn" && fallbackReason) {
|
|
270
|
+
console.log(` ℹ️ CDN fallback: ${fallbackReason}`);
|
|
271
|
+
}
|
|
272
|
+
|
|
268
273
|
const afterPath = join(outputDir, `${safeName}_after.png`);
|
|
269
274
|
writeFileSync(afterPath, Buffer.from(afterResult.image, "base64"));
|
|
270
275
|
|