@x12i/memorix-service 3.2.1 → 3.3.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.
Files changed (104) hide show
  1. package/README.md +43 -2
  2. package/dist/app.d.ts.map +1 -1
  3. package/dist/app.js +4 -0
  4. package/dist/app.js.map +1 -1
  5. package/dist/catalog/catalog-service.d.ts +48 -0
  6. package/dist/catalog/catalog-service.d.ts.map +1 -0
  7. package/dist/catalog/catalog-service.js +397 -0
  8. package/dist/catalog/catalog-service.js.map +1 -0
  9. package/dist/catalog/package-list-source.d.ts +35 -0
  10. package/dist/catalog/package-list-source.d.ts.map +1 -0
  11. package/dist/catalog/package-list-source.js +47 -0
  12. package/dist/catalog/package-list-source.js.map +1 -0
  13. package/dist/catalog/types.d.ts +65 -0
  14. package/dist/catalog/types.d.ts.map +1 -0
  15. package/dist/catalog/types.js +16 -0
  16. package/dist/catalog/types.js.map +1 -0
  17. package/dist/catalog-store-cli.d.ts +20 -0
  18. package/dist/catalog-store-cli.d.ts.map +1 -0
  19. package/dist/catalog-store-cli.js +206 -0
  20. package/dist/catalog-store-cli.js.map +1 -0
  21. package/dist/cli.d.ts +3 -1
  22. package/dist/cli.d.ts.map +1 -1
  23. package/dist/cli.js +48 -18
  24. package/dist/cli.js.map +1 -1
  25. package/dist/connector-ops/attempt-store.d.ts +5 -0
  26. package/dist/connector-ops/attempt-store.d.ts.map +1 -0
  27. package/dist/connector-ops/attempt-store.js +186 -0
  28. package/dist/connector-ops/attempt-store.js.map +1 -0
  29. package/dist/connector-ops/index.d.ts +5 -0
  30. package/dist/connector-ops/index.d.ts.map +1 -0
  31. package/dist/connector-ops/index.js +5 -0
  32. package/dist/connector-ops/index.js.map +1 -0
  33. package/dist/connector-ops/override-store.d.ts +7 -0
  34. package/dist/connector-ops/override-store.d.ts.map +1 -0
  35. package/dist/connector-ops/override-store.js +123 -0
  36. package/dist/connector-ops/override-store.js.map +1 -0
  37. package/dist/connector-ops/sanitize.d.ts +16 -0
  38. package/dist/connector-ops/sanitize.d.ts.map +1 -0
  39. package/dist/connector-ops/sanitize.js +48 -0
  40. package/dist/connector-ops/sanitize.js.map +1 -0
  41. package/dist/connector-ops/types.d.ts +76 -0
  42. package/dist/connector-ops/types.d.ts.map +1 -0
  43. package/dist/connector-ops/types.js +12 -0
  44. package/dist/connector-ops/types.js.map +1 -0
  45. package/dist/effective-listing.d.ts +11 -0
  46. package/dist/effective-listing.d.ts.map +1 -0
  47. package/dist/effective-listing.js +41 -0
  48. package/dist/effective-listing.js.map +1 -0
  49. package/dist/errors.d.ts +5 -1
  50. package/dist/errors.d.ts.map +1 -1
  51. package/dist/errors.js +10 -3
  52. package/dist/errors.js.map +1 -1
  53. package/dist/execution-target.d.ts +16 -0
  54. package/dist/execution-target.d.ts.map +1 -1
  55. package/dist/execution-target.js +54 -0
  56. package/dist/execution-target.js.map +1 -1
  57. package/dist/index.d.ts +3 -1
  58. package/dist/index.d.ts.map +1 -1
  59. package/dist/index.js +3 -1
  60. package/dist/index.js.map +1 -1
  61. package/dist/magit/magit-pack-service.d.ts +252 -70
  62. package/dist/magit/magit-pack-service.d.ts.map +1 -1
  63. package/dist/magit/magit-pack-service.js +556 -202
  64. package/dist/magit/magit-pack-service.js.map +1 -1
  65. package/dist/magit/pack-to-patchset.d.ts +21 -0
  66. package/dist/magit/pack-to-patchset.d.ts.map +1 -1
  67. package/dist/magit/pack-to-patchset.js +29 -0
  68. package/dist/magit/pack-to-patchset.js.map +1 -1
  69. package/dist/magit/package-catalog-bridge.d.ts +4 -14
  70. package/dist/magit/package-catalog-bridge.d.ts.map +1 -1
  71. package/dist/magit/package-catalog-bridge.js +2 -21
  72. package/dist/magit/package-catalog-bridge.js.map +1 -1
  73. package/dist/mgc-packages.d.ts +4 -3
  74. package/dist/mgc-packages.d.ts.map +1 -1
  75. package/dist/mgc-packages.js +4 -3
  76. package/dist/mgc-packages.js.map +1 -1
  77. package/dist/openapi/openapi.json +1716 -137
  78. package/dist/optional-companion-url.d.ts +72 -0
  79. package/dist/optional-companion-url.d.ts.map +1 -0
  80. package/dist/optional-companion-url.js +148 -0
  81. package/dist/optional-companion-url.js.map +1 -0
  82. package/dist/platform.d.ts +11 -0
  83. package/dist/platform.d.ts.map +1 -1
  84. package/dist/platform.js +77 -2
  85. package/dist/platform.js.map +1 -1
  86. package/dist/routes/catalog.d.ts +4 -0
  87. package/dist/routes/catalog.d.ts.map +1 -0
  88. package/dist/routes/catalog.js +103 -0
  89. package/dist/routes/catalog.js.map +1 -0
  90. package/dist/routes/connector-ops.d.ts +12 -0
  91. package/dist/routes/connector-ops.d.ts.map +1 -0
  92. package/dist/routes/connector-ops.js +160 -0
  93. package/dist/routes/connector-ops.js.map +1 -0
  94. package/dist/routes/memory.d.ts.map +1 -1
  95. package/dist/routes/memory.js +9 -2
  96. package/dist/routes/memory.js.map +1 -1
  97. package/dist/routes/metadata.d.ts.map +1 -1
  98. package/dist/routes/metadata.js +135 -186
  99. package/dist/routes/metadata.js.map +1 -1
  100. package/dist/routes/pipelines.d.ts.map +1 -1
  101. package/dist/routes/pipelines.js +3 -2
  102. package/dist/routes/pipelines.js.map +1 -1
  103. package/openapi/openapi.json +1716 -137
  104. package/package.json +30 -7
@@ -1,9 +1,14 @@
1
1
  import { METADATA_KIND_IDS, METADATA_KIND_REGISTRY, validateMetadataPack, } from "@x12i/memorix-metadata";
2
2
  import { resolveScope } from "../request-scope.js";
3
+ import { resolveEffectiveForListing } from "../effective-listing.js";
3
4
  import { ServiceError } from "../errors.js";
4
5
  import { listKnownPackIds, loadKnownMetadataPack } from "../known-packs.js";
5
6
  import { stripOrgRuntimeSourcesFromPack } from "../org-sources.js";
6
- import { PACKAGE_CATALOG_ORG, associationsFromPack, buildPackagePayload, catalogAgentId, discoverPackageCatalog, packageVersionMessage, parsePackageMessage, releaseAssociations, resolveOwnerAgent, } from "../magit/package-catalog-bridge.js";
7
+ import { associationsFromPack, buildPackagePayload, catalogAgentId, discoverPackageCatalog, releaseAssociations, resolveOwnerAgent, } from "../magit/package-catalog-bridge.js";
8
+ import { packagePayloadToPack } from "../magit/pack-to-patchset.js";
9
+ import { createCatalogService } from "../catalog/catalog-service.js";
10
+ import { collapseCatalogVersions, parsePackagesSource, selectPackagesBySource, } from "../catalog/package-list-source.js";
11
+ import { isMagitCatalogKind } from "../catalog/types.js";
7
12
  function requireMagit(platform) {
8
13
  if (!platform.magit) {
9
14
  throw new ServiceError("MAGIT_UNAVAILABLE", "metadata versioning requires a durable Mongo connection (set METADATA_MAGIT=0 to disable)", 503);
@@ -144,7 +149,7 @@ export async function registerMetadataRoutes(app, platform) {
144
149
  });
145
150
  app.get("/api/metadata/effective", async (req) => {
146
151
  const scope = resolveScope(req);
147
- const resolved = platform.metadata.resolveEffective(scope.agentIds);
152
+ const resolved = resolveEffectiveForListing((ids) => platform.metadata.resolveEffective(ids), scope.agentIds);
148
153
  return {
149
154
  scope,
150
155
  ok: resolved.ok,
@@ -156,12 +161,12 @@ export async function registerMetadataRoutes(app, platform) {
156
161
  issues: resolved.issues ?? [],
157
162
  referenceIssues: resolved.referenceIssues ?? [],
158
163
  },
159
- note: "agentIds select effective metadata only; effective is the resolved definition array",
164
+ note: "agentIds select effective metadata only; Any/* fans out and unions when multi-agent joint resolve conflicts",
160
165
  };
161
166
  });
162
167
  app.get("/api/metadata/kinds", async (req) => {
163
168
  const scope = resolveScope(req);
164
- const effective = platform.metadata.resolveEffective(scope.agentIds);
169
+ const effective = resolveEffectiveForListing((ids) => platform.metadata.resolveEffective(ids), scope.agentIds);
165
170
  const customDeclarations = (effective.effective ?? []).filter((e) => e.kind === "kind-declarations");
166
171
  return {
167
172
  scope,
@@ -184,7 +189,7 @@ export async function registerMetadataRoutes(app, platform) {
184
189
  app.get("/api/metadata/kinds/:kind", async (req) => {
185
190
  const scope = resolveScope(req);
186
191
  const { kind } = req.params;
187
- const effective = platform.metadata.resolveEffective(scope.agentIds);
192
+ const effective = resolveEffectiveForListing((ids) => platform.metadata.resolveEffective(ids), scope.agentIds);
188
193
  const items = (effective.effective ?? []).filter((e) => e.kind === kind);
189
194
  return { scope, kind, items };
190
195
  });
@@ -596,8 +601,8 @@ export async function registerMetadataRoutes(app, platform) {
596
601
  return { scope, definition: def };
597
602
  });
598
603
  // ---------------------------------------------------------------------------
599
- // Package catalog (Magit 2.9+ packages/ — Pack / list / fetch; Restore → install)
600
- // Spec: .operational/magit-central-package-storage-FR.md
604
+ // Central package catalog (org-free Pack/List/Fetch; org required
605
+ // only on Restore as the install target)
601
606
  // ---------------------------------------------------------------------------
602
607
  function installedPacks() {
603
608
  return platform.metadata.exportMetadata().packs;
@@ -608,95 +613,52 @@ export async function registerMetadataRoutes(app, platform) {
608
613
  return k;
609
614
  throw new ServiceError("VALIDATION", "kind must be agent | connector | service", 400);
610
615
  }
611
- /** Optional Magit actor from request headers (audit; not ownership ACL until Magit G1). */
612
- function actorFromRequest(req) {
613
- const h = req.headers;
614
- const pick = (name) => {
615
- const v = h[name] ?? h[name.toLowerCase()];
616
- if (Array.isArray(v))
617
- return v[0]?.trim() || undefined;
618
- return typeof v === "string" && v.trim() ? v.trim() : undefined;
619
- };
620
- const subject = pick("x-memorix-actor") ??
621
- pick("x-actor-id") ??
622
- pick("x-authix-subject");
623
- return subject ? { subject } : undefined;
624
- }
625
- /**
626
- * Magit published catalog and/or packable live installs.
627
- * Query: source=catalog|packable|all (default all); optional kind filter.
628
- * packages = Magit published (distinct kind+id, latest version row as summary).
629
- * packable = installed live (for Publish-from-this-env).
630
- * No publisher "ours only" filter until Magit G1–G3 ship.
631
- */
616
+ // Local packable by default. source=catalog proxies Magit inventory collapse;
617
+ // source=all returns both planes. Global product inventory is GET /api/catalog.
632
618
  app.get("/api/metadata/packages", async (req) => {
633
619
  const magit = requireMagit(platform);
634
620
  const q = req.query;
635
621
  const kindFilter = q.kind?.trim() && q.kind.trim() !== "all"
636
622
  ? parseKind(q.kind)
637
623
  : undefined;
638
- const sourceRaw = (q.source?.trim() || "all").toLowerCase();
639
- const source = sourceRaw === "catalog" || sourceRaw === "packable" || sourceRaw === "all"
640
- ? sourceRaw
641
- : (() => {
642
- throw new ServiceError("VALIDATION", "source must be catalog | packable | all", 400);
643
- })();
644
- const wantCatalog = source === "catalog" || source === "all";
645
- const wantPackable = source === "packable" || source === "all";
646
- let packages = [];
647
- let remote = magit.hasRemoteCatalog();
648
- if (wantCatalog) {
649
- const listed = await magit.listCatalogPackages({
624
+ const source = parsePackagesSource(q.source);
625
+ const packable = discoverPackageCatalog(installedPacks()).filter((e) => kindFilter ? e.kind === kindFilter : true);
626
+ let catalogRows = [];
627
+ if (source === "catalog" || source === "all") {
628
+ const catalog = createCatalogService({
629
+ magit,
630
+ metadata: platform.metadata,
631
+ connectorRegistry: platform.connectorRegistry,
632
+ genericConnectors: platform.genericConnectors,
633
+ });
634
+ const versions = await catalog.listMagitVersionRows({
650
635
  kind: kindFilter,
651
- maxCount: 500,
652
636
  });
653
- remote = listed.remote || remote;
654
- // Collapse versions → one catalog entry per kind+id (latest createdAt wins).
655
- const byKey = new Map();
656
- for (const v of listed.items) {
657
- if (kindFilter && v.kind !== kindFilter)
658
- continue;
659
- const key = `${v.kind}::${v.id}`;
660
- const prev = byKey.get(key);
661
- if (prev?.createdAt && prev.createdAt >= v.createdAt)
662
- continue;
663
- byKey.set(key, {
664
- kind: v.kind,
665
- id: v.id,
666
- // Owner agent is live concern; catalog packages are org-free.
667
- agentId: v.kind === "agent" ? v.id : "",
668
- label: v.kind === "agent"
669
- ? v.id
670
- : `${v.kind}:${v.id}${v.version ? ` @ ${v.version.slice(0, 12)}` : ""}`,
671
- version: v.version,
672
- checksum: v.checksum,
673
- createdAt: v.createdAt,
674
- mode: v.mode,
675
- associations: v.associations,
676
- });
677
- }
678
- packages = [...byKey.values()].sort((a, b) => a.kind.localeCompare(b.kind) || a.id.localeCompare(b.id));
679
- }
680
- const packable = wantPackable
681
- ? discoverPackageCatalog(installedPacks()).filter((e) => kindFilter ? e.kind === kindFilter : true)
682
- : [];
683
- // Backward-compat: when clients only read `packages`, prefer catalog when requested.
684
- // For source=packable only, packages[] mirrors packable so older clients still work.
685
- if (source === "packable") {
686
- packages = packable.map((e) => ({
687
- kind: e.kind,
688
- id: e.id,
689
- agentId: e.agentId,
690
- label: e.label,
637
+ catalogRows = versions
638
+ .filter((v) => isMagitCatalogKind(v.kind))
639
+ .map((v) => ({
640
+ kind: v.kind,
641
+ id: v.id,
642
+ version: v.version,
643
+ createdAt: v.createdAt,
644
+ checksum: v.checksum,
691
645
  }));
692
646
  }
693
- return {
694
- packages,
647
+ const selected = selectPackagesBySource({
648
+ source,
649
+ packages: collapseCatalogVersions(catalogRows),
695
650
  packable,
651
+ });
652
+ const note = source === "packable"
653
+ ? "Package identities discoverable from packs installed in this environment."
654
+ : source === "catalog"
655
+ ? "Collapsed Magit catalog identities (latest version per kind+id). Prefer GET /api/catalog for product inventory."
656
+ : "packages=Magit catalog (collapsed); packable=installed pack identities.";
657
+ return {
658
+ packages: selected.packages,
659
+ ...(source === "all" ? { packable: selected.packable } : {}),
696
660
  source,
697
- remote,
698
- catalogOrg: PACKAGE_CATALOG_ORG,
699
- note: "packages = Magit published catalog; packable = live installs for Publish. Publisher-scoped catalog awaits Magit G1–G3 (.operational/magit-package-ownership-catalog-FR.md).",
661
+ note,
700
662
  };
701
663
  });
702
664
  app.get("/api/metadata/packages/:kind/:id/associations", async (req) => {
@@ -719,6 +681,8 @@ export async function registerMetadataRoutes(app, platform) {
719
681
  associations: associationsFromPack(pack),
720
682
  };
721
683
  });
684
+ // FR-CPS-3/5 — flat catalog listing. Org-free: kind + id only, no agentId
685
+ // resolution needed (a catalog package isn't owned by any installed pack).
722
686
  app.get("/api/metadata/packages/:kind/:id/versions", async (req) => {
723
687
  const magit = requireMagit(platform);
724
688
  const kind = parseKind(req.params.kind);
@@ -726,44 +690,42 @@ export async function registerMetadataRoutes(app, platform) {
726
690
  if (!id)
727
691
  throw new ServiceError("VALIDATION", "id required", 400);
728
692
  const q = req.query;
729
- const packs = installedPacks();
730
- let ownerAgentId;
731
- try {
732
- ownerAgentId = resolveOwnerAgent(packs, kind, id, q.agentId);
733
- }
734
- catch {
735
- ownerAgentId = kind === "agent" ? id : q.agentId?.trim() || "";
736
- }
737
693
  const maxCount = q.maxCount ? Number(q.maxCount) : 50;
738
- const listed = await magit.listCatalogPackages({
694
+ const versions = await magit.listPackages({
739
695
  kind,
740
696
  id,
741
697
  maxCount: Number.isFinite(maxCount) ? maxCount : 50,
742
698
  });
743
- const versions = listed.items.map((v) => {
744
- const parsed = parsePackageMessage(v.message);
745
- return {
746
- commit: v.version,
747
- agentId: ownerAgentId || id,
748
- checksum: v.checksum,
749
- message: v.message,
750
- createdAt: v.createdAt,
751
- source: "save-version",
752
- packageKind: (parsed.kind ?? v.kind),
753
- packageId: parsed.id ?? v.id,
754
- mode: parsed.mode ?? v.mode,
755
- displayMessage: parsed.message || v.message,
756
- associations: v.associations,
757
- };
758
- });
759
699
  return {
760
700
  kind,
761
701
  id,
762
- agentId: ownerAgentId || id,
763
- versions,
764
- remote: listed.remote || magit.hasRemoteCatalog(),
765
- catalogOrg: PACKAGE_CATALOG_ORG,
766
- note: "Versions from Magit package catalog (packages/). Org is not package identity.",
702
+ // `commit` aliases `version` for existing HTTP callers written against
703
+ // the pre-cutover org-scoped history shape (e.g. Studio's
704
+ // PackVersionsPage.tsx keys/renders list rows by `.commit`). `version`
705
+ // is the FR-CPS-4/5 field name and the one new callers should use.
706
+ versions: versions.map((v) => ({ ...v, commit: v.version })),
707
+ note: "Versions from the central Magit package catalog.",
708
+ };
709
+ });
710
+ // FR-CPS-5 — fetch a package version's payload directly (§7 of the FR).
711
+ // Org header is ignored: catalog reads are org-free.
712
+ app.get("/api/metadata/packages/:kind/:id/versions/:version", async (req) => {
713
+ const magit = requireMagit(platform);
714
+ const kind = parseKind(req.params.kind);
715
+ const id = String(req.params.id ?? "").trim();
716
+ if (!id)
717
+ throw new ServiceError("VALIDATION", "id required", 400);
718
+ const version = String(req.params.version ?? "").trim();
719
+ if (!version)
720
+ throw new ServiceError("VALIDATION", "version required", 400);
721
+ const fetched = await magit.fetchPackage({ kind, id, version });
722
+ return {
723
+ kind,
724
+ id,
725
+ version,
726
+ checksum: fetched.checksum,
727
+ payload: fetched.payload,
728
+ associations: fetched.associations,
767
729
  };
768
730
  });
769
731
  app.post("/api/metadata/packages/pack", async (req) => {
@@ -788,11 +750,7 @@ export async function registerMetadataRoutes(app, platform) {
788
750
  if (!live) {
789
751
  throw new ServiceError("NOT_FOUND", `No installed pack for agent ${agentId}`, 404);
790
752
  }
791
- const mode = kind === "agent"
792
- ? body.mode === "narrow"
793
- ? "narrow"
794
- : "full"
795
- : "narrow";
753
+ const mode = kind === "agent" ? (body.mode === "narrow" ? "narrow" : "full") : undefined;
796
754
  const payload = buildPackagePayload(live, {
797
755
  kind,
798
756
  id,
@@ -807,74 +765,51 @@ export async function registerMetadataRoutes(app, platform) {
807
765
  const associations = kind === "agent" && mode
808
766
  ? releaseAssociations(live, mode, body.includeConnectorIds, body.includeServiceIds)
809
767
  : undefined;
810
- // Full agent pack: publish pin packages first, then agent with Magit pins.
811
- const actor = actorFromRequest(req);
812
- const pins = [];
768
+ const saved = await magit.packPackage({
769
+ kind,
770
+ id,
771
+ message,
772
+ pack: payload,
773
+ mode,
774
+ associations,
775
+ });
776
+ // Full agent pack also snapshots selected connector/service packages.
777
+ // `commit` aliases `version` for the same backward-compat reason as the
778
+ // versions-list route above.
813
779
  const bundled = [];
814
780
  if (kind === "agent" && mode === "full" && associations) {
815
781
  for (const connectorId of associations.connectorIds) {
816
- const slice = buildPackagePayload(live, {
817
- kind: "connector",
818
- id: connectorId,
819
- });
782
+ const slice = buildPackagePayload(live, { kind: "connector", id: connectorId });
820
783
  const ok = validateMetadataPack(slice);
821
784
  if (!ok.ok)
822
785
  continue;
823
- const b = await magit.packCatalogPackage({
786
+ const b = await magit.packPackage({
824
787
  kind: "connector",
825
788
  id: connectorId,
826
- message: packageVersionMessage("connector", connectorId, `bundled with agent ${id}: ${message}`),
789
+ message: `bundled with agent ${id}: ${message}`,
827
790
  pack: slice,
828
- mode: "narrow",
829
- actor,
830
- });
831
- pins.push({
832
- kind: "connector",
833
- id: connectorId,
834
- version: b.version,
835
- });
836
- bundled.push({
837
- kind: "connector",
838
- id: connectorId,
839
- commit: b.version,
840
- version: b.version,
841
791
  });
792
+ bundled.push({ kind: "connector", id: connectorId, version: b.version, commit: b.version });
842
793
  }
843
794
  for (const serviceId of associations.serviceIds) {
844
- const slice = buildPackagePayload(live, {
845
- kind: "service",
846
- id: serviceId,
847
- });
795
+ const slice = buildPackagePayload(live, { kind: "service", id: serviceId });
848
796
  const ok = validateMetadataPack(slice);
849
797
  if (!ok.ok)
850
798
  continue;
851
- const b = await magit.packCatalogPackage({
799
+ const b = await magit.packPackage({
852
800
  kind: "service",
853
801
  id: serviceId,
854
- message: packageVersionMessage("service", serviceId, `bundled with agent ${id}: ${message}`),
802
+ message: `bundled with agent ${id}: ${message}`,
855
803
  pack: slice,
856
- mode: "narrow",
857
- actor,
858
- });
859
- pins.push({ kind: "service", id: serviceId, version: b.version });
860
- bundled.push({
861
- kind: "service",
862
- id: serviceId,
863
- commit: b.version,
864
- version: b.version,
865
804
  });
805
+ bundled.push({ kind: "service", id: serviceId, version: b.version, commit: b.version });
866
806
  }
867
807
  }
868
- const saved = await magit.packCatalogPackage({
869
- kind,
870
- id,
871
- message: packageVersionMessage(kind, id, message, mode),
872
- pack: payload,
873
- mode: kind === "agent" ? mode : "narrow",
874
- associations,
875
- pins: pins.length ? pins : undefined,
876
- actor,
877
- });
808
+ const note = saved.published === false
809
+ ? "Pack wrote locally but was not published to the central store (published=false)."
810
+ : saved.published === true
811
+ ? "Pack published to the Magit typed package store."
812
+ : "Pack stored in the central Magit package catalog.";
878
813
  return {
879
814
  packed: true,
880
815
  kind,
@@ -883,13 +818,13 @@ export async function registerMetadataRoutes(app, platform) {
883
818
  mode: mode ?? null,
884
819
  associations,
885
820
  bundled,
886
- commit: saved.version,
887
821
  version: saved.version,
888
822
  checksum: saved.checksum,
889
823
  reused: saved.reused,
890
- remote: saved.remote || magit.hasRemoteCatalog(),
891
- catalogOrg: PACKAGE_CATALOG_ORG,
892
- note: "Packed into Magit package catalog (not live).",
824
+ ...(saved.published !== undefined ? { published: saved.published } : {}),
825
+ ...(saved.storeId ? { storeId: saved.storeId } : {}),
826
+ ...(saved.packageTypeId ? { packageTypeId: saved.packageTypeId } : {}),
827
+ note,
893
828
  };
894
829
  });
895
830
  app.post("/api/metadata/packages/restore", async (req) => {
@@ -921,13 +856,14 @@ export async function registerMetadataRoutes(app, platform) {
921
856
  throw new ServiceError("VALIDATION", "agentId required to restore connector/service into an agent pack", 400);
922
857
  }
923
858
  const sliceAgentId = catalogAgentId(kind, id, agentId);
924
- const loaded = await magit.fetchCatalogPackage({ kind, id, version }, sliceAgentId);
925
- let installPack = loaded.pack;
859
+ const fetched = await magit.fetchPackage({ kind, id, version });
860
+ const loadedPack = packagePayloadToPack(sliceAgentId, fetched.payload);
861
+ let installPack = loadedPack;
926
862
  // Connector/service restore merges slice into current live agent pack.
927
863
  if (kind === "connector" || kind === "service") {
928
864
  const live = packs[agentId] ?? emptyPackForRestore(agentId);
929
865
  if (kind === "connector") {
930
- const keepRefs = new Set((loaded.pack.sources ?? [])
866
+ const keepRefs = new Set((loadedPack.sources ?? [])
931
867
  .map((s) => s && typeof s === "object" && "connectorRef" in s
932
868
  ? String(s.connectorRef ?? "")
933
869
  : "")
@@ -941,19 +877,16 @@ export async function registerMetadataRoutes(app, platform) {
941
877
  installPack = {
942
878
  ...live,
943
879
  agentId,
944
- sources: [...otherSources, ...(loaded.pack.sources ?? [])],
880
+ sources: [...otherSources, ...(loadedPack.sources ?? [])],
945
881
  };
946
882
  }
947
883
  else {
948
884
  const svcId = id;
949
- const otherServices = (live.services ?? []).filter((s) => !(s &&
950
- typeof s === "object" &&
951
- "id" in s &&
952
- String(s.id) === svcId));
885
+ const otherServices = (live.services ?? []).filter((s) => !(s && typeof s === "object" && "id" in s && String(s.id) === svcId));
953
886
  installPack = {
954
887
  ...live,
955
888
  agentId,
956
- services: [...otherServices, ...(loaded.pack.services ?? [])],
889
+ services: [...otherServices, ...(loadedPack.services ?? [])],
957
890
  };
958
891
  }
959
892
  }
@@ -981,12 +914,10 @@ export async function registerMetadataRoutes(app, platform) {
981
914
  id,
982
915
  agentId,
983
916
  version,
917
+ checksum: fetched.checksum,
984
918
  targetOrgId: scope.orgId,
985
- checksum: loaded.checksum,
986
919
  result,
987
- remote: loaded.remote || magit.hasRemoteCatalog(),
988
- catalogOrg: PACKAGE_CATALOG_ORG,
989
- note: "Restored from Magit package catalog into this environment. Org is restore target only.",
920
+ note: "Restored from the central Magit package catalog into this environment. Org is the restore target only.",
990
921
  };
991
922
  });
992
923
  app.post("/api/metadata/packages/diff", async (req) => {
@@ -1010,12 +941,31 @@ export async function registerMetadataRoutes(app, platform) {
1010
941
  agentId = kind === "agent" ? id : body.agentId?.trim() || id;
1011
942
  }
1012
943
  const sliceAgentId = catalogAgentId(kind, id, agentId);
1013
- // version↔version: Magit catalog commits; installed vs version uses catalog org Mongo lens.
944
+ // "installed" sentinel live / installed pack slice for typed-store compare.
945
+ // Flat Mode B still maps installed → "live" commit/mongo side via MagitPackService.
1014
946
  const fromRef = from === "installed" ? "live" : from;
1015
947
  const toRef = to === "installed" ? "live" : to;
1016
- const diff = await magit.diff(PACKAGE_CATALOG_ORG, sliceAgentId, {
948
+ const needsInstalled = fromRef === "live" ||
949
+ toRef === "live" ||
950
+ from === "installed" ||
951
+ to === "installed";
952
+ let installedPack = null;
953
+ if (needsInstalled) {
954
+ const live = packs[agentId];
955
+ if (live) {
956
+ installedPack = buildPackagePayload(live, {
957
+ kind,
958
+ id,
959
+ mode: kind === "agent" ? "narrow" : undefined,
960
+ });
961
+ }
962
+ }
963
+ const diff = await magit.diffPackages(sliceAgentId, {
1017
964
  from: fromRef,
1018
965
  to: toRef,
966
+ kind,
967
+ id,
968
+ installedPack,
1019
969
  });
1020
970
  return {
1021
971
  ...diff,
@@ -1023,7 +973,6 @@ export async function registerMetadataRoutes(app, platform) {
1023
973
  id,
1024
974
  agentId,
1025
975
  catalogAgentId: sliceAgentId,
1026
- remote: magit.hasRemoteCatalog(),
1027
976
  note: "Compare package versions or version vs installed. Not env→env copy.",
1028
977
  };
1029
978
  });