mirror of
https://github.com/webstudio-is/webstudio.git
synced 2026-10-23 03:27:27 +09:00
This PR expands Webstudio MCP and CLI into a more complete agent authoring interface. Agents can discover project capabilities, edit real Webstudio content, use data/resources, verify visual output, and report useful issues when workflows fail. ## MCP User Capabilities - Create, update, duplicate, reorder, and delete pages. - Create pages from templates and manage reusable page templates. - Inspect project pages, instances, props, styles, assets, variables, resources, and metadata. - Insert Webstudio components and authored JSX fragments into pages. - Edit text, props, styles, breakpoints, design tokens, and CSS variables. - Update page metadata, SEO fields, redirects, marketplace metadata, and project settings. - Create and use static data variables. - Create and use dynamic resources fetched over HTTP. - Use REST, GraphQL, and built-in system resources in authored pages. - Bind data variables and resources to visible page content. - Create resource-backed pages such as sitemap XML, structured SEO data, and API-driven content sections. - Preview current project state without requiring a publish step. - Capture screenshots for visual verification. - Verify responsive designs across desktop, tablet, and mobile breakpoints. - Use screenshot diff and OCR-style checks to inspect rendered output. - Reset and refresh local MCP project state when needed. - Discover available CLI/MCP commands from generated manuals. - Use clearer examples for resources, data variables, JSX authoring, previewing, and visual checks. - Read marketplace product metadata without requiring a full project snapshot. - Get safer guidance when using low-level patch tools. - Get a ready-to-copy Discord report template when MCP/CLI behavior is confusing or broken.
66 lines
1.8 KiB
JavaScript
66 lines
1.8 KiB
JavaScript
import { readdir, readFile } from "node:fs/promises";
|
|
import { join } from "node:path";
|
|
|
|
const workspaceRoots = ["apps", "packages"];
|
|
const runtimeDependencyFields = [
|
|
"dependencies",
|
|
"peerDependencies",
|
|
"optionalDependencies",
|
|
];
|
|
|
|
const readJson = async (path) => JSON.parse(await readFile(path, "utf8"));
|
|
|
|
const findWorkspacePackageJsons = async () => {
|
|
const packageJsons = [];
|
|
for (const root of workspaceRoots) {
|
|
const entries = await readdir(root, { withFileTypes: true });
|
|
for (const entry of entries) {
|
|
if (entry.isDirectory()) {
|
|
packageJsons.push(join(root, entry.name, "package.json"));
|
|
}
|
|
}
|
|
}
|
|
return packageJsons;
|
|
};
|
|
|
|
const packages = await Promise.all(
|
|
(await findWorkspacePackageJsons()).map(async (path) => ({
|
|
path,
|
|
manifest: await readJson(path),
|
|
}))
|
|
);
|
|
|
|
const workspacePackageByName = new Map(
|
|
packages.map((pkg) => [pkg.manifest.name, pkg])
|
|
);
|
|
|
|
const violations = [];
|
|
|
|
for (const pkg of packages) {
|
|
if (pkg.manifest.private === true) {
|
|
continue;
|
|
}
|
|
for (const field of runtimeDependencyFields) {
|
|
for (const dependencyName of Object.keys(pkg.manifest[field] ?? {})) {
|
|
const dependency = workspacePackageByName.get(dependencyName);
|
|
if (dependency?.manifest.private === true) {
|
|
violations.push(
|
|
`${pkg.manifest.name} (${pkg.path}) lists private workspace package ` +
|
|
`${dependencyName} in ${field}. Use devDependencies for build-time ` +
|
|
`generation or move the shared runtime contract to a public package.`
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (violations.length > 0) {
|
|
console.error("Package boundary violations found:\n");
|
|
for (const violation of violations) {
|
|
console.error(`- ${violation}`);
|
|
}
|
|
process.exit(1);
|
|
}
|
|
|
|
console.info("Package boundaries are valid.");
|