xytara 1.4.0 → 1.5.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/README.md CHANGED
@@ -66,6 +66,15 @@ The economic artifact posture is also now more explicit across the default machi
66
66
 
67
67
  The same artifacts now also expose a normalized `default_path` object so the bundled economic center of gravity is visible as data instead of being inferred indirectly.
68
68
 
69
+ The package and service also expose a default transaction center surface so the out-of-the-box path is easier to inspect directly:
70
+
71
+ - default protocol lane: `mcp`
72
+ - default payment protocol: `x402`
73
+ - default settlement center: built-in chain settlement across the canonical bundled settlement modes
74
+ - default treasury landing posture: account treasury destination by settlement mode
75
+
76
+ That same default center is also reflected in direct helper paths for default MCP usage, so the default path can be previewed or quoted without repeating the full integration-selection story each time.
77
+
69
78
  ## Package Surface
70
79
 
71
80
  The SDK is broad, but it stays organized into a few repeatable families instead of one-off surfaces.
@@ -195,6 +204,14 @@ The promotion-readiness layer now makes that posture explicit as review data:
195
204
 
196
205
  That distinction matters as the registry grows.
197
206
 
207
+ The promotion-action preview layer now builds on top of that readiness data without introducing mutation:
208
+
209
+ - action previews stay read-only
210
+ - current posture and resulting posture are both visible
211
+ - requested action validity is explicit
212
+ - blockers and blocker categories remain inspectable as data
213
+ - the preview layer explains what would change before any future control-plane work exists
214
+
198
215
  There is also a small repo-local registry CLI for reviewer/operator use when working from a cloned `xytara` repository:
199
216
 
200
217
  - `node scripts/registry_cli.js validate-bundle --example protocol`
@@ -207,6 +224,9 @@ There is also a small repo-local registry CLI for reviewer/operator use when wor
207
224
  - `node scripts/registry_cli.js review-bundle-set`
208
225
  - `node scripts/registry_cli.js review-snapshot`
209
226
  - `node scripts/registry_cli.js promotion-readiness --integration partner.protocol.acme_mcp`
227
+ - `node scripts/registry_cli.js promotion-action-preview --integration partner.protocol.acme_mcp --action complete_certification`
228
+ - `node scripts/registry_cli.js promotion-action-set --integration partner.protocol.acme_mcp`
229
+ - `node scripts/registry_cli.js promotion-action-set-summary --source third_party_example --bundled false`
210
230
 
211
231
  ## Integration Selection
212
232
 
@@ -340,6 +360,9 @@ Primary service routes:
340
360
  - `GET /v1/integrations/settlement-modes`
341
361
  - `GET /v1/integrations/promotion-readiness`
342
362
  - `GET /v1/integrations/:integration_id/promotion-readiness`
363
+ - `GET /v1/integrations/promotion-actions`
364
+ - `GET /v1/integrations/:integration_id/promotion-actions`
365
+ - `POST /v1/integrations/promotion-actions/preview`
343
366
  - `POST /v1/integrations/review/submission-bundle`
344
367
  - `POST /v1/integrations/review/submission-bundle-set`
345
368
  - `POST /v1/integrations/review/registry-snapshot`
package/index.js CHANGED
@@ -32,11 +32,15 @@ const {
32
32
  summarizeIntegrationRegistrySnapshotReview,
33
33
  summarizeIntegrationPromotionReadiness,
34
34
  summarizeIntegrationPromotionWorkflow,
35
- summarizeIntegrationPromotionWorkflowList
35
+ summarizeIntegrationPromotionWorkflowList,
36
+ validatePromotionActionRequest,
37
+ summarizeIntegrationPromotionActionPreview,
38
+ summarizeIntegrationPromotionActionSet,
39
+ summarizeIntegrationPromotionActionSetList
36
40
  } = require("./integrations/registry");
37
41
 
38
42
  const COMMERCE_SDK_NAME = "xytara";
39
- const COMMERCE_SDK_VERSION = "1.4.0";
43
+ const COMMERCE_SDK_VERSION = "1.5.0";
40
44
  const COMMERCE_API_VERSION = "v1";
41
45
 
42
46
  function createClient(options) {
@@ -77,5 +81,9 @@ module.exports = {
77
81
  summarizeIntegrationPromotionReadiness,
78
82
  summarizeIntegrationPromotionWorkflow,
79
83
  summarizeIntegrationPromotionWorkflowList,
84
+ validatePromotionActionRequest,
85
+ summarizeIntegrationPromotionActionPreview,
86
+ summarizeIntegrationPromotionActionSet,
87
+ summarizeIntegrationPromotionActionSetList,
80
88
  validateAdapterImplementation
81
89
  };
@@ -681,6 +681,266 @@ function buildPromotionRecommendationSummary(readiness = {}) {
681
681
  };
682
682
  }
683
683
 
684
+ const PROMOTION_ACTION_DEFINITIONS = {
685
+ register_integration: {
686
+ action: "register_integration",
687
+ title: "Register Integration",
688
+ stage: "registration",
689
+ description: "Move an integration into an explicit staged registration posture."
690
+ },
691
+ complete_certification: {
692
+ action: "complete_certification",
693
+ title: "Complete Certification",
694
+ stage: "certification",
695
+ description: "Mark the integration as certified for the current public contract."
696
+ },
697
+ promote_maturity: {
698
+ action: "promote_maturity",
699
+ title: "Promote Maturity",
700
+ stage: "maturity",
701
+ description: "Align integration maturity with production-default rollout posture."
702
+ },
703
+ enable_default_selection: {
704
+ action: "enable_default_selection",
705
+ title: "Enable Default Selection",
706
+ stage: "selection",
707
+ description: "Allow the integration to participate in default selection instead of explicit-only use."
708
+ },
709
+ bundle_for_default_rollout: {
710
+ action: "bundle_for_default_rollout",
711
+ title: "Bundle For Default Rollout",
712
+ stage: "rollout",
713
+ description: "Mark the integration as bundled for production-default rollout."
714
+ },
715
+ maintain_production_default: {
716
+ action: "maintain_production_default",
717
+ title: "Maintain Production Default",
718
+ stage: "steady_state",
719
+ description: "Confirm the integration already satisfies production-default posture."
720
+ }
721
+ };
722
+
723
+ function getPromotionActionDefinition(action) {
724
+ const lookup = String(action || "").trim();
725
+ return PROMOTION_ACTION_DEFINITIONS[lookup] || null;
726
+ }
727
+
728
+ function clonePromotionSubject(summary = {}) {
729
+ return {
730
+ registration: clone(summary.registration || {}),
731
+ certification_state: summary.certification_state || null,
732
+ integration_maturity: summary.integration_maturity || null
733
+ };
734
+ }
735
+
736
+ function simulatePromotionActionSubject(summary = {}, action) {
737
+ const subject = clonePromotionSubject(summary);
738
+ switch (action) {
739
+ case "register_integration":
740
+ subject.registration.registration_state = "staging_registered";
741
+ if (subject.registration.default_selection_enabled !== true) {
742
+ subject.registration.default_selection_enabled = false;
743
+ }
744
+ if (subject.registration.requires_explicit_selection !== false) {
745
+ subject.registration.requires_explicit_selection = true;
746
+ }
747
+ break;
748
+ case "complete_certification":
749
+ subject.certification_state = "certified";
750
+ break;
751
+ case "promote_maturity":
752
+ subject.integration_maturity = "production_default";
753
+ break;
754
+ case "enable_default_selection":
755
+ subject.registration.default_selection_enabled = true;
756
+ subject.registration.requires_explicit_selection = false;
757
+ break;
758
+ case "bundle_for_default_rollout":
759
+ subject.registration.bundled = true;
760
+ break;
761
+ case "maintain_production_default":
762
+ break;
763
+ default:
764
+ break;
765
+ }
766
+ return subject;
767
+ }
768
+
769
+ function buildPromotionActionResultingReadiness(summary = {}, subject = {}) {
770
+ return buildPromotionReadinessSummary({
771
+ registration: subject.registration,
772
+ certification: {
773
+ certification_state: subject.certification_state || summary.certification_state || null
774
+ },
775
+ integration: {
776
+ integration_maturity: subject.integration_maturity || summary.integration_maturity || null
777
+ }
778
+ });
779
+ }
780
+
781
+ function buildPromotionActionStateChanges(current = {}, simulated = {}) {
782
+ const changes = [];
783
+ const currentRegistration = current.registration || {};
784
+ const simulatedRegistration = simulated.registration || {};
785
+ const fieldPairs = [
786
+ ["registration.registration_state", currentRegistration.registration_state, simulatedRegistration.registration_state],
787
+ ["registration.default_selection_enabled", currentRegistration.default_selection_enabled, simulatedRegistration.default_selection_enabled],
788
+ ["registration.requires_explicit_selection", currentRegistration.requires_explicit_selection, simulatedRegistration.requires_explicit_selection],
789
+ ["registration.bundled", currentRegistration.bundled, simulatedRegistration.bundled],
790
+ ["certification_state", current.certification_state, simulated.certification_state],
791
+ ["integration_maturity", current.integration_maturity, simulated.integration_maturity]
792
+ ];
793
+ fieldPairs.forEach(([field, fromValue, toValue]) => {
794
+ if (fromValue !== toValue) {
795
+ changes.push({
796
+ field,
797
+ from: fromValue === undefined ? null : fromValue,
798
+ to: toValue === undefined ? null : toValue
799
+ });
800
+ }
801
+ });
802
+ return changes;
803
+ }
804
+
805
+ function validatePromotionActionRequest(request = {}) {
806
+ const entry = request && typeof request === "object" && !Array.isArray(request) ? request : {};
807
+ const errors = [];
808
+ const integrationId = String(entry.integration_id || "").trim();
809
+ const action = String(entry.action || "").trim();
810
+ if (!integrationId) {
811
+ errors.push("promotion_action_request.integration_id is required");
812
+ }
813
+ if (!action) {
814
+ errors.push("promotion_action_request.action is required");
815
+ } else if (!getPromotionActionDefinition(action)) {
816
+ errors.push("promotion_action_request.action must be a supported promotion action");
817
+ }
818
+ return {
819
+ ok: errors.length === 0,
820
+ errors,
821
+ request: {
822
+ integration_id: integrationId || null,
823
+ action: action || null
824
+ }
825
+ };
826
+ }
827
+
828
+ function summarizeIntegrationPromotionActionPreview(request = {}) {
829
+ const validation = validatePromotionActionRequest(request);
830
+ if (!validation.ok) {
831
+ return {
832
+ ok: false,
833
+ reason: "invalid_promotion_action_request",
834
+ errors: validation.errors
835
+ };
836
+ }
837
+ const workflow = summarizeIntegrationPromotionWorkflow(validation.request.integration_id);
838
+ if (!workflow.ok) {
839
+ return workflow;
840
+ }
841
+
842
+ const action = validation.request.action;
843
+ const definition = getPromotionActionDefinition(action);
844
+ const currentSubject = clonePromotionSubject(workflow);
845
+ const simulatedSubject = simulatePromotionActionSubject(workflow, action);
846
+ const resultingReadiness = buildPromotionActionResultingReadiness(workflow, simulatedSubject);
847
+ const stateChanges = buildPromotionActionStateChanges(currentSubject, simulatedSubject);
848
+ const currentNextAction = workflow.next_transition && workflow.next_transition.action
849
+ ? workflow.next_transition.action
850
+ : null;
851
+ const currentLaterActions = Array.isArray(workflow.next_transition && workflow.next_transition.later_actions)
852
+ ? workflow.next_transition.later_actions
853
+ : [];
854
+ const validNow = currentNextAction === action || currentLaterActions.includes(action);
855
+ const invalidReasons = [];
856
+ if (!validNow) {
857
+ invalidReasons.push(action === "maintain_production_default"
858
+ ? "integration_is_not_yet_production_default_ready"
859
+ : "action_is_not_currently_recommended_from_present_posture");
860
+ }
861
+
862
+ return {
863
+ ok: true,
864
+ integration_id: workflow.integration_id,
865
+ display_name: workflow.display_name,
866
+ adapter_class: workflow.adapter_class,
867
+ source: workflow.source,
868
+ request: clone(validation.request),
869
+ action: clone(definition),
870
+ current_posture: {
871
+ registration_state: workflow.registration.registration_state || null,
872
+ certification_state: workflow.certification_state || null,
873
+ integration_maturity: workflow.integration_maturity || null,
874
+ promotion_readiness: clone(workflow.promotion_readiness || {})
875
+ },
876
+ valid_now: validNow,
877
+ is_recommended_next: currentNextAction === action,
878
+ invalid_reasons: invalidReasons,
879
+ requirements: currentNextAction === action
880
+ ? clone(workflow.next_transition.requirements || [])
881
+ : clone(buildNextTransitionSummary(resultingReadiness).requirements || []),
882
+ blockers: clone(workflow.promotion_readiness.blockers || []),
883
+ blocker_categories: clone(workflow.blocker_categories || []),
884
+ resulting_posture: {
885
+ registration_state: simulatedSubject.registration.registration_state || null,
886
+ certification_state: simulatedSubject.certification_state || null,
887
+ integration_maturity: simulatedSubject.integration_maturity || null,
888
+ promotion_readiness: clone(resultingReadiness)
889
+ },
890
+ state_changes: stateChanges,
891
+ current_transition: clone(workflow.next_transition || {}),
892
+ resulting_transition: buildNextTransitionSummary(resultingReadiness)
893
+ };
894
+ }
895
+
896
+ function summarizeIntegrationPromotionActionSet(integrationOrId) {
897
+ const workflow = summarizeIntegrationPromotionWorkflow(integrationOrId);
898
+ if (!workflow.ok) {
899
+ return workflow;
900
+ }
901
+ const actionOrder = [
902
+ workflow.next_transition && workflow.next_transition.action ? workflow.next_transition.action : null,
903
+ ...(Array.isArray(workflow.next_transition && workflow.next_transition.later_actions)
904
+ ? workflow.next_transition.later_actions
905
+ : []),
906
+ "maintain_production_default"
907
+ ].filter(Boolean);
908
+ const actions = sortStrings(actionOrder).map((action) => summarizeIntegrationPromotionActionPreview({
909
+ integration_id: workflow.integration_id,
910
+ action
911
+ }));
912
+ return {
913
+ ...workflow,
914
+ action_count: actions.length,
915
+ valid_now_count: actions.filter((entry) => entry.valid_now === true).length,
916
+ actions
917
+ };
918
+ }
919
+
920
+ function summarizeIntegrationPromotionActionSetList(filters = {}) {
921
+ const integrations = listIntegrations(filters).map((integration) => summarizeIntegrationPromotionActionSet(integration));
922
+ return {
923
+ ok: true,
924
+ integration_count: integrations.length,
925
+ valid_now_count: integrations.reduce((total, entry) => total + Number(entry.valid_now_count || 0), 0),
926
+ recommended_actions: summarizeCounts(
927
+ integrations
928
+ .map((entry) => entry.next_transition && entry.next_transition.action)
929
+ .filter(Boolean),
930
+ "action"
931
+ ),
932
+ valid_actions: summarizeCounts(
933
+ integrations
934
+ .flatMap((entry) => Array.isArray(entry.actions) ? entry.actions : [])
935
+ .filter((entry) => entry.valid_now === true)
936
+ .map((entry) => entry.request && entry.request.action)
937
+ .filter(Boolean),
938
+ "action"
939
+ ),
940
+ integrations
941
+ };
942
+ }
943
+
684
944
  function buildPromotionActionQueues(integrations = []) {
685
945
  const rows = Array.isArray(integrations) ? integrations.filter((entry) => entry && entry.next_transition) : [];
686
946
  const groups = new Map();
@@ -1631,6 +1891,10 @@ module.exports = {
1631
1891
  summarizeIntegrationPromotionReadiness,
1632
1892
  summarizeIntegrationPromotionWorkflow,
1633
1893
  summarizeIntegrationPromotionWorkflowList,
1894
+ validatePromotionActionRequest,
1895
+ summarizeIntegrationPromotionActionPreview,
1896
+ summarizeIntegrationPromotionActionSet,
1897
+ summarizeIntegrationPromotionActionSetList,
1634
1898
  createRegisteredIntegrationFromManifest,
1635
1899
  buildIntegrationRegistrationView,
1636
1900
  buildIntegrationView
@@ -2,6 +2,89 @@
2
2
 
3
3
  const { catalog, findTask, findWorkflow } = require("../fixtures/catalog");
4
4
 
5
+ function buildDefaultTransactionCenter() {
6
+ const settlementProfiles = Array.isArray(catalog.settlement_profiles) ? catalog.settlement_profiles : [];
7
+ const defaultSettlementProfile = settlementProfiles[0] || null;
8
+ const settlementModes = settlementProfiles
9
+ .map((profile) => profile && profile.mode)
10
+ .filter(Boolean);
11
+ return {
12
+ ok: true,
13
+ brand: "xytara",
14
+ product: "default transaction center",
15
+ payment_scheme: catalog.payment_scheme,
16
+ default_protocol: {
17
+ protocol: "mcp",
18
+ integration_id: "builtin.protocol.mcp",
19
+ task_ref: "adapter.mcp.invoke",
20
+ workflow_refs: ["a2c.tooling.flow"],
21
+ selection_reason: "production_default_protocol_lane"
22
+ },
23
+ default_payment: {
24
+ protocol: "x402",
25
+ integration_id: "builtin.payment.x402",
26
+ payment_scheme: catalog.payment_scheme,
27
+ supported_settlement_modes: settlementModes,
28
+ selection_reason: "production_default_payment_lane"
29
+ },
30
+ default_settlement: {
31
+ integration_id: "builtin.settlement.chain",
32
+ settlement_mode: defaultSettlementProfile && defaultSettlementProfile.mode ? defaultSettlementProfile.mode : null,
33
+ adapter: defaultSettlementProfile && defaultSettlementProfile.adapter ? defaultSettlementProfile.adapter : null,
34
+ asset: defaultSettlementProfile && defaultSettlementProfile.asset ? defaultSettlementProfile.asset : null,
35
+ payee_agent_id: defaultSettlementProfile && defaultSettlementProfile.payee_agent_id ? defaultSettlementProfile.payee_agent_id : null,
36
+ payee_label: defaultSettlementProfile && defaultSettlementProfile.payee_label ? defaultSettlementProfile.payee_label : null,
37
+ supported_modes: settlementModes,
38
+ profile_count: settlementProfiles.length
39
+ },
40
+ default_treasury: {
41
+ destination_kind: "account_treasury",
42
+ destination_template: "treasury_{account_id}",
43
+ settlement_mode: defaultSettlementProfile && defaultSettlementProfile.mode ? defaultSettlementProfile.mode : null,
44
+ payee_agent_id: defaultSettlementProfile && defaultSettlementProfile.payee_agent_id ? defaultSettlementProfile.payee_agent_id : null,
45
+ payee_label: defaultSettlementProfile && defaultSettlementProfile.payee_label ? defaultSettlementProfile.payee_label : null
46
+ },
47
+ suggested_paths: [
48
+ {
49
+ path_id: "default_mcp_x402_path",
50
+ path_kind: "first_party_default",
51
+ protocol: "mcp",
52
+ payment_protocol: "x402",
53
+ settlement_mode: defaultSettlementProfile && defaultSettlementProfile.mode ? defaultSettlementProfile.mode : null,
54
+ task_ref: "adapter.mcp.invoke",
55
+ integration_ids: ["builtin.protocol.mcp", "builtin.payment.x402", "builtin.settlement.chain"]
56
+ },
57
+ {
58
+ path_id: "default_a2c_tooling_flow",
59
+ path_kind: "first_party_default",
60
+ protocol: "mcp",
61
+ payment_protocol: "x402",
62
+ settlement_mode: defaultSettlementProfile && defaultSettlementProfile.mode ? defaultSettlementProfile.mode : null,
63
+ workflow_ref: "a2c.tooling.flow",
64
+ integration_ids: ["builtin.protocol.mcp", "builtin.payment.x402", "builtin.settlement.chain"]
65
+ }
66
+ ]
67
+ };
68
+ }
69
+
70
+ function summarizeDefaultTransactionCenter() {
71
+ const center = buildDefaultTransactionCenter();
72
+ return {
73
+ ok: true,
74
+ brand: center.brand,
75
+ product: center.product,
76
+ payment_scheme: center.payment_scheme,
77
+ default_protocol: center.default_protocol.protocol,
78
+ default_payment_protocol: center.default_payment.protocol,
79
+ default_settlement_mode: center.default_settlement.settlement_mode,
80
+ default_treasury_kind: center.default_treasury.destination_kind,
81
+ settlement_mode_count: Array.isArray(center.default_settlement.supported_modes) ? center.default_settlement.supported_modes.length : 0,
82
+ settlement_modes: center.default_settlement.supported_modes,
83
+ suggested_path_count: Array.isArray(center.suggested_paths) ? center.suggested_paths.length : 0,
84
+ suggested_paths: center.suggested_paths
85
+ };
86
+ }
87
+
5
88
  function buildCatalogResponse() {
6
89
  return {
7
90
  ok: true,
@@ -133,9 +216,11 @@ function getWorkflowDetail(ref) {
133
216
 
134
217
  module.exports = {
135
218
  buildCatalogResponse,
219
+ buildDefaultTransactionCenter,
136
220
  getCatalog,
137
221
  getTaskDetail,
138
222
  getWorkflowDetail,
139
223
  getWorkflowList,
140
- summarizeCatalog
224
+ summarizeCatalog,
225
+ summarizeDefaultTransactionCenter
141
226
  };
@@ -866,6 +866,34 @@ function summarizeCatalogPayload(payload) {
866
866
  };
867
867
  }
868
868
 
869
+ function summarizeDefaultTransactionCenterPayload(payload) {
870
+ const center = payload && typeof payload === "object" ? payload : {};
871
+ return {
872
+ ok: center.ok === true,
873
+ brand: center.brand || null,
874
+ product: center.product || null,
875
+ default_protocol: center.default_protocol && center.default_protocol.protocol
876
+ ? center.default_protocol.protocol
877
+ : center.default_protocol || null,
878
+ default_payment_protocol: center.default_payment && center.default_payment.protocol
879
+ ? center.default_payment.protocol
880
+ : center.default_payment_protocol || null,
881
+ default_settlement_mode: center.default_settlement && center.default_settlement.settlement_mode
882
+ ? center.default_settlement.settlement_mode
883
+ : center.default_settlement_mode || null,
884
+ default_treasury_kind: center.default_treasury && center.default_treasury.destination_kind
885
+ ? center.default_treasury.destination_kind
886
+ : center.default_treasury_kind || null,
887
+ settlement_mode_count: Array.isArray(center.default_settlement && center.default_settlement.supported_modes)
888
+ ? center.default_settlement.supported_modes.length
889
+ : Number(center.settlement_mode_count || 0),
890
+ suggested_path_count: Array.isArray(center.suggested_paths)
891
+ ? center.suggested_paths.length
892
+ : Number(center.suggested_path_count || 0),
893
+ suggested_paths: Array.isArray(center.suggested_paths) ? center.suggested_paths : []
894
+ };
895
+ }
896
+
869
897
  function buildCatalogSummarySource(client) {
870
898
  const baseCatalog = client && client.catalogCache && typeof client.catalogCache === "object"
871
899
  ? client.catalogCache
@@ -1601,6 +1629,45 @@ class CommerceClient {
1601
1629
  return result && result.data && Array.isArray(result.data.settlement_modes) ? result.data.settlement_modes : [];
1602
1630
  }
1603
1631
 
1632
+ async getIntegrationPromotionReadiness(integrationId) {
1633
+ const result = await this.getJson(`/v1/integrations/${encodeURIComponent(integrationId)}/promotion-readiness`);
1634
+ return result && result.data ? result.data : { ok: false, reason: "integration_not_found" };
1635
+ }
1636
+
1637
+ async listIntegrationPromotionReadiness(filters) {
1638
+ const suffix = buildQueryString(filters || {});
1639
+ const result = await this.getJson(`/v1/integrations/promotion-readiness${suffix}`);
1640
+ return result && result.data && Array.isArray(result.data.integrations) ? result.data.integrations : [];
1641
+ }
1642
+
1643
+ async getIntegrationPromotionWorkflow(integrationId) {
1644
+ const result = await this.getJson(`/v1/integrations/${encodeURIComponent(integrationId)}/promotion-workflow`);
1645
+ return result && result.data ? result.data : { ok: false, reason: "integration_not_found" };
1646
+ }
1647
+
1648
+ async listIntegrationPromotionWorkflows(filters) {
1649
+ const suffix = buildQueryString(filters || {});
1650
+ const result = await this.getJson(`/v1/integrations/promotion-workflow${suffix}`);
1651
+ return result && result.data ? result.data : { ok: true, integration_count: 0, integrations: [] };
1652
+ }
1653
+
1654
+ async getIntegrationPromotionActionSet(integrationId) {
1655
+ const result = await this.getJson(`/v1/integrations/${encodeURIComponent(integrationId)}/promotion-actions`);
1656
+ return result && result.data ? result.data : { ok: false, reason: "integration_not_found" };
1657
+ }
1658
+
1659
+ async listIntegrationPromotionActionSets(filters) {
1660
+ const suffix = buildQueryString(filters || {});
1661
+ const result = await this.getJson(`/v1/integrations/promotion-actions${suffix}`);
1662
+ return result && result.data ? result.data : { ok: true, integration_count: 0, integrations: [] };
1663
+ }
1664
+
1665
+ async previewIntegrationPromotionAction(request) {
1666
+ const payload = request && typeof request === "object" && !Array.isArray(request) ? request : {};
1667
+ const result = await this.postJson("/v1/integrations/promotion-actions/preview", {}, payload);
1668
+ return result && result.data ? result.data : { ok: false, reason: "invalid_promotion_action_request" };
1669
+ }
1670
+
1604
1671
  async getTaskExecutionModeSummaries(forceRefresh) {
1605
1672
  const tasks = await this.listTasks(forceRefresh);
1606
1673
  return summarizeFacetCounts(
@@ -2259,6 +2326,23 @@ class CommerceClient {
2259
2326
  return summarizeSettlementPayees(profiles);
2260
2327
  }
2261
2328
 
2329
+ async getDefaultTransactionCenter(forceRefresh) {
2330
+ if (!forceRefresh && this.catalogSummaryCache && this.catalogSummaryCache.defaultTransactionCenter) {
2331
+ return this.catalogSummaryCache.defaultTransactionCenter;
2332
+ }
2333
+ const result = await this.getJson("/v1/transaction-center");
2334
+ if (!forceRefresh) {
2335
+ this.catalogSummaryCache = this.catalogSummaryCache || {};
2336
+ this.catalogSummaryCache.defaultTransactionCenter = result.data;
2337
+ }
2338
+ return result.data;
2339
+ }
2340
+
2341
+ async getDefaultTransactionCenterSummary(forceRefresh) {
2342
+ const center = await this.getDefaultTransactionCenter(forceRefresh);
2343
+ return this.summarizeDefaultTransactionCenter(center);
2344
+ }
2345
+
2262
2346
  async listSettlementPayees(forceRefresh) {
2263
2347
  const summary = await this.getSettlementPayeeSummaries(forceRefresh);
2264
2348
  return extractSummaryValues(summary, "settlement_payees", "payee_agent_id");
@@ -3341,6 +3425,81 @@ class CommerceClient {
3341
3425
  return this.summarizeCommandResult(result);
3342
3426
  }
3343
3427
 
3428
+ async previewDefaultMcpToolQuote(toolName, args, options) {
3429
+ const opts = options || {};
3430
+ return this.previewTaskSetQuote([
3431
+ {
3432
+ task_ref: "adapter.mcp.invoke",
3433
+ body: {
3434
+ tool_name: String(toolName || "").trim(),
3435
+ arguments: args && typeof args === "object" && !Array.isArray(args) ? args : {}
3436
+ }
3437
+ }
3438
+ ], {
3439
+ ...opts,
3440
+ command: opts.command || `default.mcp.preview:${String(toolName || "").trim() || "tool"}`,
3441
+ protocol: opts.protocol || "mcp",
3442
+ paymentProtocol: opts.paymentProtocol || "x402",
3443
+ integrationId: opts.integrationId || "builtin.protocol.mcp",
3444
+ integrationIds: Array.isArray(opts.integrationIds) && opts.integrationIds.length > 0
3445
+ ? opts.integrationIds
3446
+ : ["builtin.protocol.mcp", "builtin.payment.x402", "builtin.settlement.chain"],
3447
+ settlementMode: opts.settlementMode || "evm_payment"
3448
+ });
3449
+ }
3450
+
3451
+ async previewDefaultMcpToolQuoteSummary(toolName, args, options) {
3452
+ const preview = await this.previewDefaultMcpToolQuote(toolName, args, options);
3453
+ return this.summarizeQuotePreview(preview);
3454
+ }
3455
+
3456
+ async createDefaultMcpToolQuote(toolName, args, options) {
3457
+ const opts = options || {};
3458
+ return this.createTaskSetQuote([
3459
+ {
3460
+ task_ref: "adapter.mcp.invoke",
3461
+ body: {
3462
+ tool_name: String(toolName || "").trim(),
3463
+ arguments: args && typeof args === "object" && !Array.isArray(args) ? args : {}
3464
+ }
3465
+ }
3466
+ ], {
3467
+ ...opts,
3468
+ command: opts.command || `default.mcp.quote:${String(toolName || "").trim() || "tool"}`,
3469
+ protocol: opts.protocol || "mcp",
3470
+ paymentProtocol: opts.paymentProtocol || "x402",
3471
+ integrationId: opts.integrationId || "builtin.protocol.mcp",
3472
+ integrationIds: Array.isArray(opts.integrationIds) && opts.integrationIds.length > 0
3473
+ ? opts.integrationIds
3474
+ : ["builtin.protocol.mcp", "builtin.payment.x402", "builtin.settlement.chain"],
3475
+ settlementMode: opts.settlementMode || "evm_payment"
3476
+ });
3477
+ }
3478
+
3479
+ async createDefaultMcpToolQuoteSummary(toolName, args, options) {
3480
+ const quote = await this.createDefaultMcpToolQuote(toolName, args, options);
3481
+ return this.summarizeQuote(quote);
3482
+ }
3483
+
3484
+ async invokeDefaultMcpTool(toolName, args, options) {
3485
+ const opts = options || {};
3486
+ return this.invokeMcpTool(toolName, args, {
3487
+ ...opts,
3488
+ protocol: opts.protocol || "mcp",
3489
+ paymentProtocol: opts.paymentProtocol || "x402",
3490
+ integrationId: opts.integrationId || "builtin.protocol.mcp",
3491
+ integrationIds: Array.isArray(opts.integrationIds) && opts.integrationIds.length > 0
3492
+ ? opts.integrationIds
3493
+ : ["builtin.protocol.mcp", "builtin.payment.x402", "builtin.settlement.chain"],
3494
+ settlementMode: opts.settlementMode || "evm_payment"
3495
+ });
3496
+ }
3497
+
3498
+ async invokeDefaultMcpToolSummary(toolName, args, options) {
3499
+ const result = await this.invokeDefaultMcpTool(toolName, args, options);
3500
+ return this.summarizeCommandResult(result);
3501
+ }
3502
+
3344
3503
  async runNamedTaskRoute(path, payload) {
3345
3504
  if (!this.apiKey || !this.walletId || !this.walletSecret) {
3346
3505
  throw new Error("named task routes require apiKey, walletId, and walletSecret");
@@ -4820,6 +4979,10 @@ class CommerceClient {
4820
4979
  return summarizeCatalogPayload(payload);
4821
4980
  }
4822
4981
 
4982
+ summarizeDefaultTransactionCenter(payload) {
4983
+ return summarizeDefaultTransactionCenterPayload(payload);
4984
+ }
4985
+
4823
4986
  summarizeTask(task) {
4824
4987
  return summarizeCatalogTask(task);
4825
4988
  }
@@ -5571,6 +5734,7 @@ module.exports = {
5571
5734
  extractTrailingIdFromUrl,
5572
5735
  summarizeQuotePayload,
5573
5736
  summarizeQuotePreviewPayload,
5737
+ summarizeDefaultTransactionCenterPayload,
5574
5738
  summarizeActivitySnapshotPayload,
5575
5739
  summarizeOpenIssuesPayload,
5576
5740
  summarizeExecutionExceptionsPayload,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xytara",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "Machine commerce SDK for discovery, quoting, execution, lifecycle inspection, and adapters.",
5
5
  "main": "index.js",
6
6
  "type": "commonjs",
package/server.js CHANGED
@@ -4,11 +4,13 @@ const http = require("http");
4
4
  const { URL } = require("url");
5
5
  const { readJsonBody, sendJson } = require("./lib/http_transport");
6
6
  const {
7
+ buildDefaultTransactionCenter,
7
8
  getCatalog,
8
9
  getTaskDetail,
9
10
  getWorkflowDetail,
10
11
  getWorkflowList,
11
- summarizeCatalog
12
+ summarizeCatalog,
13
+ summarizeDefaultTransactionCenter
12
14
  } = require("./lib/catalog_contract");
13
15
  const {
14
16
  createCommandResult,
@@ -55,6 +57,9 @@ const {
55
57
  summarizeIntegrationPromotionReadiness,
56
58
  summarizeIntegrationPromotionWorkflow,
57
59
  summarizeIntegrationPromotionWorkflowList,
60
+ summarizeIntegrationPromotionActionPreview,
61
+ summarizeIntegrationPromotionActionSet,
62
+ summarizeIntegrationPromotionActionSetList,
58
63
  summarizeIntegrationRegistrySnapshotReview,
59
64
  summarizeIntegrationSubmissionBundleReview,
60
65
  summarizeIntegrationSubmissionBundleSetReview,
@@ -373,6 +378,16 @@ async function routeRequest(req, res) {
373
378
  return;
374
379
  }
375
380
 
381
+ if (req.method === "GET" && url.pathname === "/v1/transaction-center") {
382
+ sendJson(res, 200, buildDefaultTransactionCenter());
383
+ return;
384
+ }
385
+
386
+ if (req.method === "GET" && url.pathname === "/v1/transaction-center/summary") {
387
+ sendJson(res, 200, summarizeDefaultTransactionCenter());
388
+ return;
389
+ }
390
+
376
391
  if (req.method === "GET" && url.pathname === "/v1/catalog/task") {
377
392
  const response = buildTaskDetailResponse(getTaskDetail(url.searchParams.get("ref")));
378
393
  sendJson(res, response.status, response.payload);
@@ -508,6 +523,33 @@ async function routeRequest(req, res) {
508
523
  return;
509
524
  }
510
525
 
526
+ if (req.method === "GET" && url.pathname === "/v1/integrations/promotion-actions") {
527
+ const response = buildIntegrationListResponse({
528
+ ...summarizeIntegrationPromotionActionSetList({
529
+ adapter_class: url.searchParams.get("class"),
530
+ protocol: url.searchParams.get("protocol"),
531
+ settlement_mode: url.searchParams.get("settlement_mode"),
532
+ capability: url.searchParams.get("capability"),
533
+ task_ref: url.searchParams.get("task_ref"),
534
+ source: url.searchParams.get("source"),
535
+ certification_state: url.searchParams.get("certification_state"),
536
+ integration_maturity: url.searchParams.get("integration_maturity"),
537
+ bundled: url.searchParams.get("bundled")
538
+ })
539
+ });
540
+ sendJson(res, response.status, response.payload);
541
+ return;
542
+ }
543
+
544
+ if (req.method === "POST" && url.pathname === "/v1/integrations/promotion-actions/preview") {
545
+ const body = await readJsonBody(req);
546
+ const response = buildIntegrationListResponse(
547
+ summarizeIntegrationPromotionActionPreview(body)
548
+ );
549
+ sendJson(res, response.status, response.payload);
550
+ return;
551
+ }
552
+
511
553
  if (req.method === "GET" && url.pathname.startsWith("/v1/integrations/") && url.pathname.endsWith("/promotion-readiness")) {
512
554
  const integrationId = getDecodedSuffixId(
513
555
  url.pathname.slice(0, -"/promotion-readiness".length),
@@ -520,6 +562,18 @@ async function routeRequest(req, res) {
520
562
  return;
521
563
  }
522
564
 
565
+ if (req.method === "GET" && url.pathname.startsWith("/v1/integrations/") && url.pathname.endsWith("/promotion-actions")) {
566
+ const integrationId = getDecodedSuffixId(
567
+ url.pathname.slice(0, -"/promotion-actions".length),
568
+ "/v1/integrations/"
569
+ );
570
+ const response = buildIntegrationListResponse(
571
+ summarizeIntegrationPromotionActionSet(integrationId)
572
+ );
573
+ sendJson(res, response.status || 200, response.payload || response);
574
+ return;
575
+ }
576
+
523
577
  if (req.method === "GET" && url.pathname.startsWith("/v1/integrations/") && url.pathname.endsWith("/promotion-workflow")) {
524
578
  const integrationId = getDecodedSuffixId(
525
579
  url.pathname.slice(0, -"/promotion-workflow".length),