@primeuicom/mcp 1.1.0 → 1.2.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/service.js CHANGED
@@ -577,6 +577,30 @@ var primeUiExportPageSchema = z3.object({
577
577
  componentsPath: z3.string(),
578
578
  manifest: primeUiExportPageManifestSchema
579
579
  });
580
+ var primeUiPostExportPayloadExportSchema = z3.object({
581
+ id: z3.string(),
582
+ status: primeUiExportStatusSchema,
583
+ createdAt: z3.string().datetime({ offset: true }),
584
+ expiresAt: z3.string().datetime({ offset: true }).nullable(),
585
+ summary: primeUiExportSummarySchema,
586
+ exportables: z3.array(primeUiExportedExportableSchema)
587
+ });
588
+ var primeUiComponentExportComponentSchema = z3.object({
589
+ componentId: z3.string(),
590
+ name: z3.string(),
591
+ pageType: z3.string(),
592
+ family: z3.string(),
593
+ defaultPropsAvailable: z3.boolean(),
594
+ isReadyToExport: z3.boolean()
595
+ });
596
+ var primeUiComponentExportPageSchema = z3.object({
597
+ id: z3.string(),
598
+ title: z3.string().optional(),
599
+ slug: z3.string(),
600
+ pageType: z3.string(),
601
+ isReadyToExport: z3.boolean(),
602
+ manifest: primeUiExportPageManifestSchema
603
+ });
580
604
  var primeUiProjectInfoSchema = z3.object(
581
605
  {
582
606
  projectId: z3.string(),
@@ -654,6 +678,178 @@ var primeUiIssueReportSubmitResponseSchema = z3.object({
654
678
  accepted: z3.literal(true),
655
679
  ticketId: z3.string()
656
680
  });
681
+ var nullableDateStringSchema = z3.string().nullable();
682
+ var primeUiManagedSearchLastErrorSchema = z3.object({
683
+ at: nullableDateStringSchema,
684
+ code: z3.string().nullable(),
685
+ message: z3.string(),
686
+ scope: z3.enum(["project", "index", "job", "sync-run"])
687
+ });
688
+ var primeUiManagedSearchRuntimeModelSchema = z3.object({
689
+ additionalRuntimesSupported: z3.literal(true),
690
+ defaultRuntimeAutoWired: z3.literal(true),
691
+ defaultRuntimeSlug: z3.literal("prod"),
692
+ mode: z3.literal("runtime-first"),
693
+ panelCompatibility: z3.literal("disabled"),
694
+ stagingRuntimeAutoWired: z3.literal(false),
695
+ stagingRuntimeSlug: z3.literal("staging")
696
+ });
697
+ var primeUiManagedSearchRuntimeSchema = z3.object({
698
+ createdAt: z3.string(),
699
+ currentMeilisearchIndexUid: z3.string().nullable(),
700
+ currentQueryId: z3.string().nullable(),
701
+ id: z3.string(),
702
+ lastErrorSummary: z3.string().nullable(),
703
+ lastFailedSyncAt: nullableDateStringSchema,
704
+ lastSuccessfulSyncAt: nullableDateStringSchema,
705
+ name: z3.string(),
706
+ slug: z3.string(),
707
+ status: z3.enum([
708
+ "bootstrapping",
709
+ "active",
710
+ "indexing",
711
+ "failed",
712
+ "inactive"
713
+ ]),
714
+ updatedAt: z3.string()
715
+ });
716
+ var primeUiManagedSearchRootSchema = z3.object({
717
+ bootstrapCompletedAt: nullableDateStringSchema,
718
+ createdAt: nullableDateStringSchema,
719
+ defaultIndexId: z3.string().nullable(),
720
+ defaultSearchId: z3.string().nullable(),
721
+ enabled: z3.boolean(),
722
+ id: z3.string().nullable(),
723
+ lastErrorSummary: z3.string().nullable(),
724
+ lastFailedSyncAt: nullableDateStringSchema,
725
+ lastSuccessfulSyncAt: nullableDateStringSchema,
726
+ status: z3.enum(["inactive", "active", "degraded"]),
727
+ updatedAt: nullableDateStringSchema
728
+ });
729
+ var primeUiManagedSearchSourceSchema = z3.object({
730
+ activationMode: z3.enum(["auto-export", "manual"]),
731
+ configJson: z3.record(z3.unknown()),
732
+ createdAt: z3.string(),
733
+ id: z3.string(),
734
+ sourceKey: z3.string(),
735
+ sourceSnapshotJson: z3.record(z3.unknown()),
736
+ sourceType: z3.enum(["docs", "blog", "landing-pages"]),
737
+ status: z3.enum(["inactive", "active", "blocked"]),
738
+ updatedAt: z3.string()
739
+ });
740
+ var primeUiManagedSearchIndexSchema = z3.object({
741
+ createdAt: z3.string(),
742
+ documentCount: z3.number().int().nonnegative(),
743
+ id: z3.string(),
744
+ kind: z3.enum(["default-runtime", "custom"]),
745
+ lastErrorSummary: z3.string().nullable(),
746
+ lastFailedSyncAt: nullableDateStringSchema,
747
+ lastSuccessfulSyncAt: nullableDateStringSchema,
748
+ meilisearchIndexUid: z3.string().nullable(),
749
+ name: z3.string(),
750
+ publicSearchId: z3.string().nullable(),
751
+ queryRole: z3.enum(["default-runtime", "manual"]),
752
+ retiredAt: nullableDateStringSchema,
753
+ slug: z3.string(),
754
+ sourceSelectionJson: z3.record(z3.unknown()),
755
+ status: z3.enum(["inactive", "syncing", "ready", "failed", "degraded"]),
756
+ updatedAt: z3.string()
757
+ });
758
+ var primeUiManagedSearchJobSchema = z3.object({
759
+ attemptCount: z3.number().int().nonnegative(),
760
+ createdAt: z3.string(),
761
+ errorCode: z3.string().nullable(),
762
+ errorMessage: z3.string().nullable(),
763
+ finishedAt: nullableDateStringSchema,
764
+ id: z3.string(),
765
+ jobType: z3.enum(["sync", "reindex", "recover"]),
766
+ maxAttempts: z3.number().int().nonnegative(),
767
+ projectSearchIndexId: z3.string(),
768
+ requestedById: z3.string().nullable(),
769
+ requestedByType: z3.enum(["export", "studio-user", "cli", "system"]),
770
+ startedAt: nullableDateStringSchema,
771
+ state: z3.enum(["queued", "running", "succeeded", "failed", "cancelled"])
772
+ });
773
+ var primeUiManagedSearchSyncRunSchema = z3.object({
774
+ deletedDocumentCount: z3.number().int().nonnegative(),
775
+ durationMs: z3.number().int().nonnegative().nullable(),
776
+ errorSummary: z3.string().nullable(),
777
+ extractedDocumentCount: z3.number().int().nonnegative(),
778
+ finishedAt: nullableDateStringSchema,
779
+ id: z3.string(),
780
+ projectSearchIndexId: z3.string(),
781
+ projectSearchJobId: z3.string(),
782
+ startedAt: z3.string(),
783
+ status: z3.enum(["running", "succeeded", "failed", "cancelled"]),
784
+ writtenDocumentCount: z3.number().int().nonnegative()
785
+ });
786
+ var primeUiManagedSearchQueryProtectionSchema = z3.object({
787
+ enabled: z3.literal(true),
788
+ rateLimit: z3.object({
789
+ enabled: z3.literal(true),
790
+ windowMs: z3.number().int().positive(),
791
+ maxRequests: z3.number().int().positive(),
792
+ activeBucketCount: z3.number().int().nonnegative(),
793
+ limitedRequestCount: z3.number().int().nonnegative(),
794
+ recentLimitedAt: nullableDateStringSchema
795
+ }),
796
+ logging: z3.object({
797
+ enabled: z3.literal(true),
798
+ lastDayEventCount: z3.number().int().nonnegative(),
799
+ recentEventCount: z3.number().int().nonnegative(),
800
+ lastHourEventCount: z3.number().int().nonnegative(),
801
+ lastEventAt: nullableDateStringSchema
802
+ }),
803
+ cache: z3.object({
804
+ enabled: z3.literal(false),
805
+ ttlMs: z3.null(),
806
+ reason: z3.string()
807
+ })
808
+ });
809
+ var primeUiManagedSearchRelevanceSettingsSchema = z3.object({
810
+ displayedAttributes: z3.array(z3.string()),
811
+ facetSearch: z3.boolean(),
812
+ filterableAttributes: z3.array(z3.string()),
813
+ pagination: z3.object({
814
+ maxTotalHits: z3.number().int().positive()
815
+ }),
816
+ prefixSearch: z3.enum(["indexingTime", "disabled"]),
817
+ primaryKey: z3.string(),
818
+ proximityPrecision: z3.enum(["byWord", "byAttribute"]),
819
+ rankingRules: z3.array(z3.string()),
820
+ searchableAttributes: z3.array(z3.string()),
821
+ sortableAttributes: z3.array(z3.string()),
822
+ typoTolerance: z3.object({
823
+ disableOnAttributes: z3.array(z3.string()),
824
+ enabled: z3.boolean(),
825
+ minWordSizeForTypos: z3.object({
826
+ oneTypo: z3.number().int().positive(),
827
+ twoTypos: z3.number().int().positive()
828
+ })
829
+ })
830
+ });
831
+ var primeUiManagedSearchOverviewResponseSchema = z3.object({
832
+ customIndexes: z3.array(primeUiManagedSearchIndexSchema),
833
+ defaultIndex: primeUiManagedSearchIndexSchema.nullable(),
834
+ lastError: primeUiManagedSearchLastErrorSchema.nullable(),
835
+ projectId: z3.string(),
836
+ queryProtection: primeUiManagedSearchQueryProtectionSchema,
837
+ recentJobs: z3.array(primeUiManagedSearchJobSchema),
838
+ recentSyncRuns: z3.array(primeUiManagedSearchSyncRunSchema),
839
+ relevanceSettings: primeUiManagedSearchRelevanceSettingsSchema,
840
+ runtimeModel: primeUiManagedSearchRuntimeModelSchema,
841
+ runtimes: z3.array(primeUiManagedSearchRuntimeSchema),
842
+ search: primeUiManagedSearchRootSchema,
843
+ sources: z3.array(primeUiManagedSearchSourceSchema),
844
+ success: z3.literal(true)
845
+ });
846
+ var primeUiManagedSearchRuntimeMutationResponseSchema = z3.object({
847
+ success: z3.literal(true),
848
+ runtime: primeUiManagedSearchRuntimeSchema
849
+ });
850
+ var primeUiManagedSearchRuntimeDeleteResponseSchema = z3.object({
851
+ success: z3.literal(true)
852
+ });
657
853
  var primeUiExportsResponseSchema = z3.object({
658
854
  exports: z3.array(
659
855
  z3.object({
@@ -664,17 +860,18 @@ var primeUiExportsResponseSchema = z3.object({
664
860
  )
665
861
  });
666
862
  var primeUiCreateExportResponseSchema = z3.object({
667
- export: z3.object({
668
- id: z3.string(),
669
- status: primeUiExportStatusSchema,
670
- createdAt: z3.string().datetime({ offset: true }),
671
- expiresAt: z3.string().datetime({ offset: true }).nullable(),
672
- summary: primeUiExportSummarySchema,
673
- exportables: z3.array(primeUiExportedExportableSchema)
674
- }),
863
+ export: primeUiPostExportPayloadExportSchema,
675
864
  pages: z3.array(primeUiExportPageSchema)
676
865
  });
677
866
  var primeUiExportManifestSchema = primeUiCreateExportResponseSchema;
867
+ var primeUiComponentExportResponseSchema = z3.object({
868
+ exportId: z3.string(),
869
+ export: primeUiPostExportPayloadExportSchema,
870
+ component: primeUiComponentExportComponentSchema,
871
+ page: primeUiComponentExportPageSchema,
872
+ pages: z3.array(primeUiComponentExportPageSchema)
873
+ });
874
+ var primeUiComponentExportManifestSchema = primeUiComponentExportResponseSchema;
678
875
  function parsePrimeUiExportManifest(value) {
679
876
  if (!value || typeof value !== "object") {
680
877
  throw new Error("Export manifest is invalid.");
@@ -694,6 +891,22 @@ function parsePrimeUiExportManifest(value) {
694
891
  }
695
892
  return parsed.data;
696
893
  }
894
+ function parsePrimeUiComponentExportManifest(value) {
895
+ if (!value || typeof value !== "object") {
896
+ throw new Error("Component export manifest is invalid.");
897
+ }
898
+ const maybe = value;
899
+ if (!maybe.component || typeof maybe.component !== "object") {
900
+ throw new Error("Component export manifest component payload is invalid.");
901
+ }
902
+ const parsed = primeUiComponentExportManifestSchema.safeParse(value);
903
+ if (!parsed.success) {
904
+ throw new Error(
905
+ `Component export manifest is invalid: ${parsed.error.issues.map((issue) => `${issue.path.join(".") || "<root>"} ${issue.message}`).join("; ")}`
906
+ );
907
+ }
908
+ return parsed.data;
909
+ }
697
910
 
698
911
  // src/lib/fs.ts
699
912
  import { mkdir, rm, writeFile } from "fs/promises";
@@ -882,6 +1095,49 @@ var ApiProjectDataProvider = class {
882
1095
  this.buildJsonRequestInit(input)
883
1096
  );
884
1097
  }
1098
+ async getSearchOverview() {
1099
+ return this.requestJson(
1100
+ "project/search",
1101
+ primeUiManagedSearchOverviewResponseSchema
1102
+ );
1103
+ }
1104
+ async createSearchEnvironment(params) {
1105
+ return this.requestJson(
1106
+ "project/search/runtimes",
1107
+ primeUiManagedSearchRuntimeMutationResponseSchema,
1108
+ this.buildJsonRequestInit(params)
1109
+ );
1110
+ }
1111
+ async updateSearchEnvironment(params) {
1112
+ return this.requestJson(
1113
+ `project/search/runtimes/${encodeURIComponent(params.runtimeSlug)}`,
1114
+ primeUiManagedSearchRuntimeMutationResponseSchema,
1115
+ this.buildJsonRequestInit(
1116
+ {
1117
+ projectId: params.projectId,
1118
+ ...params.name === void 0 ? {} : { name: params.name },
1119
+ ...params.status === void 0 ? {} : { status: params.status }
1120
+ },
1121
+ {
1122
+ method: "PATCH"
1123
+ }
1124
+ )
1125
+ );
1126
+ }
1127
+ async deleteSearchEnvironment(params) {
1128
+ return this.requestJson(
1129
+ `project/search/runtimes/${encodeURIComponent(params.runtimeSlug)}`,
1130
+ primeUiManagedSearchRuntimeDeleteResponseSchema,
1131
+ this.buildJsonRequestInit(
1132
+ {
1133
+ projectId: params.projectId
1134
+ },
1135
+ {
1136
+ method: "DELETE"
1137
+ }
1138
+ )
1139
+ );
1140
+ }
885
1141
  async getProjectPageBySlug(slug) {
886
1142
  const encodedSlug = encodeURIComponent(slug);
887
1143
  return this.requestJson(
@@ -905,9 +1161,19 @@ var ApiProjectDataProvider = class {
905
1161
  }
906
1162
  );
907
1163
  }
1164
+ async createComponentExport(componentId) {
1165
+ return this.requestJson(
1166
+ `component-registry/components/${encodeURIComponent(componentId)}/exports`,
1167
+ primeUiComponentExportResponseSchema,
1168
+ {
1169
+ method: "POST"
1170
+ }
1171
+ );
1172
+ }
908
1173
  /**
909
1174
  * Consumer-side runtime contract for GET /api/v1/project/exports/:exportId/download.
910
- * Producer source of truth: apps/studio/src/app/api/v1/project/exports/[exportId]/download/route.ts
1175
+ * Primary Studio runtime entrypoint: apps/studio/src/tanstack/routes/api.v1.project.exports.$exportId.download.ts
1176
+ * Legacy migration reference: apps/studio/src/app/api/v1/project/exports/[exportId]/download/route.ts
911
1177
  * Keep content-type and archive format checks synchronized with the producer response.
912
1178
  */
913
1179
  async downloadExportArchive(exportId, destinationPath) {
@@ -951,10 +1217,12 @@ var ApiProjectDataProvider = class {
951
1217
  buildUrl(endpoint) {
952
1218
  return buildPrimeUiApiUrl(this.apiRoot, endpoint);
953
1219
  }
954
- buildJsonRequestInit(payload) {
1220
+ buildJsonRequestInit(payload, overrides = {}) {
955
1221
  return {
956
- method: "POST",
1222
+ ...overrides,
1223
+ method: overrides.method ?? "POST",
957
1224
  headers: {
1225
+ ...overrides.headers ?? {},
958
1226
  "Content-Type": "application/json"
959
1227
  },
960
1228
  body: JSON.stringify(payload)
@@ -1725,11 +1993,11 @@ async function runHealthCheck(options) {
1725
1993
  }
1726
1994
 
1727
1995
  // src/services/project-sync-service.ts
1728
- import path13 from "path";
1729
- import { readFile as readFile7 } from "fs/promises";
1996
+ import path14 from "path";
1997
+ import { readFile as readFile8 } from "fs/promises";
1730
1998
 
1731
1999
  // src/services/page-copy-service.ts
1732
- import { readFile as readFile4, stat as stat6, writeFile as writeFile2 } from "fs/promises";
2000
+ import { readFile as readFile4, stat as stat6, writeFile as writeFile3 } from "fs/promises";
1733
2001
  import path10 from "path";
1734
2002
 
1735
2003
  // src/lib/import-graph.ts
@@ -2011,7 +2279,7 @@ function buildUnifiedDiff(input) {
2011
2279
  }
2012
2280
 
2013
2281
  // src/services/copy-service-shared.ts
2014
- import { readFile as readFile3, readdir as readdir2, stat as stat5 } from "fs/promises";
2282
+ import { readFile as readFile3, readdir as readdir2, stat as stat5, writeFile as writeFile2 } from "fs/promises";
2015
2283
  import path9 from "path";
2016
2284
  var DEPENDENCY_SECTIONS = [
2017
2285
  "dependencies",
@@ -2198,6 +2466,64 @@ async function resolveDependencyRequirements(input) {
2198
2466
  )
2199
2467
  };
2200
2468
  }
2469
+ async function applyDependencyRequirementsToPackageJson(input) {
2470
+ const exportPackageJson = await readJsonFile(
2471
+ input.exportPackageJsonPath
2472
+ );
2473
+ const userPackageJson = await readJsonFile(
2474
+ input.userPackageJsonPath
2475
+ );
2476
+ const addedDependencies = [];
2477
+ const dependenciesVersionConflicts = [];
2478
+ for (const packageName of new Set(input.requiredPackageNames)) {
2479
+ const exportDependency = getDependencyVersion(
2480
+ exportPackageJson,
2481
+ packageName
2482
+ );
2483
+ if (!exportDependency) {
2484
+ continue;
2485
+ }
2486
+ const userDependency = getDependencyVersion(userPackageJson, packageName);
2487
+ if (!userDependency) {
2488
+ const sectionData = getOrCreateDependencySection(
2489
+ userPackageJson,
2490
+ exportDependency.section
2491
+ );
2492
+ sectionData[packageName] = exportDependency.version;
2493
+ addedDependencies.push({
2494
+ packageName,
2495
+ version: exportDependency.version,
2496
+ section: exportDependency.section
2497
+ });
2498
+ continue;
2499
+ }
2500
+ if (userDependency.version !== exportDependency.version) {
2501
+ dependenciesVersionConflicts.push({
2502
+ packageName,
2503
+ section: exportDependency.section,
2504
+ exportVersion: exportDependency.version,
2505
+ userVersion: userDependency.version
2506
+ });
2507
+ }
2508
+ }
2509
+ if (addedDependencies.length > 0) {
2510
+ sortDependencySections(userPackageJson);
2511
+ await writeFile2(
2512
+ input.userPackageJsonPath,
2513
+ `${JSON.stringify(userPackageJson, null, 2)}
2514
+ `,
2515
+ "utf-8"
2516
+ );
2517
+ }
2518
+ return {
2519
+ addedDependencies: addedDependencies.sort(
2520
+ (a, b) => a.packageName.localeCompare(b.packageName)
2521
+ ),
2522
+ dependenciesVersionConflicts: dependenciesVersionConflicts.sort(
2523
+ (a, b) => a.packageName.localeCompare(b.packageName)
2524
+ )
2525
+ };
2526
+ }
2201
2527
 
2202
2528
  // src/services/runtime-guidance.ts
2203
2529
  var EXPORT_MANIFEST_DESCRIPTION = "Local sidecar export manifest. This is the authoritative file-level contract for the selected transfer item. Files listed per page or exportable are functionality-critical dependencies for that item.";
@@ -2367,7 +2693,7 @@ async function copyPageFromExport(input) {
2367
2693
  const targetRelative = toProjectRelative(input.projectRoot, targetFilePath);
2368
2694
  if (!targetBuffer) {
2369
2695
  await ensureDir(path10.dirname(targetFilePath));
2370
- await writeFile2(targetFilePath, plannedSourceBuffer);
2696
+ await writeFile3(targetFilePath, plannedSourceBuffer);
2371
2697
  newFiles.push(targetRelative);
2372
2698
  continue;
2373
2699
  }
@@ -2436,7 +2762,7 @@ async function copyPageFromExport(input) {
2436
2762
  }
2437
2763
  if (addedDependencies.length > 0) {
2438
2764
  sortDependencySections(userPackageJson);
2439
- await writeFile2(
2765
+ await writeFile3(
2440
2766
  userPackageJsonPath,
2441
2767
  `${JSON.stringify(userPackageJson, null, 2)}
2442
2768
  `,
@@ -2472,7 +2798,7 @@ async function copyPageFromExport(input) {
2472
2798
  sourceComponentsPath: page.componentsPath,
2473
2799
  conflicts: sortedConflictReportEntries
2474
2800
  };
2475
- await writeFile2(reportPath, `${JSON.stringify(report, null, 2)}
2801
+ await writeFile3(reportPath, `${JSON.stringify(report, null, 2)}
2476
2802
  `, "utf-8");
2477
2803
  const hasFileConflicts = conflictFiles.length > 0;
2478
2804
  const hasDependencyVersionConflicts = sortedDependenciesVersionConflicts.length > 0;
@@ -2622,7 +2948,7 @@ function buildInspectPageReport(input) {
2622
2948
  }
2623
2949
 
2624
2950
  // src/services/exportable-copy-service.ts
2625
- import { readFile as readFile5, writeFile as writeFile3 } from "fs/promises";
2951
+ import { readFile as readFile5, writeFile as writeFile4 } from "fs/promises";
2626
2952
  import path11 from "path";
2627
2953
  var PACKAGE_JSON_RELATIVE_PATH = "package.json";
2628
2954
  var SUPPLEMENTARY_DEPENDENCY_PACKAGES = {
@@ -2768,7 +3094,7 @@ async function copyExportableFromExport(input) {
2768
3094
  const targetRelative = toProjectRelative(input.projectRoot, targetFilePath);
2769
3095
  if (!targetBuffer) {
2770
3096
  await ensureDir(path11.dirname(targetFilePath));
2771
- await writeFile3(targetFilePath, sourceBuffer);
3097
+ await writeFile4(targetFilePath, sourceBuffer);
2772
3098
  newFiles.push(targetRelative);
2773
3099
  continue;
2774
3100
  }
@@ -2834,7 +3160,7 @@ async function copyExportableFromExport(input) {
2834
3160
  exportableKey: normalizedExportableKey,
2835
3161
  conflicts: sortedConflictReportEntries
2836
3162
  };
2837
- await writeFile3(reportPath, `${JSON.stringify(report, null, 2)}
3163
+ await writeFile4(reportPath, `${JSON.stringify(report, null, 2)}
2838
3164
  `, "utf-8");
2839
3165
  const hasFileConflicts = conflictFiles.length > 0;
2840
3166
  const hasDependencyVersionConflicts = dependenciesVersionConflicts.length > 0;
@@ -2895,7 +3221,7 @@ async function copyExportableFromExport(input) {
2895
3221
  }
2896
3222
 
2897
3223
  // src/services/component-copy-service.ts
2898
- import { readFile as readFile6, stat as stat7, writeFile as writeFile4 } from "fs/promises";
3224
+ import { readFile as readFile6, stat as stat7, writeFile as writeFile5 } from "fs/promises";
2899
3225
  import path12 from "path";
2900
3226
  function normalizeSlug2(slug) {
2901
3227
  const trimmed = slug.trim();
@@ -3051,7 +3377,7 @@ async function applyDependencyRequirements(input) {
3051
3377
  }
3052
3378
  if (addedDependencies.length > 0) {
3053
3379
  sortDependencySections(userPackageJson);
3054
- await writeFile4(
3380
+ await writeFile5(
3055
3381
  userPackageJsonPath,
3056
3382
  `${JSON.stringify(userPackageJson, null, 2)}
3057
3383
  `,
@@ -3215,7 +3541,7 @@ async function copyComponentFromExport(input) {
3215
3541
  }
3216
3542
  if (!targetBuffer) {
3217
3543
  await ensureDir(path12.dirname(targetPrimaryPath));
3218
- await writeFile4(targetPrimaryPath, sourceBuffer);
3544
+ await writeFile5(targetPrimaryPath, sourceBuffer);
3219
3545
  newFiles.push(primaryComponentFile);
3220
3546
  } else if (sourceBuffer.equals(targetBuffer)) {
3221
3547
  identicalFiles.push(primaryComponentFile);
@@ -3319,7 +3645,7 @@ async function copyComponentFromExport(input) {
3319
3645
  potentialConflicts: sortedPotentialConflictEntries,
3320
3646
  selectedBlock
3321
3647
  };
3322
- await writeFile4(reportPath, `${JSON.stringify(report, null, 2)}
3648
+ await writeFile5(reportPath, `${JSON.stringify(report, null, 2)}
3323
3649
  `, "utf-8");
3324
3650
  const needsReview = !primaryComponentFile || conflictFiles.length > 0 || dependenciesVersionConflicts.length > 0 || missingManifestFiles.size > 0;
3325
3651
  const missingManifestFileList = [...missingManifestFiles].sort(
@@ -3408,70 +3734,489 @@ async function copyComponentFromExport(input) {
3408
3734
  };
3409
3735
  }
3410
3736
 
3411
- // src/services/project-sync-service.ts
3412
- function buildManifestPath(exportsRoot, exportId) {
3413
- return path13.join(exportsRoot, `${exportId}.manifest.json`);
3737
+ // src/services/registry-component-copy-service.ts
3738
+ import { readFile as readFile7, writeFile as writeFile6 } from "fs/promises";
3739
+ import path13 from "path";
3740
+ var PACKAGE_JSON_RELATIVE_PATH2 = "package.json";
3741
+ var VIRTUAL_ROUTE_SEGMENT = "__primeui-component-export";
3742
+ function normalizeComponentId(componentId) {
3743
+ const trimmed = componentId.trim();
3744
+ if (!trimmed) {
3745
+ throw new Error("componentId must not be empty.");
3746
+ }
3747
+ return trimmed;
3414
3748
  }
3415
- function normalizeSlug3(slug) {
3416
- const trimmed = slug.trim();
3417
- if (!trimmed || trimmed === "/") {
3418
- return "/";
3749
+ function normalizeManifestFilePath(filePath) {
3750
+ const trimmed = filePath.trim();
3751
+ if (!trimmed) {
3752
+ throw new Error("Component export manifest contains an empty file path.");
3419
3753
  }
3420
- const withLeadingSlash = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
3421
- return withLeadingSlash.replace(/\/+$/, "") || "/";
3754
+ return toPosixPath(trimmed).replace(/^\.\/+/, "");
3422
3755
  }
3423
- var ProjectSyncService = class {
3424
- provider;
3425
- projectRoot;
3426
- targetProjectRoot;
3427
- primeUiRoot;
3428
- tempRoot;
3429
- exportsRoot;
3430
- pageDetailsBySlug;
3431
- constructor(options) {
3432
- this.projectRoot = options.projectRoot;
3433
- this.targetProjectRoot = options.targetProjectRoot;
3434
- this.provider = options.provider;
3435
- this.pageDetailsBySlug = options.pageDetailsBySlug ?? /* @__PURE__ */ new Map();
3436
- this.primeUiRoot = path13.join(this.projectRoot, ".primeui");
3437
- this.tempRoot = path13.join(this.primeUiRoot, "temp");
3438
- this.exportsRoot = path13.join(this.tempRoot, "exports");
3756
+ function isVirtualRouteFile(relativePath) {
3757
+ return relativePath.split("/").includes(VIRTUAL_ROUTE_SEGMENT);
3758
+ }
3759
+ function splitManifestFiles(files) {
3760
+ const manifestFiles = files.map(normalizeManifestFilePath);
3761
+ const copyableFiles = [];
3762
+ const skippedFiles = [];
3763
+ for (const relativePath of manifestFiles) {
3764
+ if (relativePath === PACKAGE_JSON_RELATIVE_PATH2) {
3765
+ skippedFiles.push({
3766
+ targetPath: relativePath,
3767
+ reason: "package_json_managed_as_dependencies"
3768
+ });
3769
+ continue;
3770
+ }
3771
+ if (isVirtualRouteFile(relativePath)) {
3772
+ skippedFiles.push({
3773
+ targetPath: relativePath,
3774
+ reason: "virtual_component_route"
3775
+ });
3776
+ continue;
3777
+ }
3778
+ copyableFiles.push(relativePath);
3439
3779
  }
3440
- async getProjectInfo(_context) {
3441
- await this.ensureTempLayout();
3442
- return this.provider.getProjectInfo();
3780
+ return {
3781
+ manifestFiles,
3782
+ copyableFiles,
3783
+ skippedFiles
3784
+ };
3785
+ }
3786
+ async function createConflictReportEntry2(input) {
3787
+ const sourceBuffer = await readFile7(input.sourceFilePath);
3788
+ let targetBuffer = null;
3789
+ try {
3790
+ targetBuffer = await readFile7(input.targetFilePath);
3791
+ } catch {
3792
+ targetBuffer = null;
3443
3793
  }
3444
- async getProjectDescription(_context) {
3445
- return this.provider.getProjectDescription();
3794
+ if (!targetBuffer || sourceBuffer.equals(targetBuffer)) {
3795
+ return null;
3446
3796
  }
3447
- async upsertProjectDescription(projectDescription, _context) {
3448
- return this.provider.upsertProjectDescription(projectDescription);
3797
+ const sourceRelative = toProjectRelative(
3798
+ input.exportPath,
3799
+ input.sourceFilePath
3800
+ );
3801
+ const targetRelative = toProjectRelative(
3802
+ input.projectRoot,
3803
+ input.targetFilePath
3804
+ );
3805
+ const isBinary = isBinaryBuffer(sourceBuffer) || isBinaryBuffer(targetBuffer);
3806
+ return {
3807
+ sourcePath: sourceRelative,
3808
+ targetPath: targetRelative,
3809
+ diff: isBinary ? "Binary files differ." : buildUnifiedDiff({
3810
+ oldText: targetBuffer.toString("utf-8"),
3811
+ newText: sourceBuffer.toString("utf-8"),
3812
+ oldLabel: `user/${targetRelative}`,
3813
+ newLabel: `export/${sourceRelative}`
3814
+ }),
3815
+ isBinary
3816
+ };
3817
+ }
3818
+ function buildMessage(input) {
3819
+ const parts = [
3820
+ input.status === "completed" ? `Registry component "${input.componentId}" copied from the component manifest.` : `Registry component "${input.componentId}" needs review before transfer is complete.`,
3821
+ `Report: ${input.reportPath}.`
3822
+ ];
3823
+ if (input.newFiles.length > 0) {
3824
+ parts.push(`${input.newFiles.length} new file(s) copied.`);
3449
3825
  }
3450
- async listProjectPages(_context) {
3451
- return this.provider.listProjectPages();
3826
+ if (input.identicalFiles.length > 0) {
3827
+ parts.push(`${input.identicalFiles.length} file(s) already identical.`);
3452
3828
  }
3453
- async getProjectPage(pageId, _context) {
3454
- return this.provider.getProjectPage(pageId);
3829
+ if (input.conflictFiles.length > 0) {
3830
+ parts.push(
3831
+ `${input.conflictFiles.length} conflicting file(s) were not overwritten.`
3832
+ );
3455
3833
  }
3456
- async createProjectPage(input, _context) {
3457
- return this.provider.createProjectPage(input);
3834
+ if (input.skippedFiles.length > 0) {
3835
+ parts.push(
3836
+ `${input.skippedFiles.length} manifest file(s) skipped, including virtual route or package metadata entries.`
3837
+ );
3458
3838
  }
3459
- async listProjectPageVariants(pageId, _context) {
3460
- return this.provider.listProjectPageVariants(pageId);
3839
+ if (input.missingManifestFiles.length > 0) {
3840
+ parts.push(
3841
+ `Missing manifest file(s): ${input.missingManifestFiles.join(", ")}.`
3842
+ );
3461
3843
  }
3462
- async getProjectPageVariant(pageId, variantId, _context) {
3463
- return this.provider.getProjectPageVariant(pageId, variantId);
3844
+ if (input.addedDependenciesCount > 0) {
3845
+ parts.push(
3846
+ "Missing dependencies were added to package.json but are NOT installed."
3847
+ );
3464
3848
  }
3465
- async createProjectPageVariant(pageId, input, _context) {
3466
- return this.provider.createProjectPageVariant(pageId, input);
3849
+ if (input.dependencyConflictCount > 0) {
3850
+ parts.push(
3851
+ "Dependency version conflicts require manual resolution before completion."
3852
+ );
3467
3853
  }
3468
- async setProjectPageActiveVariant(pageId, variantId, _context) {
3469
- return this.provider.setProjectPageActiveVariant(pageId, variantId);
3854
+ parts.push(
3855
+ "The virtual component export page was skipped; manually insert the copied component into a real target page."
3856
+ );
3857
+ return parts.join(" ");
3858
+ }
3859
+ async function copyRegistryComponentFromExport(input) {
3860
+ const normalizedComponentId = normalizeComponentId(input.componentId);
3861
+ const { exportId, exportPath } = await resolveSingleExportDirectory(
3862
+ input.exportsRoot
3863
+ );
3864
+ const manifestPath = path13.join(
3865
+ input.exportsRoot,
3866
+ `${exportId}.manifest.json`
3867
+ );
3868
+ if (!await fileExists2(manifestPath)) {
3869
+ throw new Error(
3870
+ `Component export manifest is missing at ${manifestPath}. Run create_component_export and download_component_export to regenerate it.`
3871
+ );
3470
3872
  }
3471
- async submitIssueReport(input, _context) {
3472
- return this.provider.submitIssueReport(input);
3873
+ const manifest = parsePrimeUiComponentExportManifest(
3874
+ await readJsonFile(manifestPath)
3875
+ );
3876
+ if (manifest.export.id !== exportId || manifest.exportId !== exportId) {
3877
+ throw new Error(
3878
+ `Component export manifest mismatch for id "${exportId}". Run create_component_export and download_component_export again.`
3879
+ );
3473
3880
  }
3474
- async listExports(_context) {
3881
+ if (manifest.component.componentId !== normalizedComponentId) {
3882
+ throw new Error(
3883
+ `Component export manifest mismatch: expected componentId "${normalizedComponentId}", got "${manifest.component.componentId}".`
3884
+ );
3885
+ }
3886
+ const { manifestFiles, copyableFiles, skippedFiles } = splitManifestFiles(
3887
+ manifest.page.manifest.files
3888
+ );
3889
+ const candidateFiles = await resolveManifestCandidateFiles({
3890
+ exportPath,
3891
+ manifestOwnerLabel: `registry component "${normalizedComponentId}"`,
3892
+ files: copyableFiles,
3893
+ requireExisting: false
3894
+ });
3895
+ const newFiles = [];
3896
+ const identicalFiles = [];
3897
+ const conflictFiles = [];
3898
+ const conflictReportEntries = [];
3899
+ const missingManifestFiles = /* @__PURE__ */ new Set();
3900
+ const existingCandidateFiles = [];
3901
+ for (const sourceFilePath of candidateFiles) {
3902
+ const relativeToExport = toProjectRelative(exportPath, sourceFilePath);
3903
+ const sourceExists = await fileExists2(sourceFilePath);
3904
+ if (!sourceExists) {
3905
+ missingManifestFiles.add(relativeToExport);
3906
+ continue;
3907
+ }
3908
+ existingCandidateFiles.push(sourceFilePath);
3909
+ const targetFilePath = path13.join(input.projectRoot, relativeToExport);
3910
+ ensureSafeTargetPath(input.projectRoot, targetFilePath);
3911
+ const sourceBuffer = await readFile7(sourceFilePath);
3912
+ let targetBuffer = null;
3913
+ try {
3914
+ targetBuffer = await readFile7(targetFilePath);
3915
+ } catch {
3916
+ targetBuffer = null;
3917
+ }
3918
+ if (!targetBuffer) {
3919
+ await ensureDir(path13.dirname(targetFilePath));
3920
+ await writeFile6(targetFilePath, sourceBuffer);
3921
+ newFiles.push(relativeToExport);
3922
+ continue;
3923
+ }
3924
+ if (sourceBuffer.equals(targetBuffer)) {
3925
+ identicalFiles.push(relativeToExport);
3926
+ continue;
3927
+ }
3928
+ const entry = await createConflictReportEntry2({
3929
+ sourceFilePath,
3930
+ targetFilePath,
3931
+ exportPath,
3932
+ projectRoot: input.projectRoot
3933
+ });
3934
+ if (entry) {
3935
+ conflictReportEntries.push(entry);
3936
+ conflictFiles.push({
3937
+ targetPath: entry.targetPath,
3938
+ isBinary: entry.isBinary
3939
+ });
3940
+ }
3941
+ }
3942
+ const dependencyGraph = existingCandidateFiles.length > 0 ? await buildImportGraph({
3943
+ projectRoot: exportPath,
3944
+ entryFiles: existingCandidateFiles,
3945
+ followInternalImports: false
3946
+ }) : { externalPackages: [] };
3947
+ const { addedDependencies, dependenciesVersionConflicts } = await applyDependencyRequirementsToPackageJson({
3948
+ exportPackageJsonPath: path13.join(exportPath, PACKAGE_JSON_RELATIVE_PATH2),
3949
+ userPackageJsonPath: path13.join(
3950
+ input.projectRoot,
3951
+ PACKAGE_JSON_RELATIVE_PATH2
3952
+ ),
3953
+ requiredPackageNames: dependencyGraph.externalPackages
3954
+ });
3955
+ const missingManifestFileList = [...missingManifestFiles].sort(
3956
+ (a, b) => a.localeCompare(b)
3957
+ );
3958
+ const sortedConflictEntries = conflictReportEntries.sort(
3959
+ (a, b) => a.targetPath.localeCompare(b.targetPath)
3960
+ );
3961
+ const sortedConflictFiles = conflictFiles.sort(
3962
+ (a, b) => a.targetPath.localeCompare(b.targetPath)
3963
+ );
3964
+ const sortedNewFiles = newFiles.sort((a, b) => a.localeCompare(b));
3965
+ const sortedIdenticalFiles = identicalFiles.sort(
3966
+ (a, b) => a.localeCompare(b)
3967
+ );
3968
+ const copyId = createCopyId();
3969
+ const reportPath = path13.join(
3970
+ input.exportsRoot,
3971
+ `${exportId}.copy-registry-component-report-${copyId}.json`
3972
+ );
3973
+ const report = {
3974
+ reportPath,
3975
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
3976
+ exportId,
3977
+ componentId: normalizedComponentId,
3978
+ manifestFiles,
3979
+ copyableFiles,
3980
+ skippedFiles,
3981
+ conflicts: sortedConflictEntries,
3982
+ missingManifestFiles: missingManifestFileList
3983
+ };
3984
+ await writeFile6(reportPath, `${JSON.stringify(report, null, 2)}
3985
+ `, "utf-8");
3986
+ const needsReview = copyableFiles.length === 0 || sortedConflictFiles.length > 0 || dependenciesVersionConflicts.length > 0 || missingManifestFileList.length > 0;
3987
+ const status = needsReview ? "needs_review" : "completed";
3988
+ const guidanceArtifacts = [
3989
+ buildExportManifestArtifact(manifestPath),
3990
+ buildReferenceExportArtifact(exportPath)
3991
+ ];
3992
+ if (needsReview) {
3993
+ guidanceArtifacts.push(buildConflictReportArtifact(reportPath));
3994
+ }
3995
+ return {
3996
+ status,
3997
+ message: buildMessage({
3998
+ componentId: normalizedComponentId,
3999
+ status,
4000
+ reportPath,
4001
+ newFiles: sortedNewFiles,
4002
+ identicalFiles: sortedIdenticalFiles,
4003
+ conflictFiles: sortedConflictFiles,
4004
+ skippedFiles,
4005
+ addedDependenciesCount: addedDependencies.length,
4006
+ dependencyConflictCount: dependenciesVersionConflicts.length,
4007
+ missingManifestFiles: missingManifestFileList
4008
+ }),
4009
+ reportPath,
4010
+ exportId,
4011
+ exportPath,
4012
+ manifestPath,
4013
+ component: manifest.component,
4014
+ manifestFiles,
4015
+ copyableFiles,
4016
+ newFiles: sortedNewFiles,
4017
+ identicalFiles: sortedIdenticalFiles,
4018
+ conflictFiles: sortedConflictFiles,
4019
+ skippedFiles,
4020
+ addedDependencies,
4021
+ dependenciesVersionConflicts,
4022
+ missingManifestFiles: missingManifestFileList,
4023
+ summary: {
4024
+ totalManifestFiles: manifestFiles.length,
4025
+ totalCopyableFiles: copyableFiles.length,
4026
+ copiedFiles: sortedNewFiles.length,
4027
+ identicalFiles: sortedIdenticalFiles.length,
4028
+ conflictFiles: sortedConflictFiles.length,
4029
+ skippedFiles: skippedFiles.length,
4030
+ addedDependencies: addedDependencies.length,
4031
+ dependenciesVersionConflicts: dependenciesVersionConflicts.length,
4032
+ missingManifestFiles: missingManifestFileList.length
4033
+ },
4034
+ guidance: {
4035
+ artifacts: guidanceArtifacts,
4036
+ requiredActions: "Do not install the skipped virtual component export page as a route. Manually import the copied component/support files into a real target page, install newly added dependencies, and resolve any reported conflicts or dependency version mismatches before treating the registry component transfer as complete."
4037
+ }
4038
+ };
4039
+ }
4040
+
4041
+ // src/services/project-sync-service.ts
4042
+ function buildManifestPath(exportsRoot, exportId) {
4043
+ return path14.join(exportsRoot, `${exportId}.manifest.json`);
4044
+ }
4045
+ function normalizeSlug3(slug) {
4046
+ const trimmed = slug.trim();
4047
+ if (!trimmed || trimmed === "/") {
4048
+ return "/";
4049
+ }
4050
+ const withLeadingSlash = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
4051
+ return withLeadingSlash.replace(/\/+$/, "") || "/";
4052
+ }
4053
+ function normalizeEnvironmentSlug(slug) {
4054
+ return slug.trim();
4055
+ }
4056
+ var ProjectSyncService = class {
4057
+ provider;
4058
+ projectRoot;
4059
+ targetProjectRoot;
4060
+ primeUiRoot;
4061
+ tempRoot;
4062
+ exportsRoot;
4063
+ pageDetailsBySlug;
4064
+ constructor(options) {
4065
+ this.projectRoot = options.projectRoot;
4066
+ this.targetProjectRoot = options.targetProjectRoot;
4067
+ this.provider = options.provider;
4068
+ this.pageDetailsBySlug = options.pageDetailsBySlug ?? /* @__PURE__ */ new Map();
4069
+ this.primeUiRoot = path14.join(this.projectRoot, ".primeui");
4070
+ this.tempRoot = path14.join(this.primeUiRoot, "temp");
4071
+ this.exportsRoot = path14.join(this.tempRoot, "exports");
4072
+ }
4073
+ async getProjectInfo(_context) {
4074
+ await this.ensureTempLayout();
4075
+ return this.provider.getProjectInfo();
4076
+ }
4077
+ async getProjectDescription(_context) {
4078
+ return this.provider.getProjectDescription();
4079
+ }
4080
+ async upsertProjectDescription(projectDescription, _context) {
4081
+ return this.provider.upsertProjectDescription(projectDescription);
4082
+ }
4083
+ async listProjectPages(_context) {
4084
+ return this.provider.listProjectPages();
4085
+ }
4086
+ async getProjectPage(pageId, _context) {
4087
+ return this.provider.getProjectPage(pageId);
4088
+ }
4089
+ async createProjectPage(input, _context) {
4090
+ return this.provider.createProjectPage(input);
4091
+ }
4092
+ async listProjectPageVariants(pageId, _context) {
4093
+ return this.provider.listProjectPageVariants(pageId);
4094
+ }
4095
+ async getProjectPageVariant(pageId, variantId, _context) {
4096
+ return this.provider.getProjectPageVariant(pageId, variantId);
4097
+ }
4098
+ async createProjectPageVariant(pageId, input, _context) {
4099
+ return this.provider.createProjectPageVariant(pageId, input);
4100
+ }
4101
+ async setProjectPageActiveVariant(pageId, variantId, _context) {
4102
+ return this.provider.setProjectPageActiveVariant(pageId, variantId);
4103
+ }
4104
+ async submitIssueReport(input, _context) {
4105
+ return this.provider.submitIssueReport(input);
4106
+ }
4107
+ async getSearchOverview(_context) {
4108
+ return this.provider.getSearchOverview();
4109
+ }
4110
+ async getSearchEnvironment(environmentSlug, _context) {
4111
+ const normalizedSlug = normalizeEnvironmentSlug(environmentSlug);
4112
+ if (!normalizedSlug) {
4113
+ throw new Error("Search environment slug is required.");
4114
+ }
4115
+ const overview = await this.provider.getSearchOverview();
4116
+ const runtime = overview.runtimes.find(
4117
+ (candidate) => candidate.slug === normalizedSlug
4118
+ );
4119
+ if (!runtime) {
4120
+ throw new Error(
4121
+ `Search environment "${normalizedSlug}" was not found in the current project overview.`
4122
+ );
4123
+ }
4124
+ const relatedIndexes = this.getRelatedIndexesForRuntime(overview, runtime);
4125
+ const relatedIndexIds = new Set(relatedIndexes.map((index) => index.id));
4126
+ const primaryIndex = relatedIndexes[0] ?? null;
4127
+ return {
4128
+ success: true,
4129
+ environmentSlug: normalizedSlug,
4130
+ environment: runtime,
4131
+ primaryIndex,
4132
+ relatedIndexes,
4133
+ recentJobs: overview.recentJobs.filter(
4134
+ (job) => relatedIndexIds.has(job.projectSearchIndexId)
4135
+ ),
4136
+ recentSyncRuns: overview.recentSyncRuns.filter(
4137
+ (syncRun) => relatedIndexIds.has(syncRun.projectSearchIndexId)
4138
+ ),
4139
+ search: overview.search,
4140
+ runtimeModel: overview.runtimeModel,
4141
+ sources: overview.sources,
4142
+ lastError: overview.lastError
4143
+ };
4144
+ }
4145
+ async createSearchEnvironment(input, _context) {
4146
+ const projectInfo = await this.provider.getProjectInfo();
4147
+ const result = await this.provider.createSearchEnvironment({
4148
+ name: input.name,
4149
+ projectId: projectInfo.projectId,
4150
+ slug: input.slug
4151
+ });
4152
+ return {
4153
+ success: result.success,
4154
+ environment: result.runtime
4155
+ };
4156
+ }
4157
+ async updateSearchEnvironment(input, _context) {
4158
+ const projectInfo = await this.provider.getProjectInfo();
4159
+ const result = await this.provider.updateSearchEnvironment({
4160
+ projectId: projectInfo.projectId,
4161
+ runtimeSlug: input.environmentSlug,
4162
+ ...input.name === void 0 ? {} : { name: input.name },
4163
+ ...input.status === void 0 ? {} : { status: input.status }
4164
+ });
4165
+ return {
4166
+ success: result.success,
4167
+ environment: result.runtime
4168
+ };
4169
+ }
4170
+ async deleteSearchEnvironment(environmentSlug, _context) {
4171
+ const projectInfo = await this.provider.getProjectInfo();
4172
+ return this.provider.deleteSearchEnvironment({
4173
+ projectId: projectInfo.projectId,
4174
+ runtimeSlug: environmentSlug
4175
+ });
4176
+ }
4177
+ async syncSearchEnvironment(environmentSlug, _context) {
4178
+ const normalizedSlug = normalizeEnvironmentSlug(environmentSlug);
4179
+ if (!normalizedSlug) {
4180
+ throw new Error("Search environment slug is required.");
4181
+ }
4182
+ const packageJsonPath = path14.join(this.targetProjectRoot, "package.json");
4183
+ const guidanceNotes = [
4184
+ `Run the command from ${this.targetProjectRoot}.`,
4185
+ "This tool returns guidance mode because Phase 13 keeps sync truthful to the real exported-project flow instead of pretending MCP generated a fresh payload itself."
4186
+ ];
4187
+ try {
4188
+ const packageJson = JSON.parse(
4189
+ await readFile8(packageJsonPath, "utf-8")
4190
+ );
4191
+ if (packageJson.scripts?.["search:sync"]) {
4192
+ return {
4193
+ success: true,
4194
+ mode: "guidance",
4195
+ environmentSlug: normalizedSlug,
4196
+ command: `pnpm search:sync --env ${normalizedSlug}`,
4197
+ workingDirectory: this.targetProjectRoot,
4198
+ jobId: null,
4199
+ status: null,
4200
+ notes: guidanceNotes
4201
+ };
4202
+ }
4203
+ } catch {
4204
+ guidanceNotes.push(
4205
+ `Package script lookup at ${packageJsonPath} was unavailable, so MCP is falling back to the package CLI command.`
4206
+ );
4207
+ }
4208
+ return {
4209
+ success: true,
4210
+ mode: "guidance",
4211
+ environmentSlug: normalizedSlug,
4212
+ command: `npx @primeuicom/cli search sync --env ${normalizedSlug}`,
4213
+ workingDirectory: this.targetProjectRoot,
4214
+ jobId: null,
4215
+ status: null,
4216
+ notes: guidanceNotes
4217
+ };
4218
+ }
4219
+ async listExports(_context) {
3475
4220
  await this.ensureTempLayout();
3476
4221
  return this.provider.listExports();
3477
4222
  }
@@ -3489,6 +4234,20 @@ var ProjectSyncService = class {
3489
4234
  }
3490
4235
  };
3491
4236
  }
4237
+ async createComponentExport(componentId, _context) {
4238
+ await this.ensureTempLayout();
4239
+ const result = await this.provider.createComponentExport(componentId);
4240
+ const manifestPath = buildManifestPath(this.exportsRoot, result.export.id);
4241
+ await writeUtf8(manifestPath, `${JSON.stringify(result, null, 2)}
4242
+ `);
4243
+ return {
4244
+ ...result,
4245
+ guidance: {
4246
+ artifacts: [buildExportManifestArtifact(manifestPath)],
4247
+ requiredActions: `Call download_component_export with id "${result.export.id}" next. This is a component-track manifest; do not use page copy tools until a component registry copy tool is available.`
4248
+ }
4249
+ };
4250
+ }
3492
4251
  async downloadExportById(id, _context) {
3493
4252
  await this.ensureTempLayout();
3494
4253
  const exportsList = await this.provider.listExports();
@@ -3496,13 +4255,13 @@ var ProjectSyncService = class {
3496
4255
  if (!selected) {
3497
4256
  throw new Error(`Export not found: ${id}`);
3498
4257
  }
3499
- const targetZipPath = path13.join(this.exportsRoot, `${id}.zip`);
3500
- const targetProjectPath = path13.join(this.exportsRoot, id);
4258
+ const targetZipPath = path14.join(this.exportsRoot, `${id}.zip`);
4259
+ const targetProjectPath = path14.join(this.exportsRoot, id);
3501
4260
  const manifestPath = buildManifestPath(this.exportsRoot, id);
3502
4261
  let manifest;
3503
4262
  try {
3504
4263
  manifest = parsePrimeUiExportManifest(
3505
- JSON.parse(await readFile7(manifestPath, "utf-8"))
4264
+ JSON.parse(await readFile8(manifestPath, "utf-8"))
3506
4265
  );
3507
4266
  } catch (error) {
3508
4267
  const reason = error instanceof Error ? error.message : String(error);
@@ -3532,6 +4291,29 @@ var ProjectSyncService = class {
3532
4291
  }
3533
4292
  };
3534
4293
  }
4294
+ async downloadComponentExportById(id, _context) {
4295
+ await this.ensureTempLayout();
4296
+ const manifestPath = buildManifestPath(this.exportsRoot, id);
4297
+ const manifest = await this.readComponentExportManifest(id, manifestPath);
4298
+ const targetZipPath = path14.join(this.exportsRoot, `${id}.zip`);
4299
+ const targetProjectPath = path14.join(this.exportsRoot, id);
4300
+ await ensureDir(this.exportsRoot);
4301
+ await this.provider.downloadExportArchive(id, targetZipPath);
4302
+ await resetDir(targetProjectPath);
4303
+ await extractZip(targetZipPath, targetProjectPath);
4304
+ return {
4305
+ exportId: id,
4306
+ projectPath: targetProjectPath,
4307
+ manifestPath,
4308
+ guidance: {
4309
+ artifacts: [
4310
+ buildReferenceExportArtifact(targetProjectPath),
4311
+ buildExportManifestArtifact(manifestPath)
4312
+ ],
4313
+ requiredActions: `Use the component export_manifest artifact as the source of truth for component "${manifest.component.componentId}" and the reference_export artifact for inspection only. The next component-track step is a registry component copy tool; do not install the virtual page as a normal page.`
4314
+ }
4315
+ };
4316
+ }
3535
4317
  async inspectPage(slug, _context) {
3536
4318
  await this.ensureTempLayout();
3537
4319
  const pageDetails = await this.provider.getProjectPageBySlug(slug);
@@ -3543,6 +4325,25 @@ var ProjectSyncService = class {
3543
4325
  reportRows: reportPayload.reportRows
3544
4326
  };
3545
4327
  }
4328
+ async readComponentExportManifest(id, manifestPath) {
4329
+ let manifest;
4330
+ try {
4331
+ manifest = parsePrimeUiComponentExportManifest(
4332
+ JSON.parse(await readFile8(manifestPath, "utf-8"))
4333
+ );
4334
+ } catch (error) {
4335
+ const reason = error instanceof Error ? error.message : String(error);
4336
+ throw new Error(
4337
+ `Component export manifest is required for download id "${id}". Run create_component_export for this export before downloading. Details: ${reason}`
4338
+ );
4339
+ }
4340
+ if (manifest.export.id !== id || manifest.exportId !== id) {
4341
+ throw new Error(
4342
+ `Component export manifest mismatch for id "${id}". Run create_component_export and retry download.`
4343
+ );
4344
+ }
4345
+ return manifest;
4346
+ }
3546
4347
  async copyPage(originPageSlug, _context) {
3547
4348
  await this.ensureTempLayout();
3548
4349
  return copyPageFromExport({
@@ -3568,6 +4369,14 @@ var ProjectSyncService = class {
3568
4369
  pageDetails
3569
4370
  });
3570
4371
  }
4372
+ async copyRegistryComponent(componentId, _context) {
4373
+ await this.ensureTempLayout();
4374
+ return copyRegistryComponentFromExport({
4375
+ projectRoot: this.targetProjectRoot,
4376
+ exportsRoot: this.exportsRoot,
4377
+ componentId
4378
+ });
4379
+ }
3571
4380
  async copyExportable(exportableKey, _context) {
3572
4381
  await this.ensureTempLayout();
3573
4382
  return copyExportableFromExport({
@@ -3586,6 +4395,30 @@ var ProjectSyncService = class {
3586
4395
  await ensureDir(this.tempRoot);
3587
4396
  await ensureDir(this.exportsRoot);
3588
4397
  }
4398
+ getRelatedIndexesForRuntime(overview, runtime) {
4399
+ const indexes = [];
4400
+ const seen = /* @__PURE__ */ new Set();
4401
+ const pushIndex = (index) => {
4402
+ if (!index || seen.has(index.id)) {
4403
+ return;
4404
+ }
4405
+ seen.add(index.id);
4406
+ indexes.push(index);
4407
+ };
4408
+ if (overview.defaultIndex) {
4409
+ const matchesByUid = runtime.currentMeilisearchIndexUid && overview.defaultIndex.meilisearchIndexUid === runtime.currentMeilisearchIndexUid;
4410
+ const matchesDefaultSlug = runtime.slug === overview.runtimeModel.defaultRuntimeSlug && overview.defaultIndex.kind === "default-runtime";
4411
+ if (matchesByUid || matchesDefaultSlug) {
4412
+ pushIndex(overview.defaultIndex);
4413
+ }
4414
+ }
4415
+ for (const index of overview.customIndexes) {
4416
+ if (runtime.currentMeilisearchIndexUid && index.meilisearchIndexUid === runtime.currentMeilisearchIndexUid) {
4417
+ pushIndex(index);
4418
+ }
4419
+ }
4420
+ return indexes;
4421
+ }
3589
4422
  };
3590
4423
 
3591
4424
  // src/runtime.ts
@@ -3776,6 +4609,57 @@ var LazyProjectSyncSource = class {
3776
4609
  }
3777
4610
  );
3778
4611
  }
4612
+ async getSearchOverview(context) {
4613
+ return this.withService(
4614
+ context,
4615
+ (service) => service.getSearchOverview(context),
4616
+ {
4617
+ requireTargetProjectRoot: false
4618
+ }
4619
+ );
4620
+ }
4621
+ async getSearchEnvironment(environmentSlug, context) {
4622
+ return this.withService(
4623
+ context,
4624
+ (service) => service.getSearchEnvironment(environmentSlug, context),
4625
+ {
4626
+ requireTargetProjectRoot: false
4627
+ }
4628
+ );
4629
+ }
4630
+ async createSearchEnvironment(input, context) {
4631
+ return this.withMutationService(
4632
+ context,
4633
+ (service) => service.createSearchEnvironment(input, context),
4634
+ {
4635
+ requireTargetProjectRoot: false
4636
+ }
4637
+ );
4638
+ }
4639
+ async updateSearchEnvironment(input, context) {
4640
+ return this.withMutationService(
4641
+ context,
4642
+ (service) => service.updateSearchEnvironment(input, context),
4643
+ {
4644
+ requireTargetProjectRoot: false
4645
+ }
4646
+ );
4647
+ }
4648
+ async deleteSearchEnvironment(environmentSlug, context) {
4649
+ return this.withMutationService(
4650
+ context,
4651
+ (service) => service.deleteSearchEnvironment(environmentSlug, context),
4652
+ {
4653
+ requireTargetProjectRoot: false
4654
+ }
4655
+ );
4656
+ }
4657
+ async syncSearchEnvironment(environmentSlug, context) {
4658
+ return this.withService(
4659
+ context,
4660
+ (service) => service.syncSearchEnvironment(environmentSlug, context)
4661
+ );
4662
+ }
3779
4663
  async listExports(context) {
3780
4664
  return this.withService(context, (service) => service.listExports(context));
3781
4665
  }
@@ -3785,12 +4669,24 @@ var LazyProjectSyncSource = class {
3785
4669
  (service) => service.createExport(context)
3786
4670
  );
3787
4671
  }
4672
+ async createComponentExport(componentId, context) {
4673
+ return this.withService(
4674
+ context,
4675
+ (service) => service.createComponentExport(componentId, context)
4676
+ );
4677
+ }
3788
4678
  async downloadExportById(id, context) {
3789
4679
  return this.withService(
3790
4680
  context,
3791
4681
  (service) => service.downloadExportById(id, context)
3792
4682
  );
3793
4683
  }
4684
+ async downloadComponentExportById(id, context) {
4685
+ return this.withService(
4686
+ context,
4687
+ (service) => service.downloadComponentExportById(id, context)
4688
+ );
4689
+ }
3794
4690
  async inspectPage(slug, context) {
3795
4691
  const result = await this.withService(
3796
4692
  context,
@@ -3811,6 +4707,12 @@ var LazyProjectSyncSource = class {
3811
4707
  (service) => service.copyComponent(originPageSlug, blockId, componentId, context)
3812
4708
  );
3813
4709
  }
4710
+ async copyRegistryComponent(componentId, context) {
4711
+ return this.withMutationService(
4712
+ context,
4713
+ (service) => service.copyRegistryComponent(componentId, context)
4714
+ );
4715
+ }
3814
4716
  async copyExportable(exportableKey, context) {
3815
4717
  return this.withMutationService(
3816
4718
  context,
@@ -3911,6 +4813,18 @@ var exportPageSchema = z4.object({
3911
4813
  componentsPath: z4.string().describe("Page components directory path relative to export root."),
3912
4814
  manifest: exportPageManifestSchema
3913
4815
  });
4816
+ var componentExportComponentSchema = z4.object({
4817
+ componentId: z4.string().describe("PrimeUI component registry identifier used to create export."),
4818
+ name: z4.string().describe("Human-readable PrimeUI component name from registry metadata."),
4819
+ pageType: z4.string().describe("Page type used by the virtual component export snapshot."),
4820
+ family: z4.string().describe("Component family/group metadata from the PrimeUI registry."),
4821
+ defaultPropsAvailable: z4.boolean().describe("True when registry default props were available for export."),
4822
+ isReadyToExport: z4.boolean().describe("True when this component export payload is ready to download.")
4823
+ });
4824
+ var componentExportPageSchema = exportPageSchema.omit({
4825
+ pagePath: true,
4826
+ componentsPath: true
4827
+ });
3914
4828
  var dependencySectionSchema = z4.enum([
3915
4829
  "dependencies",
3916
4830
  "devDependencies",
@@ -3939,8 +4853,8 @@ var skippedCopyFileSchema = z4.object({
3939
4853
  targetPath: z4.string().describe(
3940
4854
  "Relative target path intentionally not copied into user project root."
3941
4855
  ),
3942
- reason: z4.enum(["package_json_managed_as_dependencies"]).describe(
3943
- "Machine-readable reason for skipping this file. package_json_managed_as_dependencies means package.json was handled as dependency guidance instead of direct file copy."
4856
+ reason: z4.enum(["package_json_managed_as_dependencies", "virtual_component_route"]).describe(
4857
+ "Machine-readable reason for skipping this file. package_json_managed_as_dependencies means package.json was handled as dependency guidance instead of direct file copy. virtual_component_route means the internal component-export route was intentionally not installed into the target app."
3944
4858
  )
3945
4859
  });
3946
4860
  var runtimeGuidanceArtifactSchema = z4.object({
@@ -4024,7 +4938,7 @@ WORKFLOW ORDER (always follow this sequence):
4024
4938
  4. inspect_page -> inspect selected page components and produce a structured comparison table
4025
4939
  5. create_export -> generate export snapshot and local manifest with page file lists + shared exportables
4026
4940
  6. download_export -> download to temp directory
4027
- 7. copy_page, copy_component, or copy_exportable -> transfer one selected page, one selected block-level component, or one selected shared exportable safely
4941
+ 7. copy_page, copy_component, copy_exportable, or copy_registry_component -> transfer one selected page, one selected block-level page component, one selected shared exportable, or one registry component safely
4028
4942
  8. Reconcile integration points, dependency follow-up, and reported conflicts
4029
4943
  `.trim();
4030
4944
  var initialInstructions = `
@@ -4064,7 +4978,7 @@ CRITICAL RULES FOR PAGE IMPORT:
4064
4978
  - copy_page for page manifests,
4065
4979
  - copy_component for one selected block-level component instance,
4066
4980
  - copy_exportable for shared exportables.
4067
- - Always call copy_page, copy_component, or copy_exportable instead of manual file copy.
4981
+ - Always call copy_page, copy_component, copy_exportable, or copy_registry_component instead of manual file copy.
4068
4982
  - copy_page performs safe copy only:
4069
4983
  - new files are copied,
4070
4984
  - identical files are reported,
@@ -4252,6 +5166,59 @@ ${WORKFLOW_SUMMARY}`,
4252
5166
  openWorldHint: true
4253
5167
  }
4254
5168
  };
5169
+ var toolCreateComponentExport = {
5170
+ title: "PrimeUI Create Component Export",
5171
+ description: `Create a component-track export for one known PrimeUI componentId and wait for completion. This uses the component registry export API and returns a component-aware sidecar manifest plus the virtual page manifest created by Studio.
5172
+
5173
+ WHEN TO USE: Use this only for the component-registry import track when the user wants to export a single known componentId. This is separate from create_export, which exports selected project pages.
5174
+
5175
+ AFTER CALLING:
5176
+ - Verify component.componentId matches the requested componentId.
5177
+ - Verify component.isReadyToExport is true and page.manifest.files is present.
5178
+ - Local component sidecar manifest is saved to .primeui/temp/exports/[exportId].manifest.json.
5179
+ - Use the returned export ID to call download_component_export.
5180
+ - Use copy_registry_component after download_component_export for this component-track manifest. Do not use page copy tools for component-track manifests.
5181
+ - If guidance is present in the result, read guidance.artifacts and follow guidance.requiredActions before continuing.
5182
+
5183
+ ${WORKFLOW_SUMMARY}`,
5184
+ inputSchema: {
5185
+ projectRoot: projectRootInputSchema,
5186
+ componentId: z4.string().min(1).describe("PrimeUI component registry identifier to export.")
5187
+ },
5188
+ outputSchema: z4.object({
5189
+ exportId: z4.string().describe(
5190
+ "Freshly created component export identifier. Use this as download_component_export input.id."
5191
+ ),
5192
+ export: z4.object({
5193
+ id: z4.string().describe("Created export identifier."),
5194
+ status: exportStatusSchema,
5195
+ createdAt: z4.string().describe("Export creation timestamp in ISO-8601 UTC format."),
5196
+ expiresAt: z4.string().nullable().describe(
5197
+ "Export expiration timestamp in ISO-8601 UTC format, or null when export has no explicit expiration."
5198
+ ),
5199
+ summary: exportSummarySchema.describe(
5200
+ "Export run summary with total/successful/failed counters."
5201
+ ),
5202
+ exportables: z4.array(exportableSchema).describe("Shared exportables included in this export payload.")
5203
+ }).describe("Created component export summary."),
5204
+ component: componentExportComponentSchema,
5205
+ page: componentExportPageSchema.describe(
5206
+ "Virtual page manifest for this component export."
5207
+ ),
5208
+ pages: z4.array(componentExportPageSchema).describe(
5209
+ "Page-compatible virtual page payload associated with this component export."
5210
+ ),
5211
+ guidance: runtimeGuidanceSchema.optional().describe(
5212
+ "Mandatory runtime guidance for local artifacts created during component export."
5213
+ )
5214
+ }),
5215
+ annotations: {
5216
+ readOnlyHint: false,
5217
+ destructiveHint: false,
5218
+ idempotentHint: false,
5219
+ openWorldHint: true
5220
+ }
5221
+ };
4255
5222
  var toolDownloadExport = {
4256
5223
  title: "PrimeUI Download Export",
4257
5224
  description: `Download a completed export into .primeui/temp/exports/[exportId]. Downloads and extracts the full export as a standalone Next.js project into the temp directory. This does NOT modify the user's project - files land only in .primeui/temp/.
@@ -4280,25 +5247,67 @@ AFTER DOWNLOAD:
4280
5247
  - Do not force cleanup at flow end; keep downloaded export files available for validation and follow-up checks.
4281
5248
  - If guidance is present in the result, read guidance.artifacts and follow guidance.requiredActions before choosing the next copy tool.
4282
5249
 
4283
- ${WORKFLOW_SUMMARY}`,
5250
+ ${WORKFLOW_SUMMARY}`,
5251
+ inputSchema: {
5252
+ projectRoot: projectRootInputSchema,
5253
+ id: z4.string().describe(
5254
+ "Export identifier to download. Prefer export.id from create_export; use list_exports only on explicit user request."
5255
+ )
5256
+ },
5257
+ outputSchema: z4.object({
5258
+ exportId: z4.string().describe(
5259
+ "Downloaded export identifier. Should match the requested input.id for traceability."
5260
+ ),
5261
+ projectPath: z4.string().describe(
5262
+ "Absolute local path to extracted export root in .primeui/temp/exports/[exportId]. Read files from here only."
5263
+ ),
5264
+ manifestPath: z4.string().describe(
5265
+ "Absolute path to sidecar export manifest file (.primeui/temp/exports/[exportId].manifest.json) saved by create_export and required by copy_page and copy_component."
5266
+ ),
5267
+ guidance: runtimeGuidanceSchema.optional().describe(
5268
+ "Mandatory runtime guidance for the downloaded export and manifest artifacts. Present only on successful tool results."
5269
+ )
5270
+ }),
5271
+ annotations: {
5272
+ readOnlyHint: false,
5273
+ destructiveHint: false,
5274
+ idempotentHint: true,
5275
+ openWorldHint: true
5276
+ }
5277
+ };
5278
+ var toolDownloadComponentExport = {
5279
+ title: "PrimeUI Download Component Export",
5280
+ description: `Download a completed component-track export into .primeui/temp/exports/[exportId]. Downloads and extracts the full export archive through the existing PrimeUI export download endpoint, but requires a local component sidecar manifest created by create_component_export.
5281
+
5282
+ Do NOT call this as the first step. Requires export ID from create_component_export.
5283
+
5284
+ WHEN TO USE: Call this AFTER create_component_export has returned a completed component export. This does NOT modify the user's project - files land only in .primeui/temp/.
5285
+
5286
+ NOTE:
5287
+ - Download of an export ID without a local component sidecar manifest will fail.
5288
+ - A normal page export manifest from create_export is not accepted here.
5289
+ - The next component-track step is copy_registry_component. Do not use page copy tools for component-track manifests.
5290
+ - If guidance is present in the result, read guidance.artifacts and follow guidance.requiredActions before continuing.
5291
+
5292
+ ${WORKFLOW_SUMMARY}`,
4284
5293
  inputSchema: {
4285
5294
  projectRoot: projectRootInputSchema,
4286
5295
  id: z4.string().describe(
4287
- "Export identifier to download. Prefer export.id from create_export; use list_exports only on explicit user request."
5296
+ "Component export identifier to download. Use export.id from create_component_export."
4288
5297
  )
4289
5298
  },
4290
5299
  outputSchema: z4.object({
4291
5300
  exportId: z4.string().describe(
4292
- "Downloaded export identifier. Should match the requested input.id for traceability."
5301
+ "Downloaded component export identifier. Should match the requested input.id."
4293
5302
  ),
4294
5303
  projectPath: z4.string().describe(
4295
5304
  "Absolute local path to extracted export root in .primeui/temp/exports/[exportId]. Read files from here only."
4296
5305
  ),
4297
5306
  manifestPath: z4.string().describe(
4298
- "Absolute path to sidecar export manifest file (.primeui/temp/exports/[exportId].manifest.json) saved by create_export and required by copy_page and copy_component."
5307
+ "Absolute path to component sidecar export manifest saved by create_component_export."
4299
5308
  ),
4300
5309
  guidance: runtimeGuidanceSchema.optional().describe(
4301
- "Mandatory runtime guidance for the downloaded export and manifest artifacts. Present only on successful tool results."
5310
+ "Mandatory runtime guidance for the downloaded component export and manifest artifacts."
4302
5311
  )
4303
5312
  }),
4304
5313
  annotations: {
@@ -4491,6 +5500,97 @@ ${WORKFLOW_SUMMARY}`,
4491
5500
  openWorldHint: false
4492
5501
  }
4493
5502
  };
5503
+ var toolCopyRegistryComponent = {
5504
+ title: "PrimeUI Copy Registry Component",
5505
+ description: `Safely copy one registry component from a downloaded component export into the user's local project. Works only with component-track files in .primeui/temp/exports and does NOT call PrimeUI API.
5506
+
5507
+ WHEN TO USE:
5508
+ - Call this AFTER create_component_export and download_component_export.
5509
+ - Use this for component-registry exports, not page exports.
5510
+ - Pass componentId from the create_component_export result so the local component sidecar manifest can be validated before copying.
5511
+
5512
+ BEHAVIOR:
5513
+ - Reads the component sidecar manifest saved by create_component_export.
5514
+ - Validates that manifest.component.componentId matches input.componentId.
5515
+ - Copies files strictly from page.manifest.files in the component sidecar manifest.
5516
+ - Skips virtual route files that include __primeui-component-export, because those are reference/insertion hints and must not be installed as normal app routes.
5517
+ - Never copies package.json directly. package.json is used only to add missing dependency entries and report dependency version conflicts.
5518
+ - Preserves export-relative paths for copied files in this first version.
5519
+ - Never overwrites existing conflicting files.
5520
+ - Writes full conflict details to .primeui/temp/exports/[exportId].copy-registry-component-report-[copyId].json.
5521
+ - Reports copied files, identical files, conflicts, skipped files, dependency additions, dependency version conflicts, missing manifest files, and manual insertion guidance.
5522
+ - If status is needs_review, resolve conflicts, missing manifest files, or dependency version conflicts before treating transfer as complete.
5523
+
5524
+ ${WORKFLOW_SUMMARY}`,
5525
+ inputSchema: {
5526
+ projectRoot: projectRootInputSchema,
5527
+ componentId: z4.string().describe(
5528
+ "PrimeUI component registry identifier from create_component_export output. Must match the local component sidecar manifest."
5529
+ )
5530
+ },
5531
+ outputSchema: z4.object({
5532
+ status: z4.enum(["completed", "needs_review"]).describe(
5533
+ "Decision state for next step. needs_review means conflicts, dependency version conflicts, missing manifest files, or no copyable files require manual review."
5534
+ ),
5535
+ message: z4.string().describe(
5536
+ "Decision-oriented summary with reportPath and manual insertion guidance."
5537
+ ),
5538
+ reportPath: z4.string().describe(
5539
+ "Absolute path to saved local report with conflicts, skipped files, and component manifest metadata."
5540
+ ),
5541
+ exportId: z4.string().describe("Resolved local component export identifier used for copy."),
5542
+ exportPath: z4.string().describe("Absolute path to local extracted component export root."),
5543
+ manifestPath: z4.string().describe(
5544
+ "Absolute path to the local component sidecar manifest used during copy."
5545
+ ),
5546
+ component: componentExportComponentSchema.describe(
5547
+ "Component metadata from the validated component sidecar manifest."
5548
+ ),
5549
+ manifestFiles: z4.array(z4.string()).describe(
5550
+ "Normalized page.manifest.files from the component sidecar manifest."
5551
+ ),
5552
+ copyableFiles: z4.array(z4.string()).describe(
5553
+ "Manifest files considered for copying after filtering virtual route files and package.json."
5554
+ ),
5555
+ newFiles: z4.array(z4.string()).describe("Relative target paths for new files copied."),
5556
+ identicalFiles: z4.array(z4.string()).describe("Relative target paths for existing byte-identical files."),
5557
+ conflictFiles: z4.array(conflictFileSchema).describe(
5558
+ "Files that already exist and differ from export version. Never overwritten."
5559
+ ),
5560
+ skippedFiles: z4.array(skippedCopyFileSchema).describe(
5561
+ "Manifest files intentionally not copied, such as package.json or virtual component-export routes."
5562
+ ),
5563
+ addedDependencies: z4.array(dependencyToAddSchema).describe(
5564
+ "Dependencies that were missing and have been added to user's package.json."
5565
+ ),
5566
+ dependenciesVersionConflicts: z4.array(dependencyVersionConflictSchema).describe(
5567
+ "Dependencies with version mismatch between export and user project. Report only."
5568
+ ),
5569
+ missingManifestFiles: z4.array(z4.string()).describe(
5570
+ "Manifest file paths that were expected but missing from the downloaded export."
5571
+ ),
5572
+ summary: z4.object({
5573
+ totalManifestFiles: z4.number(),
5574
+ totalCopyableFiles: z4.number(),
5575
+ copiedFiles: z4.number(),
5576
+ identicalFiles: z4.number(),
5577
+ conflictFiles: z4.number(),
5578
+ skippedFiles: z4.number(),
5579
+ addedDependencies: z4.number(),
5580
+ dependenciesVersionConflicts: z4.number(),
5581
+ missingManifestFiles: z4.number()
5582
+ }),
5583
+ guidance: runtimeGuidanceSchema.describe(
5584
+ "Structured follow-up guidance. It always instructs manual insertion into a real target page and warns that the virtual route was skipped."
5585
+ )
5586
+ }),
5587
+ annotations: {
5588
+ readOnlyHint: false,
5589
+ destructiveHint: false,
5590
+ idempotentHint: false,
5591
+ openWorldHint: false
5592
+ }
5593
+ };
4494
5594
  var toolCopyExportable = {
4495
5595
  title: "PrimeUI Copy Exportable",
4496
5596
  description: `Safely copy one shared exportable from downloaded export into the user's local project. Works only with local files in .primeui/temp/exports and does NOT call PrimeUI API.
@@ -4767,6 +5867,124 @@ var projectIssueReportSubmitInputSchema = z4.object({
4767
5867
  "Optional issue report tags. Empty values are trimmed and dropped by the API."
4768
5868
  )
4769
5869
  });
5870
+ var searchEnvironmentSlugSchema = z4.string().describe(
5871
+ "Search environment slug, for example 'prod', 'staging', or a custom environment slug."
5872
+ );
5873
+ var searchRuntimeStatusSchema = z4.enum([
5874
+ "bootstrapping",
5875
+ "active",
5876
+ "indexing",
5877
+ "failed",
5878
+ "inactive"
5879
+ ]);
5880
+ var searchRuntimeSchema = z4.object({
5881
+ createdAt: z4.string().describe("ISO timestamp when the environment was created."),
5882
+ currentMeilisearchIndexUid: z4.string().nullable().describe(
5883
+ "Current Meilisearch index UID bound to this environment, when available."
5884
+ ),
5885
+ currentQueryId: z4.string().nullable().describe(
5886
+ "Current query credential or query binding identifier, when available."
5887
+ ),
5888
+ id: z4.string().describe("Stable internal environment record identifier."),
5889
+ lastErrorSummary: z4.string().nullable().describe("Most recent error summary for this environment, if any."),
5890
+ lastFailedSyncAt: z4.string().nullable().describe("ISO timestamp of the last failed sync for this environment."),
5891
+ lastSuccessfulSyncAt: z4.string().nullable().describe(
5892
+ "ISO timestamp of the last successful sync for this environment."
5893
+ ),
5894
+ name: z4.string().describe("Human-readable environment name."),
5895
+ slug: z4.string().describe("Canonical search environment slug."),
5896
+ status: searchRuntimeStatusSchema.describe(
5897
+ "Current environment lifecycle status."
5898
+ ),
5899
+ updatedAt: z4.string().describe("ISO timestamp of the latest environment update.")
5900
+ });
5901
+ var searchOverviewOutputSchema = z4.object({
5902
+ success: z4.literal(true),
5903
+ projectId: z4.string().describe("PrimeUI project identifier for this overview."),
5904
+ runtimeModel: z4.object({
5905
+ additionalRuntimesSupported: z4.literal(true),
5906
+ defaultRuntimeAutoWired: z4.literal(true),
5907
+ defaultRuntimeSlug: z4.literal("prod"),
5908
+ mode: z4.literal("runtime-first"),
5909
+ panelCompatibility: z4.literal("disabled"),
5910
+ stagingRuntimeAutoWired: z4.literal(false),
5911
+ stagingRuntimeSlug: z4.literal("staging")
5912
+ }).describe("Managed-search runtime model summary from the PrimeUI API."),
5913
+ search: z4.object({
5914
+ bootstrapCompletedAt: z4.string().nullable(),
5915
+ createdAt: z4.string().nullable(),
5916
+ id: z4.string().nullable(),
5917
+ enabled: z4.boolean(),
5918
+ status: z4.enum(["inactive", "active", "degraded"]),
5919
+ defaultIndexId: z4.string().nullable(),
5920
+ defaultSearchId: z4.string().nullable(),
5921
+ lastErrorSummary: z4.string().nullable(),
5922
+ lastFailedSyncAt: z4.string().nullable(),
5923
+ lastSuccessfulSyncAt: z4.string().nullable(),
5924
+ updatedAt: z4.string().nullable()
5925
+ }).describe("Top-level managed-search root status."),
5926
+ runtimes: z4.array(searchRuntimeSchema).describe("All configured search environments for this project."),
5927
+ defaultIndex: z4.record(z4.unknown()).nullable().describe(
5928
+ "Default index payload from the API overview, or null when absent."
5929
+ ),
5930
+ customIndexes: z4.array(z4.record(z4.unknown())).describe("Additional search index payloads from the API overview."),
5931
+ recentJobs: z4.array(z4.record(z4.unknown())).describe("Recent search jobs from the overview API."),
5932
+ recentSyncRuns: z4.array(z4.record(z4.unknown())).describe("Recent sync-run payloads from the overview API."),
5933
+ sources: z4.array(z4.record(z4.unknown())).describe("Configured managed-search sources from the overview API."),
5934
+ lastError: z4.record(z4.unknown()).nullable().describe("Latest overview-level managed-search error payload, if any."),
5935
+ queryProtection: z4.record(z4.unknown()).describe("Query protection summary from the overview API."),
5936
+ relevanceSettings: z4.record(z4.unknown()).describe("Relevance settings summary from the overview API.")
5937
+ });
5938
+ var searchEnvironmentOutputSchema = z4.object({
5939
+ success: z4.literal(true),
5940
+ environmentSlug: z4.string().describe("Resolved search environment slug for this focused MCP view."),
5941
+ environment: searchRuntimeSchema.describe("Selected environment record."),
5942
+ primaryIndex: z4.record(z4.unknown()).nullable().describe(
5943
+ "Primary related index for this environment when one can be identified."
5944
+ ),
5945
+ relatedIndexes: z4.array(z4.record(z4.unknown())).describe("Related search indexes inferred for this environment."),
5946
+ recentJobs: z4.array(z4.record(z4.unknown())).describe(
5947
+ "Recent jobs filtered to the related indexes for this environment."
5948
+ ),
5949
+ recentSyncRuns: z4.array(z4.record(z4.unknown())).describe(
5950
+ "Recent sync runs filtered to the related indexes for this environment."
5951
+ ),
5952
+ search: z4.record(z4.unknown()).describe(
5953
+ "Top-level managed-search root status carried through from the overview API."
5954
+ ),
5955
+ runtimeModel: z4.record(z4.unknown()).describe(
5956
+ "Managed-search runtime model carried through from the overview API."
5957
+ ),
5958
+ sources: z4.array(z4.record(z4.unknown())).describe("Managed-search sources carried through from the overview API."),
5959
+ lastError: z4.record(z4.unknown()).nullable().describe("Latest overview-level managed-search error payload, if any.")
5960
+ });
5961
+ var searchEnvironmentMutationOutputSchema = z4.object({
5962
+ success: z4.literal(true),
5963
+ environment: searchRuntimeSchema.describe(
5964
+ "Environment payload returned by the PrimeUI API."
5965
+ )
5966
+ });
5967
+ var searchEnvironmentDeleteOutputSchema = z4.object({
5968
+ success: z4.literal(true)
5969
+ });
5970
+ var searchEnvironmentSyncOutputSchema = z4.object({
5971
+ success: z4.literal(true),
5972
+ mode: z4.enum(["executed", "guidance"]).describe(
5973
+ "Whether MCP executed the real sync command or returned next-step guidance."
5974
+ ),
5975
+ environmentSlug: z4.string().describe("Resolved search environment slug."),
5976
+ command: z4.string().describe(
5977
+ "Exact command the agent should run or that MCP already executed."
5978
+ ),
5979
+ workingDirectory: z4.string().describe("Absolute project directory where the command applies."),
5980
+ jobId: z4.string().nullable().describe(
5981
+ "Search job identifier when the command was actually executed and returned one."
5982
+ ),
5983
+ status: z4.string().nullable().describe("Execution status when available; null for guidance-only mode."),
5984
+ notes: z4.array(z4.string()).describe(
5985
+ "Actionable notes that explain why guidance or execution was chosen."
5986
+ )
5987
+ });
4770
5988
  var toolProjectDescriptionGet = {
4771
5989
  title: "PrimeUI Project Description Get",
4772
5990
  description: `Atomic external API helper. Returns the current shared project description for the scoped PrimeUI project.
@@ -4974,6 +6192,139 @@ AFTER CALLING:
4974
6192
  openWorldHint: true
4975
6193
  }
4976
6194
  };
6195
+ var toolSearchOverviewGet = {
6196
+ title: "PrimeUI Search Overview Get",
6197
+ description: `Standalone managed-search helper. Returns the current search overview for the scoped PrimeUI project using the existing environment-first API contract.
6198
+
6199
+ WHEN TO USE:
6200
+ - Use this as the starting point for MCP search work.
6201
+ - This tool is intentionally separate from the page/export workflow chain.
6202
+ - Call this before focused environment inspection or environment mutations when the current search state is not already known.
6203
+
6204
+ AFTER CALLING:
6205
+ - Use runtimes as the authoritative inventory of search environments.
6206
+ - Use search_environment_get when the caller wants one environment-focused view instead of the full overview payload.`,
6207
+ inputSchema: optionalProjectRootInputObjectSchema,
6208
+ outputSchema: searchOverviewOutputSchema,
6209
+ annotations: {
6210
+ readOnlyHint: true,
6211
+ destructiveHint: false,
6212
+ idempotentHint: true,
6213
+ openWorldHint: true
6214
+ }
6215
+ };
6216
+ var toolSearchEnvironmentGet = {
6217
+ title: "PrimeUI Search Environment Get",
6218
+ description: `Standalone managed-search helper. Returns one environment-focused view derived from the existing search overview contract.
6219
+
6220
+ WHEN TO USE:
6221
+ - Use this when the caller already knows the target environment slug.
6222
+ - This tool does not rely on a separate runtime-details endpoint; it is an MCP convenience projection over the overview API.
6223
+
6224
+ AFTER CALLING:
6225
+ - Treat environment as the source of truth for the selected search environment.
6226
+ - Treat relatedIndexes, recentJobs, and recentSyncRuns as MCP-filtered convenience data for this one environment.`,
6227
+ inputSchema: {
6228
+ projectRoot: projectRootInputSchema,
6229
+ environmentSlug: searchEnvironmentSlugSchema
6230
+ },
6231
+ outputSchema: searchEnvironmentOutputSchema,
6232
+ annotations: {
6233
+ readOnlyHint: true,
6234
+ destructiveHint: false,
6235
+ idempotentHint: true,
6236
+ openWorldHint: true
6237
+ }
6238
+ };
6239
+ var toolSearchEnvironmentCreate = {
6240
+ title: "PrimeUI Search Environment Create",
6241
+ description: `Standalone managed-search helper. Creates one new search environment through the existing PrimeUI search-environment management API.
6242
+
6243
+ WHEN TO USE:
6244
+ - Use this only when the caller explicitly wants to create a new search environment.
6245
+ - This is a power-user environment management tool, not part of the primary page/export workflow.
6246
+
6247
+ AFTER CALLING:
6248
+ - Treat the returned environment payload as the immediate API result for the new environment.`,
6249
+ inputSchema: {
6250
+ projectRoot: projectRootInputSchema,
6251
+ slug: searchEnvironmentSlugSchema,
6252
+ name: z4.string().describe("Human-readable environment name to create.")
6253
+ },
6254
+ outputSchema: searchEnvironmentMutationOutputSchema,
6255
+ annotations: {
6256
+ readOnlyHint: false,
6257
+ destructiveHint: false,
6258
+ idempotentHint: false,
6259
+ openWorldHint: true
6260
+ }
6261
+ };
6262
+ var toolSearchEnvironmentUpdate = {
6263
+ title: "PrimeUI Search Environment Update",
6264
+ description: `Standalone managed-search helper. Updates one existing search environment through the PrimeUI search-environment management API.
6265
+
6266
+ WHEN TO USE:
6267
+ - Use this only when the caller explicitly wants to update an existing search environment.
6268
+ - Keep this narrow: name and status updates only.
6269
+
6270
+ AFTER CALLING:
6271
+ - Treat the returned environment payload as the immediate API result for the updated environment.`,
6272
+ inputSchema: {
6273
+ projectRoot: projectRootInputSchema,
6274
+ environmentSlug: searchEnvironmentSlugSchema,
6275
+ name: z4.string().optional().describe("Optional new human-readable environment name."),
6276
+ status: searchRuntimeStatusSchema.optional().describe("Optional new environment lifecycle status.")
6277
+ },
6278
+ outputSchema: searchEnvironmentMutationOutputSchema,
6279
+ annotations: {
6280
+ readOnlyHint: false,
6281
+ destructiveHint: false,
6282
+ idempotentHint: false,
6283
+ openWorldHint: true
6284
+ }
6285
+ };
6286
+ var toolSearchEnvironmentDelete = {
6287
+ title: "PrimeUI Search Environment Delete",
6288
+ description: `Standalone managed-search helper. Deletes one search environment through the PrimeUI search-environment management API when the backend allows it.
6289
+
6290
+ WHEN TO USE:
6291
+ - Use this only when the caller explicitly wants to delete an existing environment.
6292
+ - This tool relies on normal API allow/deny behavior instead of inventing separate MCP policy summaries.`,
6293
+ inputSchema: {
6294
+ projectRoot: projectRootInputSchema,
6295
+ environmentSlug: searchEnvironmentSlugSchema
6296
+ },
6297
+ outputSchema: searchEnvironmentDeleteOutputSchema,
6298
+ annotations: {
6299
+ readOnlyHint: false,
6300
+ destructiveHint: true,
6301
+ idempotentHint: false,
6302
+ openWorldHint: true
6303
+ }
6304
+ };
6305
+ var toolSearchEnvironmentSync = {
6306
+ title: "PrimeUI Search Environment Sync",
6307
+ description: `Standalone managed-search helper. Returns the real search sync command context for one environment and may execute it only when MCP can do so truthfully.
6308
+
6309
+ WHEN TO USE:
6310
+ - Use this when the caller wants to sync one search environment against the actual local exported-project flow.
6311
+ - This tool intentionally avoids pretending that a runtime-action API wrapper would always represent fresh local project state.
6312
+
6313
+ AFTER CALLING:
6314
+ - If mode is guidance, run the returned command from workingDirectory next.
6315
+ - If mode is executed, treat jobId and status as the immediate sync invocation result.`,
6316
+ inputSchema: {
6317
+ projectRoot: projectRootInputSchema,
6318
+ environmentSlug: searchEnvironmentSlugSchema
6319
+ },
6320
+ outputSchema: searchEnvironmentSyncOutputSchema,
6321
+ annotations: {
6322
+ readOnlyHint: false,
6323
+ destructiveHint: false,
6324
+ idempotentHint: false,
6325
+ openWorldHint: true
6326
+ }
6327
+ };
4977
6328
 
4978
6329
  // src/server.ts
4979
6330
  var ZERO_ARG_PROJECT_ROOT_TOOLS = /* @__PURE__ */ new Set([
@@ -4982,7 +6333,8 @@ var ZERO_ARG_PROJECT_ROOT_TOOLS = /* @__PURE__ */ new Set([
4982
6333
  "project_pages_list",
4983
6334
  "list_exports",
4984
6335
  "create_export",
4985
- "clear_temp"
6336
+ "clear_temp",
6337
+ "search_overview_get"
4986
6338
  ]);
4987
6339
  function serializeToolData(data) {
4988
6340
  try {
@@ -5260,6 +6612,20 @@ function createPrimeUiMcpServer(source) {
5260
6612
  }
5261
6613
  }
5262
6614
  );
6615
+ server.registerTool(
6616
+ "create_component_export",
6617
+ toolCreateComponentExport,
6618
+ async ({ componentId, projectRoot }) => {
6619
+ try {
6620
+ const result = await source.createComponentExport(componentId, {
6621
+ projectRoot
6622
+ });
6623
+ return okResult("create_component_export", result);
6624
+ } catch (error) {
6625
+ return errorResult(error);
6626
+ }
6627
+ }
6628
+ );
5263
6629
  server.registerTool(
5264
6630
  "download_export",
5265
6631
  toolDownloadExport,
@@ -5275,6 +6641,20 @@ function createPrimeUiMcpServer(source) {
5275
6641
  }
5276
6642
  }
5277
6643
  );
6644
+ server.registerTool(
6645
+ "download_component_export",
6646
+ toolDownloadComponentExport,
6647
+ async ({ id, projectRoot }) => {
6648
+ try {
6649
+ const result = await source.downloadComponentExportById(id, {
6650
+ projectRoot
6651
+ });
6652
+ return okResult("download_component_export", result);
6653
+ } catch (error) {
6654
+ return errorResult(error);
6655
+ }
6656
+ }
6657
+ );
5278
6658
  server.registerTool(
5279
6659
  "clear_temp",
5280
6660
  toolClearTemp,
@@ -5327,6 +6707,20 @@ function createPrimeUiMcpServer(source) {
5327
6707
  }
5328
6708
  }
5329
6709
  );
6710
+ server.registerTool(
6711
+ "copy_registry_component",
6712
+ toolCopyRegistryComponent,
6713
+ async ({ componentId, projectRoot }) => {
6714
+ try {
6715
+ const result = await source.copyRegistryComponent(componentId, {
6716
+ projectRoot
6717
+ });
6718
+ return okResult("copy_registry_component", result);
6719
+ } catch (error) {
6720
+ return errorResult(error);
6721
+ }
6722
+ }
6723
+ );
5330
6724
  server.registerTool(
5331
6725
  "copy_exportable",
5332
6726
  toolCopyExportable,
@@ -5344,6 +6738,99 @@ function createPrimeUiMcpServer(source) {
5344
6738
  }
5345
6739
  }
5346
6740
  );
6741
+ server.registerTool(
6742
+ "search_overview_get",
6743
+ toolSearchOverviewGet,
6744
+ async (args) => {
6745
+ const { projectRoot } = args ?? {};
6746
+ try {
6747
+ const result = await source.getSearchOverview({ projectRoot });
6748
+ return okResult("search_overview_get", result);
6749
+ } catch (error) {
6750
+ return errorResult(error);
6751
+ }
6752
+ }
6753
+ );
6754
+ server.registerTool(
6755
+ "search_environment_get",
6756
+ toolSearchEnvironmentGet,
6757
+ async ({ environmentSlug, projectRoot }) => {
6758
+ try {
6759
+ const result = await source.getSearchEnvironment(environmentSlug, { projectRoot });
6760
+ return okResult("search_environment_get", result);
6761
+ } catch (error) {
6762
+ return errorResult(error);
6763
+ }
6764
+ }
6765
+ );
6766
+ server.registerTool(
6767
+ "search_environment_create",
6768
+ toolSearchEnvironmentCreate,
6769
+ async ({ name, projectRoot, slug }) => {
6770
+ try {
6771
+ const result = await source.createSearchEnvironment(
6772
+ {
6773
+ name,
6774
+ slug
6775
+ },
6776
+ { projectRoot }
6777
+ );
6778
+ return okResult("search_environment_create", result);
6779
+ } catch (error) {
6780
+ return errorResult(error);
6781
+ }
6782
+ }
6783
+ );
6784
+ server.registerTool(
6785
+ "search_environment_update",
6786
+ toolSearchEnvironmentUpdate,
6787
+ async ({
6788
+ environmentSlug,
6789
+ name,
6790
+ projectRoot,
6791
+ status
6792
+ }) => {
6793
+ try {
6794
+ const result = await source.updateSearchEnvironment(
6795
+ {
6796
+ environmentSlug,
6797
+ ...name === void 0 ? {} : { name },
6798
+ ...status === void 0 ? {} : { status }
6799
+ },
6800
+ { projectRoot }
6801
+ );
6802
+ return okResult("search_environment_update", result);
6803
+ } catch (error) {
6804
+ return errorResult(error);
6805
+ }
6806
+ }
6807
+ );
6808
+ server.registerTool(
6809
+ "search_environment_delete",
6810
+ toolSearchEnvironmentDelete,
6811
+ async ({ environmentSlug, projectRoot }) => {
6812
+ try {
6813
+ const result = await source.deleteSearchEnvironment(environmentSlug, {
6814
+ projectRoot
6815
+ });
6816
+ return okResult("search_environment_delete", result);
6817
+ } catch (error) {
6818
+ return errorResult(error);
6819
+ }
6820
+ }
6821
+ );
6822
+ server.registerTool(
6823
+ "search_environment_sync",
6824
+ toolSearchEnvironmentSync,
6825
+ async ({ environmentSlug, projectRoot }) => {
6826
+ try {
6827
+ const result = await source.syncSearchEnvironment(environmentSlug, { projectRoot });
6828
+ return okResult("search_environment_sync", result);
6829
+ } catch (error) {
6830
+ return errorResult(error);
6831
+ }
6832
+ }
6833
+ );
5347
6834
  return server;
5348
6835
  }
5349
6836