@primeuicom/mcp 0.1.27 → 0.1.29

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/service.js CHANGED
@@ -485,42 +485,13 @@ import { unlink } from "fs/promises";
485
485
  import path5 from "path";
486
486
  import { Readable, Transform } from "stream";
487
487
  import { pipeline } from "stream/promises";
488
- import { z as z3 } from "zod";
489
-
490
- // src/lib/fs.ts
491
- import { mkdir, rm, writeFile } from "fs/promises";
492
- import path4 from "path";
493
- import extractZipArchive from "extract-zip";
494
- async function ensureDir(dirPath) {
495
- await mkdir(dirPath, { recursive: true });
496
- }
497
- async function resetDir(dirPath) {
498
- await rm(dirPath, { recursive: true, force: true });
499
- await mkdir(dirPath, { recursive: true });
500
- }
501
- async function writeUtf8(filePath, content) {
502
- await ensureDir(path4.dirname(filePath));
503
- await writeFile(filePath, content, "utf-8");
504
- }
505
- async function extractZip(zipPath, targetDir) {
506
- await ensureDir(targetDir);
507
- try {
508
- await extractZipArchive(zipPath, { dir: targetDir });
509
- } catch (error) {
510
- const details = error instanceof Error ? error.message : String(error);
511
- throw new Error(`Failed to extract zip at "${zipPath}". ${details}`);
512
- }
513
- }
514
488
 
515
- // src/sources/api-provider.ts
516
- var DEFAULT_API_BASE_URL = "https://app.primeui.com/";
517
- var ZIP_CONTENT_TYPES = [
518
- "application/zip",
519
- "application/octet-stream",
520
- "application/x-zip-compressed"
521
- ];
522
- var exportStatusSchema = z3.enum(["in_progress", "completed", "failed"]);
523
- var projectPageObjectSchema = z3.object({
489
+ // src/lib/api-v1-contract.ts
490
+ import { z as z3 } from "zod";
491
+ var primeUiExportStatusSchema = z3.enum(
492
+ ["in_progress", "completed", "failed"]
493
+ );
494
+ var primeUiProjectPageObjectSchema = z3.object({
524
495
  id: z3.string(),
525
496
  title: z3.string(),
526
497
  slug: z3.string(),
@@ -529,24 +500,33 @@ var projectPageObjectSchema = z3.object({
529
500
  pagePath: z3.string(),
530
501
  componentsPath: z3.string()
531
502
  });
532
- var projectPageSchema = projectPageObjectSchema;
533
- var exportSummarySchema = z3.object({
503
+ var primeUiProjectPageSchema = primeUiProjectPageObjectSchema;
504
+ var primeUiProjectExportableSchema = z3.object({
505
+ key: z3.string(),
506
+ description: z3.string(),
507
+ isReadyToExport: z3.boolean()
508
+ });
509
+ var primeUiExportSummarySchema = z3.object({
534
510
  total: z3.number(),
535
511
  successful: z3.number(),
536
512
  failed: z3.number()
537
513
  });
538
- var exportedComponentSchema = z3.object({
539
- componentKey: z3.string(),
540
- enabled: z3.boolean(),
541
- files: z3.array(z3.string()),
542
- message: z3.string()
514
+ var primeUiExportableManifestSchema = z3.object({
515
+ success: z3.boolean(),
516
+ message: z3.string(),
517
+ files: z3.array(z3.string())
518
+ });
519
+ var primeUiExportedExportableSchema = z3.object({
520
+ key: z3.string(),
521
+ isReadyToExport: z3.boolean(),
522
+ manifest: primeUiExportableManifestSchema
543
523
  });
544
- var exportPageManifestSchema = z3.object({
524
+ var primeUiExportPageManifestSchema = z3.object({
545
525
  success: z3.boolean(),
546
526
  message: z3.string(),
547
527
  files: z3.array(z3.string())
548
528
  });
549
- var exportPageSchema = z3.object({
529
+ var primeUiExportPageSchema = z3.object({
550
530
  id: z3.string(),
551
531
  title: z3.string().optional(),
552
532
  slug: z3.string(),
@@ -554,51 +534,107 @@ var exportPageSchema = z3.object({
554
534
  isReadyToExport: z3.literal(true),
555
535
  pagePath: z3.string(),
556
536
  componentsPath: z3.string(),
557
- manifest: exportPageManifestSchema
558
- });
559
- var projectInfoSchema = z3.object({
560
- projectId: z3.string(),
561
- projectName: z3.string(),
562
- metadata: z3.record(z3.unknown()),
563
- pages: z3.array(projectPageSchema)
537
+ manifest: primeUiExportPageManifestSchema
564
538
  });
565
- var projectPageComponentSchema = z3.object({
539
+ var primeUiProjectInfoSchema = z3.object(
540
+ {
541
+ projectId: z3.string(),
542
+ projectName: z3.string(),
543
+ metadata: z3.record(z3.unknown()),
544
+ exportables: z3.array(primeUiProjectExportableSchema),
545
+ pages: z3.array(primeUiProjectPageSchema)
546
+ }
547
+ );
548
+ var primeUiProjectPageComponentSchema = z3.object({
566
549
  blockId: z3.string(),
567
550
  componentId: z3.string(),
568
551
  componentGroup: z3.string(),
569
552
  slot: z3.string().nullable(),
570
553
  props: z3.record(z3.unknown()).nullable()
571
554
  });
572
- var projectPageDetailsSchema = z3.object({
573
- page: projectPageObjectSchema.extend({
555
+ var primeUiProjectPageDetailsSchema = z3.object({
556
+ page: primeUiProjectPageObjectSchema.extend({
574
557
  pageInstruction: z3.string().nullable()
575
558
  }),
576
559
  variant: z3.object({
577
560
  id: z3.string(),
578
561
  name: z3.string()
579
562
  }).nullable(),
580
- components: z3.array(projectPageComponentSchema).nullable()
563
+ components: z3.array(primeUiProjectPageComponentSchema).nullable()
581
564
  });
582
- var exportsResponseSchema = z3.object({
565
+ var primeUiExportsResponseSchema = z3.object({
583
566
  exports: z3.array(
584
567
  z3.object({
585
568
  id: z3.string(),
586
- status: exportStatusSchema,
569
+ status: primeUiExportStatusSchema,
587
570
  createdAt: z3.string().datetime({ offset: true })
588
571
  })
589
572
  )
590
573
  });
591
- var createExportResponseSchema = z3.object({
574
+ var primeUiCreateExportResponseSchema = z3.object({
592
575
  export: z3.object({
593
576
  id: z3.string(),
594
- status: exportStatusSchema,
577
+ status: primeUiExportStatusSchema,
595
578
  createdAt: z3.string().datetime({ offset: true }),
596
579
  expiresAt: z3.string().datetime({ offset: true }).nullable(),
597
- summary: exportSummarySchema,
598
- components: z3.array(exportedComponentSchema)
580
+ summary: primeUiExportSummarySchema,
581
+ exportables: z3.array(primeUiExportedExportableSchema)
599
582
  }),
600
- pages: z3.array(exportPageSchema)
583
+ pages: z3.array(primeUiExportPageSchema)
601
584
  });
585
+ var primeUiExportManifestSchema = primeUiCreateExportResponseSchema;
586
+ function parsePrimeUiExportManifest(value) {
587
+ if (!value || typeof value !== "object") {
588
+ throw new Error("Export manifest is invalid.");
589
+ }
590
+ const maybe = value;
591
+ if (!maybe.export || typeof maybe.export !== "object") {
592
+ throw new Error("Export manifest export payload is invalid.");
593
+ }
594
+ const parsed = primeUiExportManifestSchema.safeParse(value);
595
+ if (!parsed.success) {
596
+ const hasPageIssue = parsed.error.issues.some(
597
+ (issue) => issue.path[0] === "pages"
598
+ );
599
+ throw new Error(
600
+ hasPageIssue ? "Export manifest pages payload is invalid." : "Export manifest does not match expected schema."
601
+ );
602
+ }
603
+ return parsed.data;
604
+ }
605
+
606
+ // src/lib/fs.ts
607
+ import { mkdir, rm, writeFile } from "fs/promises";
608
+ import path4 from "path";
609
+ import extractZipArchive from "extract-zip";
610
+ async function ensureDir(dirPath) {
611
+ await mkdir(dirPath, { recursive: true });
612
+ }
613
+ async function resetDir(dirPath) {
614
+ await rm(dirPath, { recursive: true, force: true });
615
+ await mkdir(dirPath, { recursive: true });
616
+ }
617
+ async function writeUtf8(filePath, content) {
618
+ await ensureDir(path4.dirname(filePath));
619
+ await writeFile(filePath, content, "utf-8");
620
+ }
621
+ async function extractZip(zipPath, targetDir) {
622
+ await ensureDir(targetDir);
623
+ try {
624
+ await extractZipArchive(zipPath, { dir: targetDir });
625
+ } catch (error) {
626
+ const details = error instanceof Error ? error.message : String(error);
627
+ throw new Error(`Failed to extract zip at "${zipPath}". ${details}`);
628
+ }
629
+ }
630
+
631
+ // src/sources/api-provider.ts
632
+ var DEFAULT_API_BASE_URL = "https://app.primeui.com/";
633
+ var ZIP_CONTENT_TYPES = [
634
+ "application/zip",
635
+ "application/octet-stream",
636
+ "application/x-zip-compressed"
637
+ ];
602
638
  var PrimeUiApiContractError = class extends Error {
603
639
  constructor(endpoint, details) {
604
640
  super(`PrimeUI API contract mismatch for "${endpoint}": ${details}`);
@@ -683,26 +719,30 @@ var ApiProjectDataProvider = class {
683
719
  this.apiRoot = normalizePrimeUiApiRoot(options.baseUrl);
684
720
  }
685
721
  async getProjectInfo() {
686
- return this.requestJson("project", projectInfoSchema);
722
+ return this.requestJson("project", primeUiProjectInfoSchema);
687
723
  }
688
724
  async getProjectPageBySlug(slug) {
689
725
  const encodedSlug = encodeURIComponent(slug);
690
726
  return this.requestJson(
691
727
  `project/page?slug=${encodedSlug}`,
692
- projectPageDetailsSchema
728
+ primeUiProjectPageDetailsSchema
693
729
  );
694
730
  }
695
731
  async listExports() {
696
732
  const response = await this.requestJson(
697
733
  "project/exports",
698
- exportsResponseSchema
734
+ primeUiExportsResponseSchema
699
735
  );
700
736
  return response.exports;
701
737
  }
702
738
  async createExport() {
703
- return this.requestJson("project/exports", createExportResponseSchema, {
704
- method: "POST"
705
- });
739
+ return this.requestJson(
740
+ "project/exports",
741
+ primeUiCreateExportResponseSchema,
742
+ {
743
+ method: "POST"
744
+ }
745
+ );
706
746
  }
707
747
  /**
708
748
  * Consumer-side runtime contract for GET /api/v1/project/exports/:exportId/download.
@@ -1702,104 +1742,6 @@ async function buildImportGraph(input) {
1702
1742
  };
1703
1743
  }
1704
1744
 
1705
- // src/lib/page-paths.ts
1706
- var WEBSITE_APP_ROOT = "src/app/(website)";
1707
- var PAGE_COMPONENTS_ROOT = "src/components/pages";
1708
- var normalizeSlug = (slug) => {
1709
- const trimmed = slug.trim();
1710
- if (!trimmed || trimmed === "/") {
1711
- return "/";
1712
- }
1713
- const withLeadingSlash = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
1714
- const withoutTrailingSlash = withLeadingSlash.replace(/\/+$/, "");
1715
- return withoutTrailingSlash || "/";
1716
- };
1717
- var slugToFolderPath = (normalizedSlug) => {
1718
- if (normalizedSlug === "/") {
1719
- return "";
1720
- }
1721
- return normalizedSlug.slice(1);
1722
- };
1723
- var toPathSegment = (value) => {
1724
- const normalized = value.trim().toLowerCase().replace(/[^a-z0-9/-]+/g, "-");
1725
- const compact = normalized.replace(/-+/g, "-").replace(/^-|-$/g, "");
1726
- return compact || "page";
1727
- };
1728
- var buildWebsitePagePath = (normalizedSlug) => {
1729
- if (normalizedSlug === "/") {
1730
- return `${WEBSITE_APP_ROOT}/page.tsx`;
1731
- }
1732
- return `${WEBSITE_APP_ROOT}${normalizedSlug}/page.tsx`;
1733
- };
1734
- var buildComponentsPath = (folderPath) => `${PAGE_COMPONENTS_ROOT}/${folderPath}`;
1735
- var resolveBlogSectionRoot = (slugFolderPath) => {
1736
- if (!slugFolderPath) {
1737
- return "blog";
1738
- }
1739
- const segments = slugFolderPath.split("/").filter(Boolean);
1740
- if (segments.length <= 1) {
1741
- return "blog";
1742
- }
1743
- return segments.slice(0, -1).join("/");
1744
- };
1745
- function resolvePrimeUiPageExportPaths({
1746
- pageType,
1747
- slug
1748
- }) {
1749
- const normalizedSlug = normalizeSlug(slug);
1750
- const slugFolderPath = slugToFolderPath(normalizedSlug);
1751
- switch (pageType) {
1752
- case "landing": {
1753
- const componentsFolder = slugFolderPath || "home";
1754
- return {
1755
- pagePath: buildWebsitePagePath(normalizedSlug),
1756
- componentsPath: buildComponentsPath(componentsFolder)
1757
- };
1758
- }
1759
- case "pricing":
1760
- case "contact-us": {
1761
- const componentsFolder = slugFolderPath || pageType;
1762
- return {
1763
- pagePath: buildWebsitePagePath(normalizedSlug),
1764
- componentsPath: buildComponentsPath(componentsFolder)
1765
- };
1766
- }
1767
- case "docs": {
1768
- const docsFolder = slugFolderPath || "docs";
1769
- return {
1770
- pagePath: `${WEBSITE_APP_ROOT}/${docsFolder}/[[...slug]]/page.tsx`,
1771
- componentsPath: buildComponentsPath("docs")
1772
- };
1773
- }
1774
- case "blogIndex": {
1775
- const blogFolder = slugFolderPath || "blog";
1776
- return {
1777
- pagePath: `${WEBSITE_APP_ROOT}/${blogFolder}/page.tsx`,
1778
- componentsPath: buildComponentsPath("blog")
1779
- };
1780
- }
1781
- case "blogPost": {
1782
- const blogSectionRoot = resolveBlogSectionRoot(slugFolderPath);
1783
- return {
1784
- pagePath: `${WEBSITE_APP_ROOT}/${blogSectionRoot}/[slug]/page.tsx`,
1785
- componentsPath: buildComponentsPath("blog")
1786
- };
1787
- }
1788
- case "legal":
1789
- return {
1790
- pagePath: buildWebsitePagePath(normalizedSlug),
1791
- componentsPath: buildComponentsPath("legal")
1792
- };
1793
- default: {
1794
- const fallbackFolder = slugFolderPath || toPathSegment(pageType);
1795
- return {
1796
- pagePath: buildWebsitePagePath(normalizedSlug),
1797
- componentsPath: buildComponentsPath(fallbackFolder)
1798
- };
1799
- }
1800
- }
1801
- }
1802
-
1803
1745
  // src/lib/text-diff.ts
1804
1746
  var DEFAULT_MAX_DIFF_CHARS = 16e3;
1805
1747
  var MAX_LCS_CELLS = 2e6;
@@ -1894,15 +1836,7 @@ var DEPENDENCY_SECTIONS = [
1894
1836
  "devDependencies",
1895
1837
  "peerDependencies"
1896
1838
  ];
1897
- var REWRITABLE_IMPORT_EXTENSIONS = /* @__PURE__ */ new Set([
1898
- ".ts",
1899
- ".tsx",
1900
- ".js",
1901
- ".jsx",
1902
- ".mjs",
1903
- ".cjs"
1904
- ]);
1905
- function normalizeSlug2(slug) {
1839
+ function normalizeSlug(slug) {
1906
1840
  const trimmed = slug.trim();
1907
1841
  if (!trimmed || trimmed === "/") {
1908
1842
  return "/";
@@ -1916,9 +1850,6 @@ function toPosixPath(value) {
1916
1850
  function toProjectRelative(rootPath, absolutePath) {
1917
1851
  return toPosixPath(path9.relative(rootPath, absolutePath));
1918
1852
  }
1919
- function escapeRegExp(value) {
1920
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1921
- }
1922
1853
  function isBinaryBuffer(buffer) {
1923
1854
  const limit = Math.min(buffer.length, 8e3);
1924
1855
  for (let index = 0; index < limit; index += 1) {
@@ -1928,66 +1859,6 @@ function isBinaryBuffer(buffer) {
1928
1859
  }
1929
1860
  return false;
1930
1861
  }
1931
- function stripSrcPrefix(relativePath) {
1932
- return relativePath.replace(/^src\//, "");
1933
- }
1934
- function buildImportRewritePlan(sourceComponentsPath, targetComponentsPath) {
1935
- const normalizedSource = toPosixPath(sourceComponentsPath);
1936
- const normalizedTarget = toPosixPath(targetComponentsPath);
1937
- if (normalizedSource === normalizedTarget) {
1938
- return null;
1939
- }
1940
- const sourceAtAliasPrefix = `@/${stripSrcPrefix(normalizedSource)}`;
1941
- const targetAtAliasPrefix = `@/${stripSrcPrefix(normalizedTarget)}`;
1942
- const sourceRootAliasPrefix = `@root/${normalizedSource}`;
1943
- const targetRootAliasPrefix = `@root/${normalizedTarget}`;
1944
- return {
1945
- sourceAtAliasPrefix,
1946
- targetAtAliasPrefix,
1947
- sourceRootAliasPrefix,
1948
- targetRootAliasPrefix
1949
- };
1950
- }
1951
- function replaceAliasPrefixInImportStrings(content, sourcePrefix, targetPrefix) {
1952
- const pattern = new RegExp(
1953
- `(["'\`])${escapeRegExp(sourcePrefix)}(?=\\/|\\1)`,
1954
- "g"
1955
- );
1956
- return content.replace(pattern, `$1${targetPrefix}`);
1957
- }
1958
- function rewriteImportsForRemappedSlug(content, plan) {
1959
- const afterAtAlias = replaceAliasPrefixInImportStrings(
1960
- content,
1961
- plan.sourceAtAliasPrefix,
1962
- plan.targetAtAliasPrefix
1963
- );
1964
- return replaceAliasPrefixInImportStrings(
1965
- afterAtAlias,
1966
- plan.sourceRootAliasPrefix,
1967
- plan.targetRootAliasPrefix
1968
- );
1969
- }
1970
- function buildPlannedSourceBuffer(sourceBuffer, sourceFilePath, importRewritePlan) {
1971
- if (!importRewritePlan) {
1972
- return sourceBuffer;
1973
- }
1974
- const extension = path9.extname(sourceFilePath).toLowerCase();
1975
- if (!REWRITABLE_IMPORT_EXTENSIONS.has(extension)) {
1976
- return sourceBuffer;
1977
- }
1978
- if (isBinaryBuffer(sourceBuffer)) {
1979
- return sourceBuffer;
1980
- }
1981
- const sourceText = sourceBuffer.toString("utf-8");
1982
- const rewritten = rewriteImportsForRemappedSlug(
1983
- sourceText,
1984
- importRewritePlan
1985
- );
1986
- if (rewritten === sourceText) {
1987
- return sourceBuffer;
1988
- }
1989
- return Buffer.from(rewritten, "utf-8");
1990
- }
1991
1862
  async function readJsonFile(filePath) {
1992
1863
  const content = await readFile3(filePath, "utf-8");
1993
1864
  return JSON.parse(content);
@@ -2000,68 +1871,15 @@ async function fileExists2(filePath) {
2000
1871
  return false;
2001
1872
  }
2002
1873
  }
2003
- function isExportPageManifestRecord(value) {
2004
- if (!value || typeof value !== "object") {
2005
- return false;
2006
- }
2007
- const maybe = value;
2008
- return typeof maybe.success === "boolean" && typeof maybe.message === "string" && Array.isArray(maybe.files) && maybe.files.every((item) => typeof item === "string");
2009
- }
2010
- function isExportStatus(value) {
2011
- return value === "in_progress" || value === "completed" || value === "failed";
2012
- }
2013
- function isExportSummaryRecord(value) {
2014
- if (!value || typeof value !== "object") {
2015
- return false;
2016
- }
2017
- const maybe = value;
2018
- return typeof maybe.total === "number" && typeof maybe.successful === "number" && typeof maybe.failed === "number";
2019
- }
2020
- function isExportedComponentRecord(value) {
2021
- if (!value || typeof value !== "object") {
2022
- return false;
2023
- }
2024
- const maybe = value;
2025
- return typeof maybe.componentKey === "string" && typeof maybe.enabled === "boolean" && Array.isArray(maybe.files) && maybe.files.every((item) => typeof item === "string") && typeof maybe.message === "string";
2026
- }
2027
- function isExportPageRecord(value) {
2028
- if (!value || typeof value !== "object") {
2029
- return false;
2030
- }
2031
- const maybe = value;
2032
- const title = maybe.title;
2033
- return typeof maybe.id === "string" && (typeof title === "string" || typeof title === "undefined") && typeof maybe.slug === "string" && typeof maybe.pageType === "string" && maybe.isReadyToExport === true && typeof maybe.pagePath === "string" && typeof maybe.componentsPath === "string" && isExportPageManifestRecord(maybe.manifest);
2034
- }
2035
1874
  function parseManifest(value) {
2036
- if (!value || typeof value !== "object") {
2037
- throw new Error("Invalid export manifest format.");
2038
- }
2039
- const maybe = value;
2040
- const exportPayload = maybe.export;
2041
- if (!exportPayload || typeof exportPayload !== "object") {
2042
- throw new Error("Export manifest export payload is invalid.");
2043
- }
2044
- const exportObject = exportPayload;
2045
- const status = exportObject.status;
2046
- const summary = exportObject.summary;
2047
- const components = exportObject.components;
2048
- if (typeof exportObject.id !== "string" || !isExportStatus(status) || typeof exportObject.createdAt !== "string" || !("expiresAt" in exportObject) || !(typeof exportObject.expiresAt === "string" || exportObject.expiresAt === null) || !isExportSummaryRecord(summary) || !Array.isArray(components) || !components.every(isExportedComponentRecord) || !Array.isArray(maybe.pages)) {
2049
- throw new Error("Export manifest does not match expected schema.");
2050
- }
2051
- if (!maybe.pages.every(isExportPageRecord)) {
2052
- throw new Error("Export manifest pages payload is invalid.");
1875
+ try {
1876
+ return parsePrimeUiExportManifest(value);
1877
+ } catch (error) {
1878
+ if (error instanceof Error && error.message === "Export manifest is invalid.") {
1879
+ throw new Error("Invalid export manifest format.");
1880
+ }
1881
+ throw error;
2053
1882
  }
2054
- return {
2055
- export: {
2056
- id: exportObject.id,
2057
- status,
2058
- createdAt: exportObject.createdAt,
2059
- expiresAt: exportObject.expiresAt,
2060
- summary,
2061
- components
2062
- },
2063
- pages: maybe.pages
2064
- };
2065
1883
  }
2066
1884
  async function resolveManifestCandidateFiles(input) {
2067
1885
  const result = /* @__PURE__ */ new Set();
@@ -2109,6 +1927,9 @@ async function resolveSingleExportDirectory(exportsRoot) {
2109
1927
  exportPath: path9.join(exportsRoot, exportId)
2110
1928
  };
2111
1929
  }
1930
+ function createCopyId() {
1931
+ return `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
1932
+ }
2112
1933
  function ensureSafeTargetPath(projectRoot, targetPath) {
2113
1934
  const relative = path9.relative(projectRoot, targetPath);
2114
1935
  if (relative.startsWith("..") || path9.isAbsolute(relative)) {
@@ -2184,11 +2005,7 @@ function resolveTargetFilePath(input) {
2184
2005
  return path9.join(projectRoot, relativeToExport);
2185
2006
  }
2186
2007
  async function copyPageFromExport(input) {
2187
- const normalizedOriginSlug = normalizeSlug2(input.originPageSlug);
2188
- const normalizedActualSlug = normalizeSlug2(
2189
- input.actualPageSlug ?? input.originPageSlug
2190
- );
2191
- const isSlugRemapped = normalizedActualSlug !== normalizedOriginSlug;
2008
+ const normalizedOriginSlug = normalizeSlug(input.originPageSlug);
2192
2009
  const { exportId, exportPath } = await resolveSingleExportDirectory(
2193
2010
  input.exportsRoot
2194
2011
  );
@@ -2208,7 +2025,7 @@ async function copyPageFromExport(input) {
2208
2025
  );
2209
2026
  }
2210
2027
  const page = manifest.pages.find(
2211
- (item) => normalizeSlug2(item.slug) === normalizedOriginSlug
2028
+ (item) => normalizeSlug(item.slug) === normalizedOriginSlug
2212
2029
  );
2213
2030
  if (!page) {
2214
2031
  throw new Error(
@@ -2229,19 +2046,11 @@ async function copyPageFromExport(input) {
2229
2046
  `Source components folder not found: ${sourceComponentsPath}`
2230
2047
  );
2231
2048
  }
2232
- const targetPaths = normalizedActualSlug === normalizedOriginSlug ? {
2233
- pagePath: page.pagePath,
2234
- componentsPath: page.componentsPath
2235
- } : resolvePrimeUiPageExportPaths({
2236
- pageType: page.pageType,
2237
- slug: normalizedActualSlug
2238
- });
2239
- const targetPagePath = path9.join(input.projectRoot, targetPaths.pagePath);
2049
+ const targetPagePath = path9.join(input.projectRoot, page.pagePath);
2240
2050
  const targetComponentsPath = path9.join(
2241
2051
  input.projectRoot,
2242
- targetPaths.componentsPath
2052
+ page.componentsPath
2243
2053
  );
2244
- const importRewritePlan = isSlugRemapped ? buildImportRewritePlan(page.componentsPath, targetPaths.componentsPath) : null;
2245
2054
  ensureSafeTargetPath(input.projectRoot, targetPagePath);
2246
2055
  ensureSafeTargetPath(input.projectRoot, targetComponentsPath);
2247
2056
  const candidateFiles = await resolveManifestCandidateFiles({
@@ -2257,6 +2066,7 @@ async function copyPageFromExport(input) {
2257
2066
  const newFiles = [];
2258
2067
  const identicalFiles = [];
2259
2068
  const conflictFiles = [];
2069
+ const conflictReportEntries = [];
2260
2070
  for (const sourceFilePath of candidateFiles) {
2261
2071
  const targetFilePath = resolveTargetFilePath({
2262
2072
  sourceFilePath,
@@ -2269,11 +2079,7 @@ async function copyPageFromExport(input) {
2269
2079
  });
2270
2080
  ensureSafeTargetPath(input.projectRoot, targetFilePath);
2271
2081
  const sourceBuffer = await readFile3(sourceFilePath);
2272
- const plannedSourceBuffer = buildPlannedSourceBuffer(
2273
- sourceBuffer,
2274
- sourceFilePath,
2275
- importRewritePlan
2276
- );
2082
+ const plannedSourceBuffer = sourceBuffer;
2277
2083
  let targetBuffer = null;
2278
2084
  try {
2279
2085
  targetBuffer = await readFile3(targetFilePath);
@@ -2285,17 +2091,11 @@ async function copyPageFromExport(input) {
2285
2091
  if (!targetBuffer) {
2286
2092
  await ensureDir(path9.dirname(targetFilePath));
2287
2093
  await writeFile2(targetFilePath, plannedSourceBuffer);
2288
- newFiles.push({
2289
- sourcePath: sourceRelative,
2290
- targetPath: targetRelative
2291
- });
2094
+ newFiles.push(targetRelative);
2292
2095
  continue;
2293
2096
  }
2294
2097
  if (plannedSourceBuffer.equals(targetBuffer)) {
2295
- identicalFiles.push({
2296
- sourcePath: sourceRelative,
2297
- targetPath: targetRelative
2298
- });
2098
+ identicalFiles.push(targetRelative);
2299
2099
  continue;
2300
2100
  }
2301
2101
  const isBinary = isBinaryBuffer(plannedSourceBuffer) || isBinaryBuffer(targetBuffer);
@@ -2305,7 +2105,7 @@ async function copyPageFromExport(input) {
2305
2105
  oldLabel: `user/${targetRelative}`,
2306
2106
  newLabel: `export/${sourceRelative}`
2307
2107
  });
2308
- conflictFiles.push({
2108
+ conflictReportEntries.push({
2309
2109
  sourcePath: sourceRelative,
2310
2110
  targetPath: targetRelative,
2311
2111
  diff,
@@ -2366,24 +2166,74 @@ async function copyPageFromExport(input) {
2366
2166
  "utf-8"
2367
2167
  );
2368
2168
  }
2169
+ const sortedAddedDependencies = addedDependencies.sort(
2170
+ (a, b) => a.packageName.localeCompare(b.packageName)
2171
+ );
2172
+ const sortedDependenciesVersionConflicts = dependenciesVersionConflicts.sort(
2173
+ (a, b) => a.packageName.localeCompare(b.packageName)
2174
+ );
2175
+ const sortedConflictReportEntries = conflictReportEntries.sort(
2176
+ (a, b) => a.targetPath.localeCompare(b.targetPath)
2177
+ );
2178
+ for (const entry of sortedConflictReportEntries) {
2179
+ conflictFiles.push({
2180
+ targetPath: entry.targetPath,
2181
+ isBinary: entry.isBinary
2182
+ });
2183
+ }
2184
+ const copyId = createCopyId();
2185
+ const reportPath = path9.join(
2186
+ input.exportsRoot,
2187
+ `${exportId}.copy-report-${copyId}.json`
2188
+ );
2189
+ const report = {
2190
+ reportPath,
2191
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
2192
+ exportId,
2193
+ originPageSlug: normalizedOriginSlug,
2194
+ sourcePagePath: page.pagePath,
2195
+ sourceComponentsPath: page.componentsPath,
2196
+ conflicts: sortedConflictReportEntries
2197
+ };
2198
+ await writeFile2(reportPath, `${JSON.stringify(report, null, 2)}
2199
+ `, "utf-8");
2200
+ const hasFileConflicts = conflictFiles.length > 0;
2201
+ const hasDependencyVersionConflicts = sortedDependenciesVersionConflicts.length > 0;
2202
+ const needsReview = hasFileConflicts || hasDependencyVersionConflicts;
2203
+ const status = needsReview ? "needs_review" : "completed";
2204
+ const messageParts = [];
2205
+ if (hasFileConflicts) {
2206
+ messageParts.push(
2207
+ `Conflicts detected. Manual resolution is required before any follow-up integration steps. Review ${reportPath} for full diffs and resolve conflicts based on the target project behavior, the imported page functionality, and the possibility that MCP may run against third-party projects not generated by PrimeUI.`
2208
+ );
2209
+ } else if (hasDependencyVersionConflicts) {
2210
+ messageParts.push(
2211
+ `Dependency version conflicts detected. Manual resolution is required before any follow-up integration steps. Review ${reportPath} for full local report details, inspect dependenciesVersionConflicts in this response, and resolve versions based on the target project behavior and the imported page functionality.`
2212
+ );
2213
+ } else {
2214
+ messageParts.push(
2215
+ `Copy completed with no file conflicts or dependency version conflicts. Review ${reportPath} for full local details if needed.`
2216
+ );
2217
+ }
2218
+ if (sortedAddedDependencies.length > 0) {
2219
+ messageParts.push(
2220
+ "Missing dependencies were added to package.json but are NOT installed yet. Run dependency installation manually with the package manager used by the target project."
2221
+ );
2222
+ }
2369
2223
  return {
2224
+ status,
2225
+ message: messageParts.join(" "),
2226
+ reportPath,
2370
2227
  exportId,
2371
2228
  exportPath,
2372
2229
  originPageSlug: normalizedOriginSlug,
2373
- actualPageSlug: normalizedActualSlug,
2374
2230
  sourcePagePath: page.pagePath,
2375
- targetPagePath: targetPaths.pagePath,
2376
2231
  sourceComponentsPath: page.componentsPath,
2377
- targetComponentsPath: targetPaths.componentsPath,
2378
2232
  newFiles,
2379
2233
  identicalFiles,
2380
2234
  conflictFiles,
2381
- addedDependencies: addedDependencies.sort(
2382
- (a, b) => a.packageName.localeCompare(b.packageName)
2383
- ),
2384
- dependenciesVersionConflicts: dependenciesVersionConflicts.sort(
2385
- (a, b) => a.packageName.localeCompare(b.packageName)
2386
- ),
2235
+ addedDependencies: sortedAddedDependencies,
2236
+ dependenciesVersionConflicts: sortedDependenciesVersionConflicts,
2387
2237
  summary: {
2388
2238
  totalCandidateFiles: candidateFiles.length,
2389
2239
  copiedFiles: newFiles.length,
@@ -2486,72 +2336,9 @@ function buildInspectPageReport(input) {
2486
2336
  }
2487
2337
 
2488
2338
  // src/services/project-sync-service.ts
2489
- function isExportStatus2(value) {
2490
- return value === "in_progress" || value === "completed" || value === "failed";
2491
- }
2492
- function isExportSummary(value) {
2493
- if (!value || typeof value !== "object") {
2494
- return false;
2495
- }
2496
- const maybe = value;
2497
- return typeof maybe.total === "number" && typeof maybe.successful === "number" && typeof maybe.failed === "number";
2498
- }
2499
- function isExportedComponent(value) {
2500
- if (!value || typeof value !== "object") {
2501
- return false;
2502
- }
2503
- const maybe = value;
2504
- return typeof maybe.componentKey === "string" && typeof maybe.enabled === "boolean" && Array.isArray(maybe.files) && maybe.files.every((item) => typeof item === "string") && typeof maybe.message === "string";
2505
- }
2506
- function isExportPageManifest(value) {
2507
- if (!value || typeof value !== "object") {
2508
- return false;
2509
- }
2510
- const maybe = value;
2511
- return typeof maybe.success === "boolean" && typeof maybe.message === "string" && Array.isArray(maybe.files) && maybe.files.every((item) => typeof item === "string");
2512
- }
2513
- function isExportPage(value) {
2514
- if (!value || typeof value !== "object") {
2515
- return false;
2516
- }
2517
- const maybe = value;
2518
- const title = maybe.title;
2519
- return typeof maybe.id === "string" && (typeof title === "string" || typeof title === "undefined") && typeof maybe.slug === "string" && typeof maybe.pageType === "string" && maybe.isReadyToExport === true && typeof maybe.pagePath === "string" && typeof maybe.componentsPath === "string" && isExportPageManifest(maybe.manifest);
2520
- }
2521
2339
  function buildManifestPath(exportsRoot, exportId) {
2522
2340
  return path10.join(exportsRoot, `${exportId}.manifest.json`);
2523
2341
  }
2524
- function parseExportManifest(value) {
2525
- if (!value || typeof value !== "object") {
2526
- throw new Error("Export manifest is invalid.");
2527
- }
2528
- const maybe = value;
2529
- const exportPayload = maybe.export;
2530
- if (!exportPayload || typeof exportPayload !== "object") {
2531
- throw new Error("Export manifest export payload is invalid.");
2532
- }
2533
- const exportObject = exportPayload;
2534
- const status = exportObject.status;
2535
- const summary = exportObject.summary;
2536
- const components = exportObject.components;
2537
- if (typeof exportObject.id !== "string" || !isExportStatus2(status) || typeof exportObject.createdAt !== "string" || !("expiresAt" in exportObject) || !(typeof exportObject.expiresAt === "string" || exportObject.expiresAt === null) || !isExportSummary(summary) || !Array.isArray(components) || !components.every(isExportedComponent) || !Array.isArray(maybe.pages)) {
2538
- throw new Error("Export manifest does not match expected schema.");
2539
- }
2540
- if (!maybe.pages.every(isExportPage)) {
2541
- throw new Error("Export manifest pages payload is invalid.");
2542
- }
2543
- return {
2544
- export: {
2545
- id: exportObject.id,
2546
- status,
2547
- createdAt: exportObject.createdAt,
2548
- expiresAt: exportObject.expiresAt,
2549
- summary,
2550
- components
2551
- },
2552
- pages: maybe.pages
2553
- };
2554
- }
2555
2342
  var ProjectSyncService = class {
2556
2343
  provider;
2557
2344
  projectRoot;
@@ -2595,7 +2382,7 @@ var ProjectSyncService = class {
2595
2382
  const manifestPath = buildManifestPath(this.exportsRoot, id);
2596
2383
  let manifest;
2597
2384
  try {
2598
- manifest = parseExportManifest(
2385
+ manifest = parsePrimeUiExportManifest(
2599
2386
  JSON.parse(await readFile4(manifestPath, "utf-8"))
2600
2387
  );
2601
2388
  } catch (error) {
@@ -2613,12 +2400,10 @@ var ProjectSyncService = class {
2613
2400
  await this.provider.downloadExportArchive(id, targetZipPath);
2614
2401
  await resetDir(targetProjectPath);
2615
2402
  await extractZip(targetZipPath, targetProjectPath);
2616
- const pages = manifest.pages;
2617
2403
  return {
2618
2404
  exportId: id,
2619
2405
  projectPath: targetProjectPath,
2620
- manifestPath,
2621
- pages
2406
+ manifestPath
2622
2407
  };
2623
2408
  }
2624
2409
  async inspectPage(slug, _context) {
@@ -2631,13 +2416,12 @@ var ProjectSyncService = class {
2631
2416
  reportRows: reportPayload.reportRows
2632
2417
  };
2633
2418
  }
2634
- async copyPage(originPageSlug, actualPageSlug, _context) {
2419
+ async copyPage(originPageSlug, _context) {
2635
2420
  await this.ensureTempLayout();
2636
2421
  return copyPageFromExport({
2637
2422
  projectRoot: this.targetProjectRoot,
2638
2423
  exportsRoot: this.exportsRoot,
2639
- originPageSlug,
2640
- actualPageSlug
2424
+ originPageSlug
2641
2425
  });
2642
2426
  }
2643
2427
  async clearTemp(_context) {
@@ -2727,10 +2511,10 @@ var LazyProjectSyncSource = class {
2727
2511
  (service) => service.inspectPage(slug, context)
2728
2512
  );
2729
2513
  }
2730
- async copyPage(originPageSlug, actualPageSlug, context) {
2514
+ async copyPage(originPageSlug, context) {
2731
2515
  return this.withMutationService(
2732
2516
  context,
2733
- (service) => service.copyPage(originPageSlug, actualPageSlug, context)
2517
+ (service) => service.copyPage(originPageSlug, context)
2734
2518
  );
2735
2519
  }
2736
2520
  async clearTemp(context) {
@@ -2771,35 +2555,48 @@ var pageSchema = z4.object({
2771
2555
  }).describe(
2772
2556
  "PrimeUI page descriptor used by project and export tools. Paths are always relative to export project root."
2773
2557
  );
2774
- var exportStatusSchema2 = z4.enum(["in_progress", "completed", "failed"]).describe(
2558
+ var exportStatusSchema = z4.enum(["in_progress", "completed", "failed"]).describe(
2775
2559
  "Export lifecycle state. Use 'completed' before calling download_export."
2776
2560
  );
2777
2561
  var exportItemSchema = z4.object({
2778
2562
  id: z4.string().describe(
2779
2563
  "Export identifier. Pass this value to download_export input.id."
2780
2564
  ),
2781
- status: exportStatusSchema2,
2565
+ status: exportStatusSchema,
2782
2566
  createdAt: z4.string().describe("Export creation timestamp in ISO-8601 UTC format.")
2783
2567
  }).describe("Single export record from PrimeUI export history.");
2784
- var exportSummarySchema2 = z4.object({
2568
+ var exportSummarySchema = z4.object({
2785
2569
  total: z4.number().describe("Total pages processed in this export run."),
2786
2570
  successful: z4.number().describe("Number of pages exported successfully."),
2787
2571
  failed: z4.number().describe("Number of pages that failed export.")
2788
2572
  });
2789
- var exportComponentSchema = z4.object({
2790
- componentKey: z4.string().describe("Global component key from export manifest."),
2791
- enabled: z4.boolean().describe("True when this global component was exported."),
2792
- files: z4.array(z4.string()).describe("Files associated with this global component."),
2793
- message: z4.string().describe("Export status message for this global component.")
2573
+ var exportManifestSchema = z4.object({
2574
+ success: z4.boolean().describe("True when export processing succeeded for this item."),
2575
+ message: z4.string().describe("Export status message for this item."),
2576
+ files: z4.array(z4.string()).describe("Authoritative exported file list for this item.")
2794
2577
  });
2795
- var exportPageManifestSchema2 = z4.object({
2796
- success: z4.boolean().describe("True when page export succeeded in this export run."),
2797
- message: z4.string().describe("Export status message for this page."),
2578
+ var exportableSchema = z4.object({
2579
+ key: z4.string().describe("Shared exportable key from export manifest."),
2580
+ isReadyToExport: z4.boolean().describe("True when this shared exportable was eligible for export."),
2581
+ manifest: exportManifestSchema.describe(
2582
+ "Export manifest for this shared exportable, aligned with page manifest shape."
2583
+ )
2584
+ });
2585
+ var projectExportableSchema = z4.object({
2586
+ key: z4.string().describe("Stable shared exportable key from PrimeUI project info."),
2587
+ description: z4.string().describe(
2588
+ "Agent-oriented summary of what this shared exportable provides."
2589
+ ),
2590
+ isReadyToExport: z4.boolean().describe(
2591
+ "Best-effort readiness snapshot for whether this shared exportable can be included in export now."
2592
+ )
2593
+ });
2594
+ var exportPageManifestSchema = exportManifestSchema.extend({
2798
2595
  files: z4.array(z4.string()).describe(
2799
2596
  "Authoritative list of page-related files from PrimeUI export manifest, including shared project files required by this page."
2800
2597
  )
2801
2598
  });
2802
- var exportPageSchema2 = z4.object({
2599
+ var exportPageSchema = z4.object({
2803
2600
  id: z4.string().describe("Stable PrimeUI page identifier for this export entry."),
2804
2601
  title: z4.string().optional().describe(
2805
2602
  "Optional page title from export manifest. Can be undefined for some legacy records."
@@ -2809,17 +2606,7 @@ var exportPageSchema2 = z4.object({
2809
2606
  isReadyToExport: z4.literal(true).describe("Always true for pages included in export payload."),
2810
2607
  pagePath: z4.string().describe("Page source file path relative to export root."),
2811
2608
  componentsPath: z4.string().describe("Page components directory path relative to export root."),
2812
- manifest: exportPageManifestSchema2
2813
- });
2814
- var fileTransferSchema = z4.object({
2815
- sourcePath: z4.string().describe("Relative source file path inside downloaded export root."),
2816
- targetPath: z4.string().describe("Relative target file path inside user project root.")
2817
- });
2818
- var conflictFileSchema = fileTransferSchema.extend({
2819
- diff: z4.string().describe(
2820
- "Unified diff between user file and export file. For binary files the diff contains a plain message."
2821
- ),
2822
- isBinary: z4.boolean().describe("True if conflict comparison was treated as binary data.")
2609
+ manifest: exportPageManifestSchema
2823
2610
  });
2824
2611
  var dependencySectionSchema = z4.enum([
2825
2612
  "dependencies",
@@ -2841,6 +2628,10 @@ var dependencyVersionConflictSchema = z4.object({
2841
2628
  exportVersion: z4.string().describe("Version found in exported project's package.json."),
2842
2629
  userVersion: z4.string().describe("Version currently present in user's package.json.")
2843
2630
  });
2631
+ var conflictFileSchema = z4.object({
2632
+ targetPath: z4.string().describe("Relative conflict target path inside user project root."),
2633
+ isBinary: z4.boolean().describe("True if conflict comparison was treated as binary data.")
2634
+ });
2844
2635
  var pageDetailsSchema = pageSchema.extend({
2845
2636
  pageInstruction: z4.string().nullable().describe(
2846
2637
  "Current instruction text for the active page variant. Null when no active variant is set."
@@ -2889,7 +2680,7 @@ WORKFLOW ORDER (always follow this sequence):
2889
2680
  2. get_project_info -> discover PrimeUI pages
2890
2681
  3. Reconcile PrimeUI pages with local project pages/routes/paths, then confirm target pages with user
2891
2682
  4. inspect_page -> inspect selected page components and produce a structured comparison table
2892
- 5. create_export -> generate export snapshot and local manifest with page file lists + global components
2683
+ 5. create_export -> generate export snapshot and local manifest with page file lists + shared exportables
2893
2684
  6. download_export -> download to temp directory
2894
2685
  7. copy_page -> copy one page safely (repeat for each selected page)
2895
2686
  8. Reconcile integration points and resolve reported conflicts, if any
@@ -2917,7 +2708,7 @@ CRITICAL RULES FOR PAGE IMPORT:
2917
2708
  - Before creating export, ask user which pages to add/update (specific pages or all missing pages) and keep that choice in thread context.
2918
2709
  - create_export response includes:
2919
2710
  - page-level manifest files per page ('pages[].manifest.files'),
2920
- - global components list ('export.components').
2711
+ - shared exportables list ('export.exportables').
2921
2712
  Mention both to user after create_export, because this is the source of truth for copy decisions.
2922
2713
  - The downloaded export in .primeui/temp/ contains a full standalone Next.js project.
2923
2714
  Do NOT copy it wholesale.
@@ -2935,7 +2726,7 @@ CRITICAL RULES FOR PAGE IMPORT:
2935
2726
  `.trim();
2936
2727
  var toolGetProjectInfo = {
2937
2728
  title: "PrimeUI Project Info",
2938
- description: `ENTRY POINT for all PrimeUI import operations. Always start here. Returns project metadata and the full list of available pages.
2729
+ description: `ENTRY POINT for all PrimeUI import operations. Always start here. Returns project metadata plus a lightweight inventory of pages and shared exportables you can reason about before export.
2939
2730
 
2940
2731
  WHEN TO USE: Call this FIRST when user wants to import, add, sync, pull, or transfer a page from PrimeUI. Intent examples (semantic intent, not exact phrase matching): ${TRIGGER_PHRASES}.
2941
2732
 
@@ -2964,6 +2755,9 @@ ${WORKFLOW_SUMMARY}`,
2964
2755
  metadata: z4.record(z4.unknown()).describe(
2965
2756
  "Additional project metadata from PrimeUI. May include project-description and other context fields."
2966
2757
  ),
2758
+ exportables: z4.array(projectExportableSchema).describe(
2759
+ "Lightweight inventory of shared exportables (for example logo, cookie banner, announcement banner, theme, image assets). Use description + isReadyToExport to plan imports before create_export."
2760
+ ),
2967
2761
  pages: z4.array(pageSchema).describe(
2968
2762
  "All pages visible for this project context. Filter by user request and isReadyToExport before creating export."
2969
2763
  )
@@ -3050,7 +2844,7 @@ ${WORKFLOW_SUMMARY}`,
3050
2844
  };
3051
2845
  var toolCreateExport = {
3052
2846
  title: "PrimeUI Create Export",
3053
- description: `Create a new export snapshot from the current PrimeUI project state and wait for completion. Returns strict export manifest payload from API, including page-level file manifests and global components.
2847
+ description: `Create a new export snapshot from the current PrimeUI project state and wait for completion. Returns strict export manifest payload from API, including page-level file manifests and shared exportables.
3054
2848
 
3055
2849
  WHEN TO USE: Call this AFTER the user has confirmed which pages they want to import via get_project_info. This tool is REQUIRED before download_export, unless the user explicitly and directly asked to download a specific previous export.
3056
2850
 
@@ -3058,7 +2852,7 @@ AFTER CALLING:
3058
2852
  - Verify that all user-selected pages are present in the export result AND have isReadyToExport: true.
3059
2853
  - If path mismatch pages were flagged during project-info reconciliation, ensure they are included for deeper comparison after download.
3060
2854
  - If any required page is missing or not ready, report and pause for user decision before proceeding.
3061
- - Mention that global components are available in export.components and can be transferred separately if needed.
2855
+ - Mention that shared exportables are available in export.exportables and can be transferred separately if needed.
3062
2856
  - Local sidecar manifest is saved to .primeui/temp/exports/[exportId].manifest.json from this API payload.
3063
2857
  - Use the returned export ID to call download_export.
3064
2858
 
@@ -3069,19 +2863,19 @@ ${WORKFLOW_SUMMARY}`,
3069
2863
  id: z4.string().describe(
3070
2864
  "Freshly created export identifier. Use this as download_export input.id."
3071
2865
  ),
3072
- status: exportStatusSchema2,
2866
+ status: exportStatusSchema,
3073
2867
  createdAt: z4.string().describe("Export creation timestamp in ISO-8601 UTC format."),
3074
2868
  expiresAt: z4.string().nullable().describe(
3075
2869
  "Export expiration timestamp in ISO-8601 UTC format, or null when export has no explicit expiration."
3076
2870
  ),
3077
- summary: exportSummarySchema2.describe(
2871
+ summary: exportSummarySchema.describe(
3078
2872
  "Export run summary with total/successful/failed counters."
3079
2873
  ),
3080
- components: z4.array(exportComponentSchema).describe(
3081
- "Global component export manifest. These components are independent from page-level manifests."
2874
+ exportables: z4.array(exportableSchema).describe(
2875
+ "Shared exportable manifest. These entries are independent from page-level manifests."
3082
2876
  )
3083
2877
  }).describe("Created export summary."),
3084
- pages: z4.array(exportPageSchema2).describe(
2878
+ pages: z4.array(exportPageSchema).describe(
3085
2879
  "Strict page payload associated with this export, including per-page manifest files list."
3086
2880
  )
3087
2881
  }),
@@ -3107,9 +2901,8 @@ NOTE:
3107
2901
  AFTER DOWNLOAD:
3108
2902
  - Use manifestPath from this response as the contract for page slug/path mapping and manifest file lists in copy operations.
3109
2903
  - For each selected page, call copy_page with:
3110
- - originPageSlug (required),
3111
- - actualPageSlug (optional, if route remap is needed).
3112
- - If there are unresolved conflicts in copy report, stop and ask the user.
2904
+ - originPageSlug (required).
2905
+ - Treat conflicts as normal and expected. If copy_page returns needs_review, stop follow-up integration and resolve manually first.
3113
2906
  - Do not force cleanup at flow end; keep downloaded export files available for validation and follow-up checks.
3114
2907
 
3115
2908
  ${WORKFLOW_SUMMARY}`,
@@ -3128,9 +2921,6 @@ AFTER DOWNLOAD:
3128
2921
  ),
3129
2922
  manifestPath: z4.string().describe(
3130
2923
  "Absolute path to sidecar export manifest file (.primeui/temp/exports/[exportId].manifest.json) saved by create_export and required by copy_page."
3131
- ),
3132
- pages: z4.array(exportPageSchema2).describe(
3133
- "Page descriptors loaded from local sidecar export manifest for import decisions."
3134
2924
  )
3135
2925
  }),
3136
2926
  annotations: {
@@ -3147,46 +2937,46 @@ var toolCopyPage = {
3147
2937
  WHEN TO USE:
3148
2938
  - Call this AFTER download_export.
3149
2939
  - Call once per selected page.
3150
- - Use actualPageSlug only when user wants to remap route during import.
3151
2940
 
3152
2941
  BEHAVIOR:
3153
2942
  - Reads export sidecar manifest to resolve originPageSlug -> pagePath/componentsPath.
3154
2943
  - Copies and validates files strictly from pages[].manifest.files for the selected page.
3155
2944
  - Never overwrites existing conflicting files.
2945
+ - Writes full conflict diffs to a local report file in .primeui/temp/exports/[exportId].copy-report-[copyId].json.
3156
2946
  - Reports:
3157
- a) copied new files,
3158
- b) identical existing files,
3159
- c) conflicting files with diff,
2947
+ a) copied new files (relative target paths),
2948
+ b) identical existing files (relative target paths),
2949
+ c) conflicting files as lightweight metadata (relative target paths + binary flag, no inline diff),
3160
2950
  d) missing dependencies added to package.json,
3161
2951
  e) dependency version conflicts (report-only, no auto upgrade).
3162
2952
  - Adds only missing dependencies to package.json (dependencies/devDependencies/peerDependencies).
3163
2953
  - Never updates existing dependency versions and never runs install commands.
2954
+ - If status is needs_review, page import is NOT complete and manual review is required before continuing. This can be caused by file conflicts or dependency version conflicts.
3164
2955
 
3165
2956
  ${WORKFLOW_SUMMARY}`,
3166
2957
  inputSchema: {
3167
2958
  projectRoot: projectRootInputSchema,
3168
2959
  originPageSlug: z4.string().describe(
3169
2960
  "Source page slug from PrimeUI project pages list, for example '/', '/pricing', '/docs'."
3170
- ),
3171
- actualPageSlug: z4.string().optional().describe(
3172
- "Optional destination slug in user's project. If omitted, originPageSlug is used."
3173
2961
  )
3174
2962
  },
3175
2963
  outputSchema: z4.object({
2964
+ status: z4.enum(["completed", "needs_review"]).describe(
2965
+ "Decision state for next step. needs_review means manual review is required before follow-up integration because of file conflicts or dependency version conflicts."
2966
+ ),
2967
+ message: z4.string().describe(
2968
+ "Decision-oriented summary that includes resolved reportPath and manual follow-up instructions when needed."
2969
+ ),
2970
+ reportPath: z4.string().describe(
2971
+ "Absolute path to saved local report with full conflict diffs and details."
2972
+ ),
3176
2973
  exportId: z4.string().describe("Resolved local export identifier used for copy operation."),
3177
2974
  exportPath: z4.string().describe("Absolute path to local extracted export project root."),
3178
2975
  originPageSlug: z4.string().describe("Normalized source page slug requested for copy."),
3179
- actualPageSlug: z4.string().describe("Normalized destination slug used for target route paths."),
3180
2976
  sourcePagePath: z4.string().describe("Source page path relative to export root."),
3181
- targetPagePath: z4.string().describe("Destination page path relative to user project root."),
3182
2977
  sourceComponentsPath: z4.string().describe("Source components directory relative to export root."),
3183
- targetComponentsPath: z4.string().describe(
3184
- "Destination components directory relative to user project root."
3185
- ),
3186
- newFiles: z4.array(fileTransferSchema).describe("New files copied into user project without conflicts."),
3187
- identicalFiles: z4.array(fileTransferSchema).describe(
3188
- "Existing files in user project that are byte-identical to export files."
3189
- ),
2978
+ newFiles: z4.array(z4.string()).describe("Relative target paths for new files copied into user project."),
2979
+ identicalFiles: z4.array(z4.string()).describe("Relative target paths for existing byte-identical files."),
3190
2980
  conflictFiles: z4.array(conflictFileSchema).describe(
3191
2981
  "Files that already exist and differ from export version. Never overwritten."
3192
2982
  ),
@@ -3399,13 +3189,11 @@ function createPrimeUiMcpServer(source) {
3399
3189
  toolCopyPage,
3400
3190
  async ({
3401
3191
  originPageSlug,
3402
- actualPageSlug,
3403
3192
  projectRoot
3404
3193
  }) => {
3405
3194
  try {
3406
3195
  const result = await source.copyPage(
3407
3196
  originPageSlug,
3408
- actualPageSlug,
3409
3197
  { projectRoot }
3410
3198
  );
3411
3199
  return okResult("copy_page", result);