@agentcentral/cli 0.1.1 → 0.1.3

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 (3) hide show
  1. package/README.md +33 -3
  2. package/dist/index.js +2964 -232
  3. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -17,7 +17,7 @@ var CliError = class extends Error {
17
17
  };
18
18
 
19
19
  // src/constants.ts
20
- var CLI_VERSION = "0.1.1";
20
+ var CLI_VERSION = "0.1.2";
21
21
  var DEFAULT_MCP_ENDPOINT = "https://mcp.agentcentral.to/mcp";
22
22
  var ENV_API_KEY = "AGENT_CENTRAL_API_KEY";
23
23
  var ENV_API_KEY_LEGACY = "AGENTCENTRAL_API_KEY";
@@ -34,13 +34,14 @@ var API_KEY_PREFIX = "ac_live_";
34
34
 
35
35
  // src/config.ts
36
36
  import {
37
- chmodSync,
38
37
  closeSync,
39
38
  existsSync,
40
39
  fstatSync,
41
40
  mkdirSync,
42
41
  openSync,
43
42
  readFileSync,
43
+ renameSync,
44
+ unlinkSync,
44
45
  writeFileSync
45
46
  } from "fs";
46
47
  import { homedir } from "os";
@@ -107,9 +108,23 @@ function loadConfig(env = process.env) {
107
108
  function saveConfig(config, env = process.env) {
108
109
  const path = configPath(env);
109
110
  const dir = dirname(path);
111
+ const tmp = `${path}.${process.pid}.tmp`;
110
112
  mkdirSync(dir, { recursive: true, mode: 448 });
111
- writeFileSync(path, JSON.stringify(config, null, 2), { mode: 384 });
112
- chmodSync(path, 384);
113
+ const data = JSON.stringify(config, null, 2);
114
+ try {
115
+ writeFileSync(tmp, data, { mode: 384, flag: "wx" });
116
+ renameSync(tmp, path);
117
+ } catch (error) {
118
+ try {
119
+ unlinkSync(tmp);
120
+ } catch {
121
+ }
122
+ throw new CliError(
123
+ 1 /* GeneralFailure */,
124
+ `failed to write config ${path}`,
125
+ error instanceof Error ? error.message : String(error)
126
+ );
127
+ }
113
128
  }
114
129
  function upsertProfile(config, profile) {
115
130
  const exists = config.profiles.some((p) => p.name === profile.name);
@@ -243,7 +258,128 @@ async function resolveAuth(input) {
243
258
  };
244
259
  }
245
260
 
261
+ // src/exit-codes.ts
262
+ var RPC_INVALID_PARAMS = -32602;
263
+ var DETAIL_MAX_LENGTH = 180;
264
+ var PERMISSION_PATTERN = /no_amazon|not connected|expired|suspended|revoked|past_due|trial expired|permission|not authorized|scope/i;
265
+ var VALIDATION_PATTERN = /invalid|validation|must be|required/i;
266
+ function writeEnvelopeFrom(result) {
267
+ const structured = result.structuredContent;
268
+ if (!structured) {
269
+ return void 0;
270
+ }
271
+ const hasWriteShape = "mode" in structured || "status" in structured || "requested_count" in structured;
272
+ if (!hasWriteShape) {
273
+ return void 0;
274
+ }
275
+ return structured;
276
+ }
277
+ function toolClassification(def) {
278
+ const hint = def.annotations;
279
+ const annotationWrite = hint?.destructiveHint === true || hint?.readOnlyHint === false;
280
+ const properties = def.inputSchema.properties;
281
+ const props = properties && typeof properties === "object" ? properties : {};
282
+ const schemaWrite = "confirm" in props && "idempotency_key" in props;
283
+ const isWrite = annotationWrite || schemaWrite;
284
+ return {
285
+ isWrite,
286
+ supportsPreview: isWrite
287
+ };
288
+ }
289
+ function classifyToolText(text) {
290
+ if (PERMISSION_PATTERN.test(text)) {
291
+ return 4 /* PermissionDenied */;
292
+ }
293
+ if (VALIDATION_PATTERN.test(text)) {
294
+ return 5 /* ValidationFailed */;
295
+ }
296
+ return void 0;
297
+ }
298
+ function joinContentText(result) {
299
+ return result.content.map((block) => typeof block.text === "string" ? block.text : "").filter((text) => text.length > 0).join(" ").trim();
300
+ }
301
+ function truncateDetail(text) {
302
+ if (text.length <= DETAIL_MAX_LENGTH) {
303
+ return text;
304
+ }
305
+ return `${text.slice(0, DETAIL_MAX_LENGTH)}\u2026`;
306
+ }
307
+ function classifyWriteStatus(status) {
308
+ switch (status) {
309
+ case "validation_error":
310
+ return 5 /* ValidationFailed */;
311
+ case "partial":
312
+ return 9 /* PartialWrite */;
313
+ case "blocked":
314
+ case "failed":
315
+ return 7 /* ToolExecutionFailed */;
316
+ case "duplicate_blocked":
317
+ case "accepted":
318
+ case "preview":
319
+ default:
320
+ return 0 /* Success */;
321
+ }
322
+ }
323
+ function summarizeWriteEnvelope(env) {
324
+ const parts = [];
325
+ if (typeof env.requested_count === "number") {
326
+ parts.push(`requested=${env.requested_count}`);
327
+ }
328
+ if (typeof env.accepted_count === "number") {
329
+ parts.push(`accepted=${env.accepted_count}`);
330
+ }
331
+ if (typeof env.failed_count === "number") {
332
+ parts.push(`failed=${env.failed_count}`);
333
+ }
334
+ if (typeof env.previewed_count === "number") {
335
+ parts.push(`previewed=${env.previewed_count}`);
336
+ }
337
+ const status = env.status ?? "unknown";
338
+ return parts.length > 0 ? `${status} (${parts.join(", ")})` : status;
339
+ }
340
+ function classifyResponse(response) {
341
+ if (response.error) {
342
+ const message = response.error.message;
343
+ const code = response.error.code === RPC_INVALID_PARAMS ? 5 /* ValidationFailed */ : classifyToolText(message) ?? 7 /* ToolExecutionFailed */;
344
+ return {
345
+ code,
346
+ status: "rpc_error",
347
+ detail: message
348
+ };
349
+ }
350
+ const result = response.result;
351
+ const env = writeEnvelopeFrom(result);
352
+ if (env?.status) {
353
+ return {
354
+ code: classifyWriteStatus(env.status),
355
+ status: env.status,
356
+ detail: summarizeWriteEnvelope(env),
357
+ result
358
+ };
359
+ }
360
+ if (result.isError) {
361
+ const text = joinContentText(result);
362
+ const code = classifyToolText(text) ?? 7 /* ToolExecutionFailed */;
363
+ return {
364
+ code,
365
+ status: "tool_error",
366
+ detail: truncateDetail(text),
367
+ result
368
+ };
369
+ }
370
+ return {
371
+ code: 0 /* Success */,
372
+ status: "ok",
373
+ detail: truncateDetail(joinContentText(result)),
374
+ result
375
+ };
376
+ }
377
+
246
378
  // src/transport.ts
379
+ var RPC_INVALID_PARAMS2 = -32602;
380
+ function classifyRpcError(error) {
381
+ return error.code === RPC_INVALID_PARAMS2 ? 5 /* ValidationFailed */ : classifyToolText(error.message) ?? 7 /* ToolExecutionFailed */;
382
+ }
247
383
  function parseSseJsonRpc(text) {
248
384
  const dataLines = text.trim().split(/\n/).filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trim());
249
385
  return JSON.parse(dataLines.length ? dataLines.join("\n") : text);
@@ -284,115 +420,2776 @@ function buildHeaders(auth, requestId) {
284
420
  ...requestId ? { "X-Request-Id": requestId } : {}
285
421
  };
286
422
  }
287
- function createClient(auth, opts = {}) {
288
- const retry = opts.retry ?? DEFAULT_RETRY;
289
- const defaultTimeoutMs = opts.defaultTimeoutMs ?? DEFAULT_TIMEOUT_MS;
290
- const headers = buildHeaders(auth, opts.requestId);
291
- let counter = 0;
292
- const nextId = () => {
293
- counter += 1;
294
- return counter;
295
- };
296
- async function attempt(method, params, id, timeoutMs) {
297
- let res;
298
- try {
299
- res = await fetch(auth.endpoint, {
300
- method: "POST",
301
- headers,
302
- body: JSON.stringify({ jsonrpc: "2.0", id, method, params }),
303
- signal: AbortSignal.timeout(timeoutMs)
304
- });
305
- } catch (error) {
306
- if (isAbortError(error)) {
307
- throw new CliError(
308
- 8 /* Timeout */,
309
- `Request timed out after ${timeoutMs}ms`,
310
- method
311
- );
312
- }
313
- throw new RetryableError(
314
- error instanceof Error ? error.message : String(error)
315
- );
423
+ function createClient(auth, opts = {}) {
424
+ const retry = opts.retry ?? DEFAULT_RETRY;
425
+ const defaultTimeoutMs = opts.defaultTimeoutMs ?? DEFAULT_TIMEOUT_MS;
426
+ const headers = buildHeaders(auth, opts.requestId);
427
+ let counter = 0;
428
+ const nextId = () => {
429
+ counter += 1;
430
+ return counter;
431
+ };
432
+ async function attempt(method, params, id, timeoutMs, notification) {
433
+ const requestBody = notification ? { jsonrpc: "2.0", method, params } : { jsonrpc: "2.0", id, method, params };
434
+ let res;
435
+ try {
436
+ res = await fetch(auth.endpoint, {
437
+ method: "POST",
438
+ headers,
439
+ body: JSON.stringify(requestBody),
440
+ signal: AbortSignal.timeout(timeoutMs)
441
+ });
442
+ } catch (error) {
443
+ if (isAbortError(error)) {
444
+ throw new CliError(
445
+ 8 /* Timeout */,
446
+ `Request timed out after ${timeoutMs}ms`,
447
+ method
448
+ );
449
+ }
450
+ throw new RetryableError(
451
+ error instanceof Error ? error.message : String(error)
452
+ );
453
+ }
454
+ if (res.status === 401) {
455
+ throw new CliError(
456
+ 3 /* AuthError */,
457
+ "Authentication failed (HTTP 401): the API key was rejected by the hosted server.",
458
+ method
459
+ );
460
+ }
461
+ if (res.status === 429 || res.status >= 500) {
462
+ const retryAfterMs = retry.honorRetryAfter ? parseRetryAfterMs(res.headers.get("retry-after"), Date.now()) : void 0;
463
+ throw new RetryableError(`HTTP ${res.status}`, {
464
+ status: res.status,
465
+ retryAfterMs
466
+ });
467
+ }
468
+ const text = await res.text();
469
+ if (!res.ok) {
470
+ throw new CliError(
471
+ 6 /* TransportFailure */,
472
+ `HTTP ${res.status}: ${text.slice(0, 200)}`,
473
+ method
474
+ );
475
+ }
476
+ if (notification) {
477
+ return { jsonrpc: "2.0" };
478
+ }
479
+ return parseSseJsonRpc(text);
480
+ }
481
+ async function rpc(method, params, rpcOpts) {
482
+ const timeoutMs = rpcOpts?.timeoutMs ?? defaultTimeoutMs;
483
+ const notification = rpcOpts?.notification === true;
484
+ const id = rpcOpts?.id ?? nextId();
485
+ const maxAttempts = Math.max(1, retry.maxAttempts);
486
+ let lastReason = "transport failure";
487
+ for (let n = 1; n <= maxAttempts; n += 1) {
488
+ try {
489
+ return await attempt(method, params ?? {}, id, timeoutMs, notification);
490
+ } catch (error) {
491
+ if (error instanceof CliError) {
492
+ throw error;
493
+ }
494
+ if (!(error instanceof RetryableError)) {
495
+ throw error;
496
+ }
497
+ lastReason = error.message;
498
+ if (n >= maxAttempts) break;
499
+ const backoffMs = retry.baseBackoffMs * 2 ** (n - 1);
500
+ const delayMs = error.retryAfterMs ?? backoffMs;
501
+ opts.onRetry?.({ attempt: n, delayMs, reason: lastReason });
502
+ await sleep(delayMs);
503
+ }
504
+ }
505
+ throw new CliError(
506
+ 6 /* TransportFailure */,
507
+ `Transport failure after ${maxAttempts} attempt(s): ${lastReason}`,
508
+ method
509
+ );
510
+ }
511
+ async function listTools(listOpts) {
512
+ const response = await rpc("tools/list", {}, { timeoutMs: listOpts?.timeoutMs });
513
+ if (response.error) {
514
+ throw new CliError(classifyRpcError(response.error), response.error.message, "tools/list");
515
+ }
516
+ const result = response.result ?? {};
517
+ return result.tools ?? [];
518
+ }
519
+ async function callTool(name, args, callOpts) {
520
+ const response = await rpc(
521
+ "tools/call",
522
+ { name, arguments: args },
523
+ { timeoutMs: callOpts?.timeoutMs }
524
+ );
525
+ if (response.error) {
526
+ throw new CliError(classifyRpcError(response.error), response.error.message, name);
527
+ }
528
+ return response.result ?? {};
529
+ }
530
+ return { rpc, listTools, callTool };
531
+ }
532
+
533
+ // src/commands/tools.ts
534
+ import { readFile, writeFile } from "fs/promises";
535
+ import { existsSync as existsSync2 } from "fs";
536
+
537
+ // ../shared/dist/index.js
538
+ import { z as z2 } from "zod";
539
+ import { z as z22 } from "zod";
540
+ import { z as z3 } from "zod";
541
+ import { z as z4 } from "zod";
542
+ var TABLES = {
543
+ // Ads API tables
544
+ campaigns: "amzn_ads_sp_campaigns_v3",
545
+ campaignSnapshots: "amzn_ads_sp_campaign_snapshots_v1",
546
+ adsChangeHistory: "amzn_ads_change_history_v1",
547
+ budgetUsage: "amzn_ads_sp_budget_usage_v1",
548
+ adgroups: "amzn_ads_sp_campaigns_by_adgroup_v2",
549
+ placements: "amzn_ads_sp_campaigns_by_placement_v3",
550
+ advertisedProducts: "amzn_ads_sp_advertised_products_v3",
551
+ purchasedProducts: "amzn_ads_sp_purchased_products_v3",
552
+ searchTerms: "amzn_ads_sp_search_terms_v2",
553
+ targeting: "amzn_ads_sp_targeting_v4",
554
+ profiles: "amzn_ads_profiles_v2",
555
+ sqp: "sqp_search_query_by_week",
556
+ brandMetrics: "amzn_ads_brand_metrics_v1",
557
+ attributionPerformance: "amzn_ads_attribution_performance_v1",
558
+ dspPerformance: "amzn_ads_dsp_performance_v1",
559
+ storeInsights: "amzn_ads_store_insights_v1",
560
+ sbCampaigns: "amzn_ads_sb_campaigns_v1",
561
+ sdCampaigns: "amzn_ads_sd_campaigns_v1",
562
+ sdAdvertisedProducts: "amzn_ads_sd_advertised_products_v1",
563
+ sdTargeting: "amzn_ads_sd_targeting_v1",
564
+ agentActions: "agent_actions",
565
+ writeSubmissions: "write_submissions",
566
+ // SP-API tables (shared across ads + inventory)
567
+ salesAndTraffic: "sp_sales_and_traffic_v1",
568
+ activeListings: "sp_active_listings_v1",
569
+ suppressedListings: "sp_suppressed_listings_v1",
570
+ settlements: "sp_settlements_v1",
571
+ // FBA inventory tables
572
+ fbaInventory: "sp_fba_inventory_summaries_v1",
573
+ inventoryHealth: "sp_fba_inventory_health_v1",
574
+ inventoryLedger: "sp_inventory_ledger_v1",
575
+ inventoryLedgerSummary: "sp_inventory_ledger_summary_v1",
576
+ // AWD tables
577
+ awdInventory: "awd_inventory_v1",
578
+ awdShipments: "awd_shipments_v1",
579
+ awdShipmentItems: "awd_shipment_items_v1",
580
+ // FBA Inbound tables
581
+ fbaInboundShipments: "sp_fba_inbound_shipments_v1",
582
+ fbaInboundShipmentItems: "sp_fba_inbound_shipment_items_v1",
583
+ // SP-API: Orders, returns, reimbursements, financial events, catalog
584
+ orders: "sp_orders_v1",
585
+ orderItems: "sp_order_items_v1",
586
+ returns: "sp_fba_returns_v1",
587
+ reimbursements: "sp_fba_reimbursements_v1",
588
+ financialEvents: "sp_financial_events_v1",
589
+ catalogItems: "sp_catalog_items_v1",
590
+ listingQuality: "sp_listing_quality_v1",
591
+ pricingSnapshots: "sp_pricing_v1",
592
+ replenishmentOffers: "sp_replenishment_offers_v1",
593
+ customerFeedbackSnapshots: "sp_customer_feedback_snapshots_v1",
594
+ // SP-API: Fees
595
+ referralFees: "sp_referral_fees_v1",
596
+ fbaStorageFeeCharges: "sp_fba_storage_fee_charges_v1",
597
+ fbaLongTermStorageFeeCharges: "sp_fba_longterm_storage_fee_charges_v1",
598
+ // Brand Analytics tables
599
+ baSearchTerms: "ba_search_terms_v1",
600
+ baMarketBasket: "ba_market_basket_v1",
601
+ baRepeatPurchase: "ba_repeat_purchase_v1",
602
+ baSearchCatalog: "ba_search_catalog_v1",
603
+ // SB (Sponsored Brands) ads tables
604
+ sbAds: "amzn_ads_sb_ads_v1",
605
+ sbSearchTerms: "amzn_ads_sb_search_terms_v1",
606
+ sbTargeting: "amzn_ads_sb_targeting_v1",
607
+ sbPurchasedProducts: "amzn_ads_sb_purchased_products_v1",
608
+ sbGrossAndInvalids: "amzn_ads_sb_gross_and_invalids_v1",
609
+ // SD (Sponsored Display) ads tables
610
+ sdPurchasedProducts: "amzn_ads_sd_purchased_products_v1",
611
+ sdGrossAndInvalids: "amzn_ads_sd_gross_and_invalids_v1",
612
+ // SP (Sponsored Products) gross & invalids
613
+ spGrossAndInvalids: "amzn_ads_sp_gross_and_invalids_v1",
614
+ // Infrastructure tables
615
+ tenants: "tenants",
616
+ agencies: "agencies",
617
+ appUsers: "app_users",
618
+ agencyMemberships: "agency_memberships",
619
+ tenantMemberships: "tenant_memberships",
620
+ tenantAdsProfiles: "tenant_ads_profiles",
621
+ tenantMarketplaceConnections: "tenant_marketplace_connections",
622
+ apiKeys: "api_keys",
623
+ apiUsageEvents: "api_usage_events",
624
+ signupAttribution: "signup_attribution",
625
+ adLifecycleEvents: "ad_lifecycle_events",
626
+ adConversionUploads: "ad_conversion_uploads",
627
+ landingVisits: "landing_visits",
628
+ alertEvents: "alert_events",
629
+ remediationActions: "remediation_actions",
630
+ emailEvents: "email_events",
631
+ emailVerificationTokens: "email_verification_tokens",
632
+ passwordResetTokens: "password_reset_tokens",
633
+ onboardingInvites: "onboarding_invites",
634
+ tenantDeletionTombstones: "tenant_deletion_tombstones",
635
+ ingestionMetadata: "sp_ingestion_metadata",
636
+ asinRegistry: "asin_registry",
637
+ syncRuns: "sync_runs",
638
+ syncLeases: "sync_leases",
639
+ paginationCheckpoints: "pagination_checkpoints",
640
+ tenantCapabilities: "tenant_capabilities",
641
+ bqUsageDaily: "bq_usage_daily",
642
+ workerUsageDaily: "worker_usage_daily",
643
+ pendingReports: "pending_reports",
644
+ reportJobs: "report_jobs",
645
+ shareableReports: "shareable_reports",
646
+ conversationFeedback: "conversation_feedback",
647
+ dataCoverage: "data_coverage",
648
+ sellerAccountMarketplaceRegistry: "seller_account_marketplace_registry",
649
+ sellerAccountBillingState: "seller_account_billing_state",
650
+ sellerAccountBillingMeasurements: "seller_account_billing_measurements",
651
+ sellerAccountBillingEvents: "seller_account_billing_events",
652
+ /** @deprecated Use sellerAccountBillingState. */
653
+ marketplaceBillingState: "seller_account_billing_state",
654
+ /** @deprecated Use sellerAccountBillingMeasurements. */
655
+ marketplaceBillingMeasurements: "seller_account_billing_measurements",
656
+ /** @deprecated Use sellerAccountBillingEvents. */
657
+ marketplaceBillingEvents: "seller_account_billing_events",
658
+ // Computed tables
659
+ seasonalityIndex: "seasonality_index_v1",
660
+ keywordRanks: "sp_keyword_ranks_v1",
661
+ // Sales metrics (aggregated)
662
+ orderMetrics: "sp_order_metrics_v1",
663
+ // Dashboard tables
664
+ asinCogs: "asin_cogs",
665
+ inventoryConfig: "inventory_config"
666
+ };
667
+ var SHARED_ONLY_TABLES = [
668
+ "agencies",
669
+ "agency_memberships",
670
+ "alert_events",
671
+ "amzn_ads_profiles_v2",
672
+ "app_users",
673
+ "remediation_actions",
674
+ "api_keys",
675
+ "api_usage_events",
676
+ "ad_lifecycle_events",
677
+ "ad_conversion_uploads",
678
+ "landing_visits",
679
+ "asin_registry",
680
+ "data_coverage",
681
+ "seller_account_marketplace_registry",
682
+ "seller_account_billing_state",
683
+ "seller_account_billing_measurements",
684
+ "seller_account_billing_events",
685
+ "email_events",
686
+ "email_verification_tokens",
687
+ "onboarding_invites",
688
+ "password_reset_tokens",
689
+ "pending_reports",
690
+ "report_jobs",
691
+ "shareable_reports",
692
+ "conversation_feedback",
693
+ "signup_attribution",
694
+ "sp_ingestion_metadata",
695
+ "sync_leases",
696
+ "sync_runs",
697
+ "pagination_checkpoints",
698
+ "tenant_capabilities",
699
+ "bq_usage_daily",
700
+ "worker_usage_daily",
701
+ "tenant_ads_profiles",
702
+ "tenant_marketplace_connections",
703
+ "tenant_deletion_tombstones",
704
+ "tenant_memberships",
705
+ "tenants"
706
+ ];
707
+ var SHARED_ONLY_TABLE_SET = new Set(SHARED_ONLY_TABLES);
708
+ var METRIC_EXPRESSIONS = {
709
+ acos: "CASE WHEN COALESCE(SUM(sales14d), 0) = 0 THEN NULL ELSE ROUND(SAFE_DIVIDE(SUM(cost), SUM(sales14d)) * 100, 2) END",
710
+ roas: "CASE WHEN COALESCE(SUM(sales14d), 0) = 0 OR COALESCE(SUM(cost), 0) = 0 THEN NULL ELSE ROUND(SAFE_DIVIDE(SUM(sales14d), SUM(cost)), 2) END",
711
+ ctr: "ROUND(SAFE_DIVIDE(SUM(clicks), SUM(impressions)) * 100, 2)",
712
+ cpc: "ROUND(SAFE_DIVIDE(SUM(cost), SUM(clicks)), 2)",
713
+ cvr: "CASE WHEN COALESCE(SUM(purchases14d), 0) = 0 OR COALESCE(SUM(clicks), 0) = 0 THEN NULL ELSE ROUND(SAFE_DIVIDE(SUM(purchases14d), SUM(clicks)) * 100, 2) END"
714
+ };
715
+ var STANDARD_METRICS = `
716
+ SUM(impressions) AS impressions,
717
+ SUM(clicks) AS clicks,
718
+ ROUND(SUM(cost), 2) AS spend,
719
+ ROUND(SUM(sales14d), 2) AS sales,
720
+ SUM(purchases14d) AS orders,
721
+ SUM(units_sold_clicks14d) AS units_sold,
722
+ ${METRIC_EXPRESSIONS.acos} AS acos,
723
+ ${METRIC_EXPRESSIONS.roas} AS roas,
724
+ ${METRIC_EXPRESSIONS.ctr} AS ctr,
725
+ ${METRIC_EXPRESSIONS.cpc} AS cpc,
726
+ ${METRIC_EXPRESSIONS.cvr} AS cvr`;
727
+ var DEFAULT_MARKETPLACE_ID = "ATVPDKIKX0DER";
728
+ var DEFAULT_REPORTING_TIME_ZONE = "America/Los_Angeles";
729
+ var SP_API_BASE_URLS = {
730
+ NA: "https://sellingpartnerapi-na.amazon.com",
731
+ EU: "https://sellingpartnerapi-eu.amazon.com",
732
+ FE: "https://sellingpartnerapi-fe.amazon.com"
733
+ };
734
+ var ADS_API_BASE_URLS = {
735
+ NA: "https://advertising-api.amazon.com",
736
+ EU: "https://advertising-api-eu.amazon.com",
737
+ FE: "https://advertising-api-fe.amazon.com"
738
+ };
739
+ var ENABLED_ROLLOUT = {
740
+ rolloutStatus: "enabled",
741
+ phase1Enabled: true,
742
+ oauthConnectEnabled: true
743
+ };
744
+ var MARKETPLACE_DEFINITIONS = [
745
+ {
746
+ marketplaceId: "ATVPDKIKX0DER",
747
+ countryCode: "US",
748
+ countryName: "United States",
749
+ amazonDomain: "Amazon.com",
750
+ currencyCode: "USD",
751
+ defaultReportingTimeZone: DEFAULT_REPORTING_TIME_ZONE,
752
+ spApiRegion: "NA",
753
+ spApiBaseUrl: SP_API_BASE_URLS.NA,
754
+ sellerCentralBaseUrl: "https://sellercentral.amazon.com",
755
+ adsRegion: "NA",
756
+ adsApiBaseUrl: ADS_API_BASE_URLS.NA,
757
+ rolloutStatus: "foundation",
758
+ phase1Enabled: true
759
+ },
760
+ {
761
+ marketplaceId: "A1F83G8C2ARO7P",
762
+ countryCode: "GB",
763
+ countryName: "United Kingdom",
764
+ amazonDomain: "Amazon.co.uk",
765
+ currencyCode: "GBP",
766
+ defaultReportingTimeZone: "Europe/London",
767
+ spApiRegion: "EU",
768
+ spApiBaseUrl: SP_API_BASE_URLS.EU,
769
+ sellerCentralBaseUrl: "https://sellercentral-europe.amazon.com",
770
+ adsRegion: "EU",
771
+ adsApiBaseUrl: ADS_API_BASE_URLS.EU,
772
+ rolloutStatus: "foundation",
773
+ phase1Enabled: true
774
+ },
775
+ {
776
+ marketplaceId: "A17E79C6D8DWNP",
777
+ countryCode: "SA",
778
+ countryName: "Saudi Arabia",
779
+ amazonDomain: "Amazon.sa",
780
+ currencyCode: "SAR",
781
+ defaultReportingTimeZone: "Asia/Riyadh",
782
+ spApiRegion: "EU",
783
+ spApiBaseUrl: SP_API_BASE_URLS.EU,
784
+ sellerCentralBaseUrl: "https://sellercentral.amazon.sa",
785
+ adsRegion: "EU",
786
+ adsApiBaseUrl: ADS_API_BASE_URLS.EU,
787
+ rolloutStatus: "foundation",
788
+ phase1Enabled: true
789
+ },
790
+ {
791
+ marketplaceId: "A2EUQ1WTGCTBG2",
792
+ countryCode: "CA",
793
+ countryName: "Canada",
794
+ amazonDomain: "Amazon.ca",
795
+ currencyCode: "CAD",
796
+ defaultReportingTimeZone: "America/Toronto",
797
+ spApiRegion: "NA",
798
+ spApiBaseUrl: SP_API_BASE_URLS.NA,
799
+ sellerCentralBaseUrl: "https://sellercentral.amazon.ca",
800
+ adsRegion: "NA",
801
+ adsApiBaseUrl: ADS_API_BASE_URLS.NA,
802
+ ...ENABLED_ROLLOUT
803
+ },
804
+ {
805
+ marketplaceId: "A1AM78C64UM0Y8",
806
+ countryCode: "MX",
807
+ countryName: "Mexico",
808
+ amazonDomain: "Amazon.com.mx",
809
+ currencyCode: "MXN",
810
+ defaultReportingTimeZone: "America/Mexico_City",
811
+ spApiRegion: "NA",
812
+ spApiBaseUrl: SP_API_BASE_URLS.NA,
813
+ sellerCentralBaseUrl: "https://sellercentral.amazon.com.mx",
814
+ adsRegion: "NA",
815
+ adsApiBaseUrl: ADS_API_BASE_URLS.NA,
816
+ ...ENABLED_ROLLOUT
817
+ },
818
+ {
819
+ marketplaceId: "A2Q3Y263D00KWC",
820
+ countryCode: "BR",
821
+ countryName: "Brazil",
822
+ amazonDomain: "Amazon.com.br",
823
+ currencyCode: "BRL",
824
+ defaultReportingTimeZone: "America/Sao_Paulo",
825
+ spApiRegion: "NA",
826
+ spApiBaseUrl: SP_API_BASE_URLS.NA,
827
+ sellerCentralBaseUrl: "https://sellercentral.amazon.com.br",
828
+ adsRegion: "NA",
829
+ adsApiBaseUrl: ADS_API_BASE_URLS.NA,
830
+ ...ENABLED_ROLLOUT
831
+ },
832
+ {
833
+ marketplaceId: "A28R8C7NBKEWEA",
834
+ countryCode: "IE",
835
+ countryName: "Ireland",
836
+ amazonDomain: "Amazon.ie",
837
+ currencyCode: "EUR",
838
+ defaultReportingTimeZone: "Europe/Dublin",
839
+ spApiRegion: "EU",
840
+ spApiBaseUrl: SP_API_BASE_URLS.EU,
841
+ sellerCentralBaseUrl: "https://sellercentral.amazon.ie",
842
+ adsRegion: "EU",
843
+ adsApiBaseUrl: ADS_API_BASE_URLS.EU,
844
+ ...ENABLED_ROLLOUT
845
+ },
846
+ {
847
+ marketplaceId: "A1RKKUPIHCS9HS",
848
+ countryCode: "ES",
849
+ countryName: "Spain",
850
+ amazonDomain: "Amazon.es",
851
+ currencyCode: "EUR",
852
+ defaultReportingTimeZone: "Europe/Madrid",
853
+ spApiRegion: "EU",
854
+ spApiBaseUrl: SP_API_BASE_URLS.EU,
855
+ sellerCentralBaseUrl: "https://sellercentral-europe.amazon.com",
856
+ adsRegion: "EU",
857
+ adsApiBaseUrl: ADS_API_BASE_URLS.EU,
858
+ ...ENABLED_ROLLOUT
859
+ },
860
+ {
861
+ marketplaceId: "A13V1IB3VIYZZH",
862
+ countryCode: "FR",
863
+ countryName: "France",
864
+ amazonDomain: "Amazon.fr",
865
+ currencyCode: "EUR",
866
+ defaultReportingTimeZone: "Europe/Paris",
867
+ spApiRegion: "EU",
868
+ spApiBaseUrl: SP_API_BASE_URLS.EU,
869
+ sellerCentralBaseUrl: "https://sellercentral-europe.amazon.com",
870
+ adsRegion: "EU",
871
+ adsApiBaseUrl: ADS_API_BASE_URLS.EU,
872
+ ...ENABLED_ROLLOUT
873
+ },
874
+ {
875
+ marketplaceId: "AMEN7PMS3EDWL",
876
+ countryCode: "BE",
877
+ countryName: "Belgium",
878
+ amazonDomain: "Amazon.com.be",
879
+ currencyCode: "EUR",
880
+ defaultReportingTimeZone: "Europe/Brussels",
881
+ spApiRegion: "EU",
882
+ spApiBaseUrl: SP_API_BASE_URLS.EU,
883
+ sellerCentralBaseUrl: "https://sellercentral.amazon.com.be",
884
+ adsRegion: "EU",
885
+ adsApiBaseUrl: ADS_API_BASE_URLS.EU,
886
+ ...ENABLED_ROLLOUT
887
+ },
888
+ {
889
+ marketplaceId: "A1805IZSGTT6HS",
890
+ countryCode: "NL",
891
+ countryName: "Netherlands",
892
+ amazonDomain: "Amazon.nl",
893
+ currencyCode: "EUR",
894
+ defaultReportingTimeZone: "Europe/Amsterdam",
895
+ spApiRegion: "EU",
896
+ spApiBaseUrl: SP_API_BASE_URLS.EU,
897
+ sellerCentralBaseUrl: "https://sellercentral.amazon.nl",
898
+ adsRegion: "EU",
899
+ adsApiBaseUrl: ADS_API_BASE_URLS.EU,
900
+ ...ENABLED_ROLLOUT
901
+ },
902
+ {
903
+ marketplaceId: "A1PA6795UKMFR9",
904
+ countryCode: "DE",
905
+ countryName: "Germany",
906
+ amazonDomain: "Amazon.de",
907
+ currencyCode: "EUR",
908
+ defaultReportingTimeZone: "Europe/Berlin",
909
+ spApiRegion: "EU",
910
+ spApiBaseUrl: SP_API_BASE_URLS.EU,
911
+ sellerCentralBaseUrl: "https://sellercentral-europe.amazon.com",
912
+ adsRegion: "EU",
913
+ adsApiBaseUrl: ADS_API_BASE_URLS.EU,
914
+ ...ENABLED_ROLLOUT
915
+ },
916
+ {
917
+ marketplaceId: "APJ6JRA9NG5V4",
918
+ countryCode: "IT",
919
+ countryName: "Italy",
920
+ amazonDomain: "Amazon.it",
921
+ currencyCode: "EUR",
922
+ defaultReportingTimeZone: "Europe/Rome",
923
+ spApiRegion: "EU",
924
+ spApiBaseUrl: SP_API_BASE_URLS.EU,
925
+ sellerCentralBaseUrl: "https://sellercentral-europe.amazon.com",
926
+ adsRegion: "EU",
927
+ adsApiBaseUrl: ADS_API_BASE_URLS.EU,
928
+ ...ENABLED_ROLLOUT
929
+ },
930
+ {
931
+ marketplaceId: "A2NODRKZP88ZB9",
932
+ countryCode: "SE",
933
+ countryName: "Sweden",
934
+ amazonDomain: "Amazon.se",
935
+ currencyCode: "SEK",
936
+ defaultReportingTimeZone: "Europe/Stockholm",
937
+ spApiRegion: "EU",
938
+ spApiBaseUrl: SP_API_BASE_URLS.EU,
939
+ sellerCentralBaseUrl: "https://sellercentral.amazon.se",
940
+ adsRegion: "EU",
941
+ adsApiBaseUrl: ADS_API_BASE_URLS.EU,
942
+ ...ENABLED_ROLLOUT
943
+ },
944
+ {
945
+ marketplaceId: "AE08WJ6YKNBMC",
946
+ countryCode: "ZA",
947
+ countryName: "South Africa",
948
+ amazonDomain: "Amazon.co.za",
949
+ currencyCode: "ZAR",
950
+ defaultReportingTimeZone: "Africa/Johannesburg",
951
+ spApiRegion: "EU",
952
+ spApiBaseUrl: SP_API_BASE_URLS.EU,
953
+ sellerCentralBaseUrl: "https://sellercentral.amazon.co.za",
954
+ adsRegion: "EU",
955
+ adsApiBaseUrl: ADS_API_BASE_URLS.EU,
956
+ ...ENABLED_ROLLOUT
957
+ },
958
+ {
959
+ marketplaceId: "A1C3SOZRARQ6R3",
960
+ countryCode: "PL",
961
+ countryName: "Poland",
962
+ amazonDomain: "Amazon.pl",
963
+ currencyCode: "PLN",
964
+ defaultReportingTimeZone: "Europe/Warsaw",
965
+ spApiRegion: "EU",
966
+ spApiBaseUrl: SP_API_BASE_URLS.EU,
967
+ sellerCentralBaseUrl: "https://sellercentral.amazon.pl",
968
+ adsRegion: "EU",
969
+ adsApiBaseUrl: ADS_API_BASE_URLS.EU,
970
+ ...ENABLED_ROLLOUT
971
+ },
972
+ {
973
+ marketplaceId: "ARBP9OOSHTCHU",
974
+ countryCode: "EG",
975
+ countryName: "Egypt",
976
+ amazonDomain: "Amazon.eg",
977
+ currencyCode: "EGP",
978
+ defaultReportingTimeZone: "Africa/Cairo",
979
+ spApiRegion: "EU",
980
+ spApiBaseUrl: SP_API_BASE_URLS.EU,
981
+ sellerCentralBaseUrl: "https://sellercentral.amazon.eg",
982
+ adsRegion: "EU",
983
+ adsApiBaseUrl: ADS_API_BASE_URLS.EU,
984
+ ...ENABLED_ROLLOUT
985
+ },
986
+ {
987
+ marketplaceId: "A33AVAJ2PDY3EV",
988
+ countryCode: "TR",
989
+ countryName: "Turkey",
990
+ amazonDomain: "Amazon.com.tr",
991
+ currencyCode: "TRY",
992
+ defaultReportingTimeZone: "Europe/Istanbul",
993
+ spApiRegion: "EU",
994
+ spApiBaseUrl: SP_API_BASE_URLS.EU,
995
+ sellerCentralBaseUrl: "https://sellercentral.amazon.com.tr",
996
+ adsRegion: "EU",
997
+ adsApiBaseUrl: ADS_API_BASE_URLS.EU,
998
+ ...ENABLED_ROLLOUT
999
+ },
1000
+ {
1001
+ marketplaceId: "A2VIGQ35RCS4UG",
1002
+ countryCode: "AE",
1003
+ countryName: "United Arab Emirates",
1004
+ amazonDomain: "Amazon.ae",
1005
+ currencyCode: "AED",
1006
+ defaultReportingTimeZone: "Asia/Dubai",
1007
+ spApiRegion: "EU",
1008
+ spApiBaseUrl: SP_API_BASE_URLS.EU,
1009
+ sellerCentralBaseUrl: "https://sellercentral.amazon.ae",
1010
+ adsRegion: "EU",
1011
+ adsApiBaseUrl: ADS_API_BASE_URLS.EU,
1012
+ ...ENABLED_ROLLOUT
1013
+ },
1014
+ {
1015
+ marketplaceId: "A21TJRUUN4KGV",
1016
+ countryCode: "IN",
1017
+ countryName: "India",
1018
+ amazonDomain: "Amazon.in",
1019
+ currencyCode: "INR",
1020
+ defaultReportingTimeZone: "Asia/Kolkata",
1021
+ spApiRegion: "EU",
1022
+ spApiBaseUrl: SP_API_BASE_URLS.EU,
1023
+ sellerCentralBaseUrl: "https://sellercentral.amazon.in",
1024
+ adsRegion: "EU",
1025
+ adsApiBaseUrl: ADS_API_BASE_URLS.EU,
1026
+ ...ENABLED_ROLLOUT
1027
+ },
1028
+ {
1029
+ marketplaceId: "A19VAU5U5O7RUS",
1030
+ countryCode: "SG",
1031
+ countryName: "Singapore",
1032
+ amazonDomain: "Amazon.sg",
1033
+ currencyCode: "SGD",
1034
+ defaultReportingTimeZone: "Asia/Singapore",
1035
+ spApiRegion: "FE",
1036
+ spApiBaseUrl: SP_API_BASE_URLS.FE,
1037
+ sellerCentralBaseUrl: "https://sellercentral.amazon.sg",
1038
+ adsRegion: "FE",
1039
+ adsApiBaseUrl: ADS_API_BASE_URLS.FE,
1040
+ ...ENABLED_ROLLOUT
1041
+ },
1042
+ {
1043
+ marketplaceId: "A39IBJ37TRP1C6",
1044
+ countryCode: "AU",
1045
+ countryName: "Australia",
1046
+ amazonDomain: "Amazon.com.au",
1047
+ currencyCode: "AUD",
1048
+ defaultReportingTimeZone: "Australia/Sydney",
1049
+ spApiRegion: "FE",
1050
+ spApiBaseUrl: SP_API_BASE_URLS.FE,
1051
+ sellerCentralBaseUrl: "https://sellercentral.amazon.com.au",
1052
+ adsRegion: "FE",
1053
+ adsApiBaseUrl: ADS_API_BASE_URLS.FE,
1054
+ ...ENABLED_ROLLOUT
1055
+ },
1056
+ {
1057
+ marketplaceId: "A1VC38T7YXB528",
1058
+ countryCode: "JP",
1059
+ countryName: "Japan",
1060
+ amazonDomain: "Amazon.co.jp",
1061
+ currencyCode: "JPY",
1062
+ defaultReportingTimeZone: "Asia/Tokyo",
1063
+ spApiRegion: "FE",
1064
+ spApiBaseUrl: SP_API_BASE_URLS.FE,
1065
+ sellerCentralBaseUrl: "https://sellercentral.amazon.co.jp",
1066
+ adsRegion: "FE",
1067
+ adsApiBaseUrl: ADS_API_BASE_URLS.FE,
1068
+ ...ENABLED_ROLLOUT
1069
+ }
1070
+ ];
1071
+ var MARKETPLACES_BY_ID = Object.freeze(
1072
+ Object.fromEntries(MARKETPLACE_DEFINITIONS.map((marketplace) => [marketplace.marketplaceId, marketplace]))
1073
+ );
1074
+ function marketplaceIdsForCountryCodes(countryCodes) {
1075
+ return Object.freeze(countryCodes.map((countryCode) => {
1076
+ const marketplace = MARKETPLACE_DEFINITIONS.find((entry) => entry.countryCode === countryCode);
1077
+ if (!marketplace) {
1078
+ throw new Error(`Missing marketplace definition for country code ${countryCode}`);
1079
+ }
1080
+ return marketplace.marketplaceId;
1081
+ }));
1082
+ }
1083
+ function marketplaceSetForCountryCodes(countryCodes) {
1084
+ return Object.freeze(new Set(marketplaceIdsForCountryCodes(countryCodes)));
1085
+ }
1086
+ var CUSTOMER_FEEDBACK_SUPPORTED_MARKETPLACE_IDS = Object.freeze(
1087
+ /* @__PURE__ */ new Set([
1088
+ "ATVPDKIKX0DER",
1089
+ // US
1090
+ "A1F83G8C2ARO7P",
1091
+ // UK
1092
+ "A1PA6795UKMFR9",
1093
+ // DE
1094
+ "A1RKKUPIHCS9HS",
1095
+ // ES
1096
+ "A13V1IB3VIYZZH",
1097
+ // FR
1098
+ "APJ6JRA9NG5V4",
1099
+ // IT
1100
+ "A1VC38T7YXB528"
1101
+ // JP
1102
+ ])
1103
+ );
1104
+ var ADS_SPONSORED_PRODUCTS_CAMPAIGN_MANAGEMENT_SUPPORTED_MARKETPLACE_IDS = marketplaceSetForCountryCodes([
1105
+ "US",
1106
+ "CA",
1107
+ "MX",
1108
+ "BR",
1109
+ "DE",
1110
+ "ES",
1111
+ "FR",
1112
+ "IT",
1113
+ "GB",
1114
+ "NL",
1115
+ "SE",
1116
+ "TR",
1117
+ "PL",
1118
+ "BE",
1119
+ "AE",
1120
+ "EG",
1121
+ "SA",
1122
+ "JP",
1123
+ "IN",
1124
+ "AU",
1125
+ "SG",
1126
+ "ZA"
1127
+ ]);
1128
+ var ADS_SPONSORED_PRODUCTS_BID_RECOMMENDATION_SUPPORTED_MARKETPLACE_IDS = marketplaceSetForCountryCodes(["US", "CA", "DE", "ES", "FR", "GB", "JP", "IN"]);
1129
+ var ADS_SPONSORED_PRODUCTS_BUDGET_RECOMMENDATION_SUPPORTED_MARKETPLACE_IDS = marketplaceSetForCountryCodes(["US", "CA", "MX", "DE", "ES", "FR", "GB", "IT", "JP", "IN", "AU", "AE"]);
1130
+ var ADS_BRAND_METRICS_SUPPORTED_MARKETPLACE_IDS = marketplaceSetForCountryCodes(["US", "CA", "MX", "GB", "DE", "FR", "IN", "IT", "ES", "JP", "AU"]);
1131
+ var BRAND_ANALYTICS_REPORT_SUPPORTED_MARKETPLACE_IDS = marketplaceSetForCountryCodes([
1132
+ "US",
1133
+ "CA",
1134
+ "MX",
1135
+ "BR",
1136
+ "ES",
1137
+ "GB",
1138
+ "FR",
1139
+ "NL",
1140
+ "DE",
1141
+ "IT",
1142
+ "SE",
1143
+ "TR",
1144
+ "SA",
1145
+ "AE",
1146
+ "IN",
1147
+ "SG",
1148
+ "AU",
1149
+ "JP"
1150
+ ]);
1151
+ var FULFILLMENT_INBOUND_SUPPORTED_MARKETPLACE_IDS = Object.freeze(
1152
+ new Set(MARKETPLACE_DEFINITIONS.filter((marketplace) => marketplace.countryCode !== "BR").map((marketplace) => marketplace.marketplaceId))
1153
+ );
1154
+ var FBA_INVENTORY_PLANNING_UNSUPPORTED_COUNTRY_CODES = /* @__PURE__ */ new Set(["NL", "PL", "SE", "BE"]);
1155
+ var FBA_INVENTORY_PLANNING_SUPPORTED_MARKETPLACE_IDS = Object.freeze(
1156
+ new Set(MARKETPLACE_DEFINITIONS.filter((marketplace) => !FBA_INVENTORY_PLANNING_UNSUPPORTED_COUNTRY_CODES.has(marketplace.countryCode)).map((marketplace) => marketplace.marketplaceId))
1157
+ );
1158
+ var AWD_SUPPORTED_MARKETPLACE_IDS = marketplaceSetForCountryCodes(["US"]);
1159
+ var MARKETPLACE_NAMES = Object.freeze(
1160
+ Object.fromEntries(MARKETPLACE_DEFINITIONS.map((marketplace) => [marketplace.marketplaceId, marketplace.countryName]))
1161
+ );
1162
+ function getMarketplaceDefinition(marketplaceId) {
1163
+ if (!marketplaceId) return void 0;
1164
+ return MARKETPLACES_BY_ID[marketplaceId];
1165
+ }
1166
+ var MARKETPLACE_ORDER_TIER_IDS = [
1167
+ "starter",
1168
+ "growth",
1169
+ "scale",
1170
+ "business",
1171
+ "enterprise"
1172
+ ];
1173
+ var SELLER_ACCOUNT_ORDER_TIER_IDS = MARKETPLACE_ORDER_TIER_IDS;
1174
+ var MARKETPLACE_ORDER_TIERS = [
1175
+ {
1176
+ id: "starter",
1177
+ displayName: "Starter",
1178
+ minOrdersInclusive: 0,
1179
+ maxOrdersInclusive: 1e3,
1180
+ monthlyUsd: 39,
1181
+ monthlyPriceCents: 3900
1182
+ },
1183
+ {
1184
+ id: "growth",
1185
+ displayName: "Growth",
1186
+ minOrdersInclusive: 1001,
1187
+ maxOrdersInclusive: 5e3,
1188
+ monthlyUsd: 69,
1189
+ monthlyPriceCents: 6900
1190
+ },
1191
+ {
1192
+ id: "scale",
1193
+ displayName: "Scale",
1194
+ minOrdersInclusive: 5001,
1195
+ maxOrdersInclusive: 1e4,
1196
+ monthlyUsd: 99,
1197
+ monthlyPriceCents: 9900
1198
+ },
1199
+ {
1200
+ id: "business",
1201
+ displayName: "Business",
1202
+ minOrdersInclusive: 10001,
1203
+ maxOrdersInclusive: 25e3,
1204
+ monthlyUsd: 199,
1205
+ monthlyPriceCents: 19900
1206
+ },
1207
+ {
1208
+ id: "enterprise",
1209
+ displayName: "Enterprise",
1210
+ minOrdersInclusive: 25001,
1211
+ maxOrdersInclusive: null,
1212
+ monthlyUsd: null,
1213
+ monthlyPriceCents: null
1214
+ }
1215
+ ];
1216
+ var SELLER_ACCOUNT_BILLING_STATUSES = [
1217
+ "trialing",
1218
+ "active",
1219
+ "past_due",
1220
+ "canceled",
1221
+ "provisional",
1222
+ "custom",
1223
+ "disabled"
1224
+ ];
1225
+ var SELLER_ACCOUNT_BILLING_MEASUREMENT_SOURCES = [
1226
+ "order_metrics",
1227
+ "raw_orders",
1228
+ "manual",
1229
+ "unavailable"
1230
+ ];
1231
+ var SELLER_ACCOUNT_BILLING_MEASUREMENT_CONFIDENCES = [
1232
+ "final",
1233
+ "partial",
1234
+ "provisional",
1235
+ "unavailable",
1236
+ "manual"
1237
+ ];
1238
+ var TIER_INDEX_BY_ID = new Map(
1239
+ MARKETPLACE_ORDER_TIERS.map((tier, index) => [tier.id, index])
1240
+ );
1241
+ var TIER_BY_ID = new Map(
1242
+ MARKETPLACE_ORDER_TIERS.map((tier) => [tier.id, tier])
1243
+ );
1244
+ var DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
1245
+ var DATE_ERROR = "Expected date string in YYYY-MM-DD format";
1246
+ var CALENDAR_DATE_ERROR = "Expected valid calendar date in YYYY-MM-DD format";
1247
+ var TIMESTAMP_ERROR = "Expected parseable timestamp";
1248
+ function isLeapYear(year) {
1249
+ return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
1250
+ }
1251
+ function isValidCalendarDateString(value) {
1252
+ const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
1253
+ if (!match) {
1254
+ return false;
1255
+ }
1256
+ const year = Number(match[1]);
1257
+ const month = Number(match[2]);
1258
+ const day = Number(match[3]);
1259
+ if (year < 1 || month < 1 || month > 12) {
1260
+ return false;
1261
+ }
1262
+ const daysInMonth = [31, isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
1263
+ return day >= 1 && day <= daysInMonth[month - 1];
1264
+ }
1265
+ function isParseableTimestampString(value) {
1266
+ if (!Number.isFinite(Date.parse(value))) {
1267
+ return false;
1268
+ }
1269
+ const leadingDate = /^(\d{4}-\d{2}-\d{2})(?:[T\s]|$)/.exec(value);
1270
+ if (leadingDate && !isValidCalendarDateString(leadingDate[1])) {
1271
+ return false;
1272
+ }
1273
+ return true;
1274
+ }
1275
+ var dateSchema = z2.string({ invalid_type_error: DATE_ERROR }).regex(DATE_PATTERN, DATE_ERROR).describe("Date (YYYY-MM-DD)");
1276
+ var DEFAULT_TOOL_LIMIT = 20;
1277
+ var MAX_TOOL_LIMIT = 1e3;
1278
+ function toolLimitParam(description = `Max rows (1-${MAX_TOOL_LIMIT}, default ${DEFAULT_TOOL_LIMIT}).`, options) {
1279
+ const max = options?.max ?? MAX_TOOL_LIMIT;
1280
+ const defaultValue = options?.defaultValue ?? DEFAULT_TOOL_LIMIT;
1281
+ return z2.number().int().min(1).max(max).default(defaultValue).describe(description);
1282
+ }
1283
+ function optionalDateParam(description) {
1284
+ return z2.preprocess(
1285
+ (value) => value === null ? void 0 : value,
1286
+ z2.string({ invalid_type_error: DATE_ERROR }).regex(DATE_PATTERN, DATE_ERROR).optional()
1287
+ ).describe(description);
1288
+ }
1289
+ var AGENCY_STATUSES = ["pilot", "active", "paused", "disabled"];
1290
+ var APP_USER_STATUSES = ["active", "invited", "disabled", "deleted"];
1291
+ var AGENCY_MEMBERSHIP_ROLES = ["owner", "admin", "member"];
1292
+ var TENANT_MEMBERSHIP_ROLES = ["owner", "admin", "member", "read_only"];
1293
+ var MEMBERSHIP_STATUSES = ["invited", "active", "disabled", "deleted"];
1294
+ var TENANT_BILLING_OWNERS = ["self_serve", "agency", "manual"];
1295
+ var TENANT_BILLING_MODES = ["standard", "custom_agency", "covered"];
1296
+ var agencyStatusSchema = z2.enum(AGENCY_STATUSES);
1297
+ var appUserStatusSchema = z2.enum(APP_USER_STATUSES);
1298
+ var agencyMembershipRoleSchema = z2.enum(AGENCY_MEMBERSHIP_ROLES);
1299
+ var tenantMembershipRoleSchema = z2.enum(TENANT_MEMBERSHIP_ROLES);
1300
+ var membershipStatusSchema = z2.enum(MEMBERSHIP_STATUSES);
1301
+ var tenantBillingOwnerSchema = z2.enum(TENANT_BILLING_OWNERS);
1302
+ var tenantBillingModeSchema = z2.enum(TENANT_BILLING_MODES);
1303
+ var nonEmptyStringSchema = z2.string().min(1);
1304
+ var nullableStringSchema = nonEmptyStringSchema.nullable();
1305
+ var timestampStringSchema = nonEmptyStringSchema;
1306
+ var nullableTimestampStringSchema = timestampStringSchema.nullable();
1307
+ var sellerAccountMarketplaceRegistryDateSchema = z2.string({ invalid_type_error: CALENDAR_DATE_ERROR }).regex(DATE_PATTERN, CALENDAR_DATE_ERROR).refine(isValidCalendarDateString, CALENDAR_DATE_ERROR);
1308
+ var nullableSellerAccountMarketplaceRegistryDateSchema = sellerAccountMarketplaceRegistryDateSchema.nullable();
1309
+ var nullableDateSchema = dateSchema.nullable();
1310
+ var sellerAccountMarketplaceRegistryTimestampSchema = z2.string({ invalid_type_error: TIMESTAMP_ERROR }).min(1, TIMESTAMP_ERROR).refine(isParseableTimestampString, TIMESTAMP_ERROR);
1311
+ var nullableSellerAccountMarketplaceRegistryTimestampSchema = sellerAccountMarketplaceRegistryTimestampSchema.nullable();
1312
+ var nonNegativeIntegerSchema = z2.number().int().nonnegative();
1313
+ var nullableNonNegativeIntegerSchema = nonNegativeIntegerSchema.nullable();
1314
+ var sellerAccountOrderTierSchema = z2.enum(SELLER_ACCOUNT_ORDER_TIER_IDS);
1315
+ var sellerAccountBillingStatusSchema = z2.enum(SELLER_ACCOUNT_BILLING_STATUSES);
1316
+ var sellerAccountBillingMeasurementSourceSchema = z2.enum(SELLER_ACCOUNT_BILLING_MEASUREMENT_SOURCES);
1317
+ var sellerAccountBillingMeasurementConfidenceSchema = z2.enum(
1318
+ SELLER_ACCOUNT_BILLING_MEASUREMENT_CONFIDENCES
1319
+ );
1320
+ var SELLER_ACCOUNT_MARKETPLACE_REGISTRY_STATUSES = ["draft", "verified", "superseded"];
1321
+ var SELLER_ACCOUNT_MARKETPLACE_CONNECTION_STATUSES = [
1322
+ "pending",
1323
+ "active",
1324
+ "reconnect_needed",
1325
+ "disconnected",
1326
+ "archived"
1327
+ ];
1328
+ var SELLER_ACCOUNT_RAW_ORDERS_COVERAGE_ROLES = ["candidate", "expected", "excluded"];
1329
+ var SELLER_ACCOUNT_MARKETPLACE_VERIFICATION_SOURCES = [
1330
+ "operator_verified",
1331
+ "amazon_discovery",
1332
+ "seller_central_oauth",
1333
+ "migration",
1334
+ "support_override"
1335
+ ];
1336
+ var sellerAccountMarketplaceRegistryStatusSchema = z2.enum(
1337
+ SELLER_ACCOUNT_MARKETPLACE_REGISTRY_STATUSES
1338
+ );
1339
+ var sellerAccountMarketplaceConnectionStatusSchema = z2.enum(
1340
+ SELLER_ACCOUNT_MARKETPLACE_CONNECTION_STATUSES
1341
+ );
1342
+ var sellerAccountRawOrdersCoverageRoleSchema = z2.enum(
1343
+ SELLER_ACCOUNT_RAW_ORDERS_COVERAGE_ROLES
1344
+ );
1345
+ var sellerAccountMarketplaceVerificationSourceSchema = z2.enum(
1346
+ SELLER_ACCOUNT_MARKETPLACE_VERIFICATION_SOURCES
1347
+ );
1348
+ var sellerAccountBillingMeasurementRowSchema = z2.object({
1349
+ measurement_id: nonEmptyStringSchema,
1350
+ tenant_id: nonEmptyStringSchema,
1351
+ connection_id: nonEmptyStringSchema,
1352
+ marketplace_id: nonEmptyStringSchema,
1353
+ period_start: dateSchema,
1354
+ period_end: dateSchema,
1355
+ reporting_time_zone: nonEmptyStringSchema,
1356
+ orders_30d: nullableNonNegativeIntegerSchema,
1357
+ units_30d: nullableNonNegativeIntegerSchema,
1358
+ source: sellerAccountBillingMeasurementSourceSchema,
1359
+ confidence: sellerAccountBillingMeasurementConfidenceSchema,
1360
+ computed_tier: sellerAccountOrderTierSchema,
1361
+ computed_at: timestampStringSchema,
1362
+ details_json: nullableStringSchema
1363
+ }).strict();
1364
+ var sellerAccountBillingStateRowSchema = z2.object({
1365
+ billing_state_id: nonEmptyStringSchema,
1366
+ tenant_id: nonEmptyStringSchema,
1367
+ connection_id: nonEmptyStringSchema,
1368
+ marketplace_id: nonEmptyStringSchema,
1369
+ billing_status: sellerAccountBillingStatusSchema,
1370
+ billing_tier: sellerAccountOrderTierSchema,
1371
+ pending_billing_tier: sellerAccountOrderTierSchema.nullable(),
1372
+ stripe_customer_id: nullableStringSchema,
1373
+ stripe_subscription_id: nullableStringSchema,
1374
+ stripe_subscription_item_id: nullableStringSchema,
1375
+ stripe_price_id: nullableStringSchema,
1376
+ last_measured_orders_30d: nullableNonNegativeIntegerSchema,
1377
+ last_measured_units_30d: nullableNonNegativeIntegerSchema,
1378
+ last_measurement_source: sellerAccountBillingMeasurementSourceSchema,
1379
+ last_measurement_confidence: sellerAccountBillingMeasurementConfidenceSchema,
1380
+ last_measured_period_start: nullableDateSchema,
1381
+ last_measured_period_end: nullableDateSchema,
1382
+ last_measured_at: nullableTimestampStringSchema,
1383
+ consecutive_months_below_tier: nonNegativeIntegerSchema,
1384
+ tier_effective_at: nullableTimestampStringSchema,
1385
+ pending_tier_effective_at: nullableTimestampStringSchema,
1386
+ manual_billing_override: z2.boolean(),
1387
+ manual_billing_override_reason: nullableStringSchema,
1388
+ created_at: timestampStringSchema,
1389
+ updated_at: timestampStringSchema
1390
+ }).strict();
1391
+ var sellerAccountBillingEventRowSchema = z2.object({
1392
+ event_id: nonEmptyStringSchema,
1393
+ tenant_id: nonEmptyStringSchema,
1394
+ connection_id: nonEmptyStringSchema,
1395
+ marketplace_id: nonEmptyStringSchema,
1396
+ event_type: nonEmptyStringSchema,
1397
+ from_tier: sellerAccountOrderTierSchema.nullable(),
1398
+ to_tier: sellerAccountOrderTierSchema.nullable(),
1399
+ orders_30d: nullableNonNegativeIntegerSchema,
1400
+ stripe_subscription_id: nullableStringSchema,
1401
+ stripe_subscription_item_id: nullableStringSchema,
1402
+ stripe_price_id: nullableStringSchema,
1403
+ effective_at: nullableTimestampStringSchema,
1404
+ metadata_json: nullableStringSchema,
1405
+ created_at: timestampStringSchema
1406
+ }).strict();
1407
+ var sellerAccountMarketplaceRegistryRowSchema = z2.object({
1408
+ registry_entry_id: nonEmptyStringSchema,
1409
+ registry_version_id: nonEmptyStringSchema,
1410
+ registry_status: sellerAccountMarketplaceRegistryStatusSchema,
1411
+ tenant_id: nonEmptyStringSchema,
1412
+ seller_id: nonEmptyStringSchema,
1413
+ connection_id: nonEmptyStringSchema,
1414
+ marketplace_id: nonEmptyStringSchema,
1415
+ country_code: nonEmptyStringSchema,
1416
+ currency_code: nonEmptyStringSchema,
1417
+ reporting_time_zone: nonEmptyStringSchema,
1418
+ connection_status: sellerAccountMarketplaceConnectionStatusSchema,
1419
+ raw_orders_coverage_role: sellerAccountRawOrdersCoverageRoleSchema,
1420
+ raw_orders_coverage_start_date: nullableSellerAccountMarketplaceRegistryDateSchema,
1421
+ raw_orders_coverage_end_date: nullableSellerAccountMarketplaceRegistryDateSchema,
1422
+ coverage_exclusion_reason: nullableStringSchema,
1423
+ verification_source: sellerAccountMarketplaceVerificationSourceSchema,
1424
+ verified_at: nullableSellerAccountMarketplaceRegistryTimestampSchema,
1425
+ evidence_json: nullableStringSchema,
1426
+ created_at: sellerAccountMarketplaceRegistryTimestampSchema,
1427
+ updated_at: sellerAccountMarketplaceRegistryTimestampSchema
1428
+ }).strict().superRefine((row, ctx) => {
1429
+ if (row.marketplace_id === "seller_account") {
1430
+ ctx.addIssue({
1431
+ code: z2.ZodIssueCode.custom,
1432
+ path: ["marketplace_id"],
1433
+ message: "marketplace_id must be an actual Amazon marketplace ID, not seller_account"
1434
+ });
1435
+ } else if (!getMarketplaceDefinition(row.marketplace_id)) {
1436
+ ctx.addIssue({
1437
+ code: z2.ZodIssueCode.custom,
1438
+ path: ["marketplace_id"],
1439
+ message: "marketplace_id must be a supported canonical Amazon marketplace ID"
1440
+ });
1441
+ }
1442
+ if (row.registry_status === "verified" && row.raw_orders_coverage_role === "candidate") {
1443
+ ctx.addIssue({
1444
+ code: z2.ZodIssueCode.custom,
1445
+ path: ["raw_orders_coverage_role"],
1446
+ message: "verified registry versions cannot contain unresolved candidate marketplaces"
1447
+ });
1448
+ }
1449
+ if (row.registry_status === "verified" && !row.verified_at) {
1450
+ ctx.addIssue({
1451
+ code: z2.ZodIssueCode.custom,
1452
+ path: ["verified_at"],
1453
+ message: "verified registry rows require verified_at"
1454
+ });
1455
+ }
1456
+ if (row.raw_orders_coverage_role === "expected" && !row.raw_orders_coverage_start_date) {
1457
+ ctx.addIssue({
1458
+ code: z2.ZodIssueCode.custom,
1459
+ path: ["raw_orders_coverage_start_date"],
1460
+ message: "expected raw-orders coverage rows require raw_orders_coverage_start_date"
1461
+ });
1462
+ }
1463
+ if (row.raw_orders_coverage_role === "excluded" && !row.coverage_exclusion_reason) {
1464
+ ctx.addIssue({
1465
+ code: z2.ZodIssueCode.custom,
1466
+ path: ["coverage_exclusion_reason"],
1467
+ message: "excluded raw-orders coverage rows require coverage_exclusion_reason"
1468
+ });
1469
+ }
1470
+ });
1471
+ var baseToolParams = {
1472
+ start_date: optionalDateParam("Optional. YYYY-MM-DD. Defaults to 30 days ago if omitted."),
1473
+ end_date: optionalDateParam("Optional. YYYY-MM-DD. Defaults to today if omitted."),
1474
+ profile_id: z2.string().optional().describe("Filter by profile ID"),
1475
+ campaign_name: z2.string().optional().describe("Filter by campaign name (LIKE match, use % for wildcards)"),
1476
+ sort_order: z2.enum(["asc", "desc"]).default("desc").describe("Sort order"),
1477
+ limit: toolLimitParam()
1478
+ };
1479
+ var baseInventoryParams = {
1480
+ asin: z2.string().optional().describe("Filter by ASIN"),
1481
+ sku: z2.string().optional().describe("Filter by SKU"),
1482
+ sort_order: z2.enum(["asc", "desc"]).default("desc").describe("Sort order"),
1483
+ limit: toolLimitParam()
1484
+ };
1485
+ var DISABLE_WRITE_TOOLS_FOR_DOMAIN_PREFIX = "__write_tools_disabled__:";
1486
+ var TOOL_DOMAINS = [
1487
+ {
1488
+ name: "Ads",
1489
+ serverDomain: "ads",
1490
+ tools: [
1491
+ { name: "get_campaign_performance", description: "Campaign health, spend, and ACOS metrics" },
1492
+ { name: "get_campaign_snapshots", description: "Campaign setting history and change detection" },
1493
+ { name: "get_ads_change_history", description: "Timestamped Amazon Ads entity change events" },
1494
+ { name: "get_adgroup_performance", description: "Ad group level performance breakdown" },
1495
+ { name: "get_keyword_performance", description: "Keyword bid and targeting analysis" },
1496
+ { name: "get_product_performance", description: "Sponsored Products advertised-ASIN performance" },
1497
+ { name: "get_purchased_products", description: "Products purchased from ad clicks" },
1498
+ { name: "get_search_terms", description: "SP/SB customer search terms that triggered ads" },
1499
+ { name: "get_placement_breakdown", description: "Performance by ad placement" },
1500
+ { name: "get_sb_campaign_performance", description: "Sponsored Brands campaign metrics" },
1501
+ { name: "get_sd_campaign_performance", description: "Sponsored Display campaign metrics" },
1502
+ { name: "get_sponsored_ads_report", description: "Consolidated SP/SB/SD retained report views" },
1503
+ { name: "get_dsp_performance", description: "Amazon DSP order, line item, and creative metrics" },
1504
+ { name: "get_dsp_advertisers_live", description: "Live Amazon DSP advertiser records" },
1505
+ { name: "get_dsp_entities_live", description: "Live Amazon DSP campaigns, ad groups, and targets" },
1506
+ { name: "get_store_performance", description: "Brand Store traffic, page, source, tag, and sales insights" },
1507
+ { name: "get_portfolio_performance", description: "Sponsored Products portfolio-level performance rollups" },
1508
+ { name: "get_sales_and_traffic", description: "Sales and traffic by ASIN" },
1509
+ { name: "get_tacos", description: "Total ad cost of sales per ASIN" },
1510
+ { name: "get_search_query_performance", description: "Market share and conversion data" },
1511
+ { name: "get_repeat_purchase_behavior", description: "Brand Analytics repeat-purchase behavior by ASIN" },
1512
+ { name: "get_search_query_ad_coverage", description: "Search queries with and without ad coverage" },
1513
+ { name: "diagnose_performance", description: "SP/SB/SD root cause analysis between date ranges" },
1514
+ { name: "get_sp_entities_live", description: "Live Sponsored Products entity state from Amazon" },
1515
+ { name: "get_sponsored_ads_entities_live", description: "Live SP/SB/SD entity state from Amazon" },
1516
+ { name: "get_sp_targeting_options", description: "Targeting candidates, categories, and negative brands" },
1517
+ { name: "get_sponsored_ads_targeting_options", description: "Live SP/SB/SD targeting options and bid fields" },
1518
+ { name: "create_sb_campaigns", description: "Preview or create Sponsored Brands campaigns", write: true },
1519
+ { name: "update_sb_campaign_budget", description: "Preview or update Sponsored Brands campaign budgets", write: true },
1520
+ { name: "update_sb_campaign_state", description: "Preview or set Sponsored Brands campaign state", write: true },
1521
+ { name: "archive_sb_campaigns", description: "Preview or archive Sponsored Brands campaigns", write: true },
1522
+ { name: "create_sb_ad_groups", description: "Preview or create Sponsored Brands ad groups", write: true },
1523
+ { name: "update_sb_ad_group_state", description: "Preview or set Sponsored Brands ad group state", write: true },
1524
+ { name: "archive_sb_ad_groups", description: "Preview or archive Sponsored Brands ad groups", write: true },
1525
+ { name: "create_sb_ads", description: "Preview or create Sponsored Brands ads with caller-supplied creative", write: true },
1526
+ { name: "update_sb_ad_state", description: "Preview or set Sponsored Brands ad state", write: true },
1527
+ { name: "archive_sb_ads", description: "Preview or archive Sponsored Brands ads", write: true },
1528
+ { name: "create_sb_targets", description: "Preview or create Sponsored Brands targets", write: true },
1529
+ { name: "update_sb_target_bids", description: "Preview or update Sponsored Brands target bids", write: true },
1530
+ { name: "update_sb_target_state", description: "Preview or set Sponsored Brands target state", write: true },
1531
+ { name: "archive_sb_targets", description: "Preview or archive Sponsored Brands targets", write: true },
1532
+ { name: "create_sb_negative_targets", description: "Preview or create Sponsored Brands negative targets", write: true },
1533
+ { name: "update_sb_negative_target_state", description: "Preview or set Sponsored Brands negative target state", write: true },
1534
+ { name: "archive_sb_negative_targets", description: "Preview or archive Sponsored Brands negative targets", write: true },
1535
+ { name: "update_keyword_bids", description: "Preview or adjust keyword bids", write: true },
1536
+ { name: "update_target_bids", description: "Preview or adjust Sponsored Products target bids", write: true },
1537
+ { name: "update_keyword_state", description: "Preview or set keyword state", write: true },
1538
+ { name: "archive_keywords", description: "Preview or archive keywords", write: true },
1539
+ { name: "update_adgroup_bid", description: "Preview or update ad group default bids", write: true },
1540
+ { name: "update_campaign_bidding", description: "Preview or adjust placement bid modifiers", write: true },
1541
+ { name: "update_campaign_budget", description: "Preview or change daily campaign budget", write: true },
1542
+ { name: "update_campaign_state", description: "Preview or set campaign state", write: true },
1543
+ { name: "archive_campaigns", description: "Preview or archive Sponsored Products campaigns", write: true },
1544
+ { name: "create_sd_campaigns", description: "Preview or create Sponsored Display campaigns", write: true },
1545
+ { name: "update_sd_campaign_budget", description: "Preview or update Sponsored Display campaign budgets", write: true },
1546
+ { name: "update_sd_campaign_state", description: "Preview or set Sponsored Display campaign state", write: true },
1547
+ { name: "archive_sd_campaigns", description: "Preview or archive Sponsored Display campaigns", write: true },
1548
+ { name: "create_sd_ad_groups", description: "Preview or create Sponsored Display ad groups", write: true },
1549
+ { name: "update_sd_ad_group_bid", description: "Preview or update Sponsored Display ad group default bids", write: true },
1550
+ { name: "update_sd_ad_group_state", description: "Preview or set Sponsored Display ad group state", write: true },
1551
+ { name: "archive_sd_ad_groups", description: "Preview or archive Sponsored Display ad groups", write: true },
1552
+ { name: "create_sd_product_ads", description: "Preview or create Sponsored Display product ads", write: true },
1553
+ { name: "update_sd_product_ad_state", description: "Preview or set Sponsored Display product ad state", write: true },
1554
+ { name: "archive_sd_product_ads", description: "Preview or archive Sponsored Display product ads", write: true },
1555
+ { name: "create_sd_targets", description: "Preview or create Sponsored Display targets", write: true },
1556
+ { name: "update_sd_target_bids", description: "Preview or update Sponsored Display target bids", write: true },
1557
+ { name: "update_sd_target_state", description: "Preview or set Sponsored Display target state", write: true },
1558
+ { name: "archive_sd_targets", description: "Preview or archive Sponsored Display targets", write: true },
1559
+ { name: "create_sd_negative_targets", description: "Preview or create Sponsored Display negative targets", write: true },
1560
+ { name: "update_sd_negative_target_state", description: "Preview or set Sponsored Display negative target state", write: true },
1561
+ { name: "archive_sd_negative_targets", description: "Preview or archive Sponsored Display negative targets", write: true },
1562
+ { name: "update_campaign_audience_bid_adjustment", description: "Preview or set audience bid adjustments", write: true },
1563
+ { name: "create_keywords", description: "Preview or add keywords", write: true },
1564
+ { name: "create_negative_keywords", description: "Preview or add negative keywords", write: true },
1565
+ { name: "create_sp_campaigns", description: "Preview or create Sponsored Products campaigns", write: true },
1566
+ { name: "create_sp_ad_groups", description: "Preview or create Sponsored Products ad groups", write: true },
1567
+ { name: "create_sp_product_ads", description: "Preview or create Sponsored Products product ads", write: true },
1568
+ { name: "update_sp_ad_entities", description: "Preview or update/archive Sponsored Products ad groups and product ads", write: true },
1569
+ { name: "create_sp_targets", description: "Preview or create Sponsored Products targeting clauses", write: true },
1570
+ { name: "update_sp_target_state", description: "Preview or set Sponsored Products target state", write: true },
1571
+ { name: "archive_sp_targets", description: "Preview or archive Sponsored Products targets", write: true },
1572
+ { name: "create_sp_negative_targets", description: "Preview or create Sponsored Products negative ASIN/brand targets", write: true },
1573
+ { name: "update_sp_negative_keyword_state", description: "Preview or set Sponsored Products negative keyword state", write: true },
1574
+ { name: "archive_sp_negative_keywords", description: "Preview or archive Sponsored Products negative keywords", write: true },
1575
+ { name: "update_sp_negative_target_state", description: "Preview or set Sponsored Products negative target state", write: true },
1576
+ { name: "archive_sp_negative_targets", description: "Preview or archive Sponsored Products negative targets", write: true },
1577
+ { name: "get_bid_recommendations", description: "Live suggested bids from Amazon" },
1578
+ { name: "get_budget_recommendations", description: "Live Amazon budget suggestion fields" },
1579
+ { name: "get_budget_pacing", description: "Daily campaign budget usage and pacing snapshots" },
1580
+ { name: "get_ad_eligibility", description: "Check ASIN eligibility for ad types" },
1581
+ { name: "get_brand_health", description: "Brand Metrics funnel and peer benchmarks" },
1582
+ { name: "get_share_of_voice", description: "Brand Metrics visibility and engagement signals" },
1583
+ { name: "get_attribution_performance", description: "Off-Amazon Amazon Attribution performance" },
1584
+ { name: "get_audience_segments", description: "Live Amazon Ads audience segment discovery" }
1585
+ ]
1586
+ },
1587
+ {
1588
+ name: "Inventory",
1589
+ serverDomain: "inventory",
1590
+ tools: [
1591
+ { name: "get_fba_inventory", description: "FBA stock levels and quantities" },
1592
+ { name: "get_inventory_health", description: "Age buckets, weeks of cover, storage fee exposure" },
1593
+ { name: "get_fba_storage_fees", description: "FBA monthly and long-term storage fee rows by ASIN/FNSKU/SKU" },
1594
+ { name: "get_inventory_movements", description: "Inventory change history" },
1595
+ { name: "get_inventory_by_fulfillment_center", description: "Stock levels per fulfillment center" },
1596
+ { name: "get_awd_inventory", description: "AWD inbound and on-hand stock" },
1597
+ { name: "get_awd_shipments", description: "AWD shipment tracking" },
1598
+ { name: "get_awd_shipment_items", description: "Per-SKU AWD shipment quantities" },
1599
+ { name: "get_inbound_shipments", description: "FBA inbound shipment tracking" },
1600
+ { name: "get_shipment_receiving_status", description: "Per-SKU receiving progress" },
1601
+ { name: "get_sales_velocity", description: "Daily sales and traffic time series" },
1602
+ { name: "get_listing_registry", description: "Active listing registry, search, and brand ASIN views" },
1603
+ { name: "get_suppressed_listings", description: "Suppressed and stranded listings" },
1604
+ { name: "get_days_of_cover", description: "Days of stock remaining" },
1605
+ { name: "get_todays_sales", description: "Today's priced/estimated revenue by ASIN" },
1606
+ { name: "get_orders", description: "Order list with filters" },
1607
+ { name: "get_order_details", description: "Per-order line items" },
1608
+ { name: "get_returns", description: "FBA return records" },
1609
+ { name: "get_reimbursements", description: "FBA reimbursement records" },
1610
+ { name: "get_seasonality_index", description: "52-week demand curve with events" },
1611
+ { name: "get_sales_summary", description: "Daily final/priced revenue and estimates" },
1612
+ { name: "get_inventory_risk_triage", description: "SKUs at risk: low stock, overstock, aged, or stranded" },
1613
+ { name: "get_current_rank", description: "Live keyword rank check via catalog search" },
1614
+ { name: "get_buybox_status", description: "Live Buy Box status plus daily win-rate history" },
1615
+ { name: "get_competitive_pricing", description: "Live price points plus historical pricing snapshots" },
1616
+ { name: "get_offer_listings", description: "Live seller offers for an ASIN" },
1617
+ { name: "get_subscribe_and_save", description: "Subscribe & Save offer status, history, and Amazon-provided metrics" },
1618
+ { name: "get_fba_eligibility", description: "Check FBA eligibility per ASIN" },
1619
+ { name: "get_listing_restrictions", description: "Listing restrictions and approvals" }
1620
+ ]
1621
+ },
1622
+ {
1623
+ name: "Finance",
1624
+ serverDomain: "finance",
1625
+ tools: [
1626
+ { name: "get_financial_events", description: "Financial event fee breakdown by ASIN/order and profitability views" },
1627
+ { name: "get_profitability_review", description: "Per-ASIN profitability across fees, returns, and ad spend" },
1628
+ { name: "get_payment_transactions", description: "Live Amazon Payments transaction rows and summaries" },
1629
+ { name: "get_settlement_economics", description: "Settlement-finalized financial data" }
1630
+ ]
1631
+ },
1632
+ {
1633
+ name: "Catalog",
1634
+ serverDomain: "catalog",
1635
+ tools: [
1636
+ { name: "get_product_details", description: "Product info, images, dimensions" },
1637
+ { name: "get_sales_ranks", description: "Best seller rank by category" },
1638
+ { name: "get_aplus_status", description: "A+ Content status and associated ASINs" },
1639
+ { name: "get_variations", description: "Parent/child variation relationships" },
1640
+ { name: "get_product_reviews", description: "Customer review topics and snippets" },
1641
+ { name: "get_review_trends", description: "Six-month review topic trends" },
1642
+ { name: "get_listing_quality", description: "Listing completeness scores and issues" },
1643
+ { name: "get_catalog_cleanup", description: "Listings with quality issues to fix" },
1644
+ { name: "create_listing", description: "Validate or submit a listing creation request", write: true },
1645
+ { name: "update_listing", description: "Update listing attributes with preview and audit trail", write: true },
1646
+ { name: "update_price", description: "Submit listing price updates through the Listings Items API", write: true },
1647
+ { name: "update_inventory_quantity", description: "Update seller-fulfilled listing quantities", write: true }
1648
+ ]
1649
+ },
1650
+ {
1651
+ name: "Ranking",
1652
+ serverDomain: "ranking",
1653
+ tools: [
1654
+ { name: "get_keyword_ranks", description: "Keyword rank positions, changes, and SQP volume views" }
1655
+ ]
1656
+ },
1657
+ {
1658
+ name: "Fulfillment",
1659
+ serverDomain: "fulfillment",
1660
+ tools: [
1661
+ { name: "get_shipping_preview", description: "MCF shipping options and cost estimates" },
1662
+ { name: "get_mcf_orders", description: "Multi-Channel Fulfillment order list" },
1663
+ { name: "create_mcf_order", description: "Submit MCF order request from FBA inventory", write: true },
1664
+ { name: "manage_returns", description: "MCF return authorization", write: true }
1665
+ ]
1666
+ }
1667
+ ];
1668
+ var DISABLED_WRITE_TOOL_MARKERS = TOOL_DOMAINS.map(
1669
+ (domain) => `${DISABLE_WRITE_TOOLS_FOR_DOMAIN_PREFIX}${domain.serverDomain}`
1670
+ );
1671
+ var UTILITY_TOOLS = [
1672
+ {
1673
+ name: "get_account_data_tour",
1674
+ description: "Return a first-run account data tour with trust preflight, business pulse, spotlight products, neutral cross-domain signals, and evidence handles"
1675
+ },
1676
+ {
1677
+ name: "submit_conversation_feedback",
1678
+ description: "Submit a redacted structured product-quality report after the user explicitly asks agentcentral to receive feedback"
1679
+ },
1680
+ {
1681
+ name: "get_account_info",
1682
+ description: "Return the marketplace scope, connection status, tool availability, and next-step guidance for the active API key"
1683
+ },
1684
+ {
1685
+ name: "get_action_history",
1686
+ description: "Return tenant-wide write audit history when the active API key has action-history read permission"
1687
+ }
1688
+ ];
1689
+ var TOOL_COUNTS_BY_DOMAIN = TOOL_DOMAINS.reduce(
1690
+ (counts, domain) => {
1691
+ counts[domain.serverDomain] = {
1692
+ domainTools: domain.tools.length,
1693
+ writeTools: domain.tools.filter((tool) => tool.write).length
1694
+ };
1695
+ return counts;
1696
+ },
1697
+ {}
1698
+ );
1699
+ var DATA_DOMAIN_COUNT = TOOL_DOMAINS.length;
1700
+ var DOMAIN_SCOPED_TOOL_COUNT = TOOL_DOMAINS.reduce((sum, domain) => sum + domain.tools.length, 0);
1701
+ var UTILITY_TOOL_COUNT = UTILITY_TOOLS.length;
1702
+ var SHIPPED_TOOL_COUNT = DOMAIN_SCOPED_TOOL_COUNT + UTILITY_TOOL_COUNT;
1703
+ var WRITE_TOOL_COUNT = TOOL_DOMAINS.reduce(
1704
+ (sum, domain) => sum + domain.tools.filter((tool) => tool.write).length,
1705
+ 0
1706
+ );
1707
+ var TOOL_NAMES = /* @__PURE__ */ new Set(
1708
+ [
1709
+ ...TOOL_DOMAINS.flatMap((d) => d.tools.map((t) => t.name)),
1710
+ ...UTILITY_TOOLS.map((t) => t.name)
1711
+ ]
1712
+ );
1713
+ var DOMAIN_WRITE_TOOL_NAMES = new Set(
1714
+ TOOL_DOMAINS.flatMap(
1715
+ (domain) => domain.tools.filter((tool) => tool.write).map((tool) => tool.name)
1716
+ )
1717
+ );
1718
+ var VALID_DISABLED_TOOL_NAMES = /* @__PURE__ */ new Set([
1719
+ ...TOOL_NAMES,
1720
+ ...DISABLED_WRITE_TOOL_MARKERS
1721
+ ]);
1722
+ var CURRENT_WRITE_TOOL_NAMES_BY_DOMAIN = TOOL_DOMAINS.reduce(
1723
+ (byDomain, domain) => {
1724
+ byDomain[domain.serverDomain] = domain.tools.filter((tool) => tool.write).map((tool) => tool.name);
1725
+ return byDomain;
1726
+ },
1727
+ {}
1728
+ );
1729
+ var DATA_COVERAGE_STATUSES = ["success", "partial", "failure"];
1730
+ var DATA_COVERAGE_GRANULARITIES = ["day", "week", "month", "quarter", "snapshot", "event"];
1731
+ var DataCoverageStatusSchema = z22.enum(DATA_COVERAGE_STATUSES);
1732
+ var DataCoverageGranularitySchema = z22.enum(DATA_COVERAGE_GRANULARITIES);
1733
+ var DataCoverageRowSchema = z22.object({
1734
+ coverage_id: z22.string(),
1735
+ tenant_id: z22.string(),
1736
+ sync_mode: z22.string(),
1737
+ table_name: z22.string(),
1738
+ source_type: z22.string(),
1739
+ coverage_granularity: DataCoverageGranularitySchema,
1740
+ coverage_start_date: z22.string().nullable(),
1741
+ coverage_end_date: z22.string().nullable(),
1742
+ marketplace_id: z22.string().nullable(),
1743
+ connection_id: z22.string().nullable().optional(),
1744
+ profile_id: z22.string().nullable(),
1745
+ status: DataCoverageStatusSchema,
1746
+ rows_loaded: z22.number().int().nonnegative(),
1747
+ checked_at: z22.string(),
1748
+ error_message: z22.string().nullable(),
1749
+ trigger_source: z22.string(),
1750
+ snapshot_date: z22.string()
1751
+ });
1752
+ var ADS_DAILY_LAG_DAYS = 1;
1753
+ var ADS_LOOKBACK_DAYS = 14;
1754
+ var SP_DAILY_LAG_DAYS = 1;
1755
+ var SP_LOOKBACK_DAYS = 14;
1756
+ var SNAPSHOT_FRESHNESS_HOURS = 36;
1757
+ var WEEKLY_LAG_DAYS = 8;
1758
+ var DATA_HEALTH_TABLE_POLICIES = [
1759
+ { syncMode: "campaign_snapshots", tableName: TABLES.campaignSnapshots, label: "SP campaign entity snapshot", coverageGranularity: "snapshot", required: true, freshnessHours: SNAPSHOT_FRESHNESS_HOURS },
1760
+ { syncMode: "ad_change_history", tableName: TABLES.adsChangeHistory, label: "Amazon Ads change history", coverageGranularity: "event", required: false, expectedLagDays: ADS_DAILY_LAG_DAYS, lookbackDays: 90 },
1761
+ { syncMode: "budget_usage", tableName: TABLES.budgetUsage, label: "SP budget usage snapshot", coverageGranularity: "snapshot", required: false, freshnessHours: SNAPSHOT_FRESHNESS_HOURS },
1762
+ { syncMode: "attribution", tableName: TABLES.attributionPerformance, label: "Amazon Attribution", coverageGranularity: "day", required: false, expectedLagDays: ADS_DAILY_LAG_DAYS, lookbackDays: ADS_LOOKBACK_DAYS },
1763
+ { syncMode: "dsp_reporting", tableName: TABLES.dspPerformance, label: "DSP performance", coverageGranularity: "day", required: false, expectedLagDays: ADS_DAILY_LAG_DAYS, lookbackDays: ADS_LOOKBACK_DAYS },
1764
+ { syncMode: "store_insights", tableName: TABLES.storeInsights, label: "Brand Store insights", coverageGranularity: "day", required: false, expectedLagDays: ADS_DAILY_LAG_DAYS, lookbackDays: ADS_LOOKBACK_DAYS },
1765
+ { syncMode: "ads", tableName: TABLES.campaigns, label: "SP campaigns", coverageGranularity: "day", required: true, expectedLagDays: ADS_DAILY_LAG_DAYS, lookbackDays: ADS_LOOKBACK_DAYS },
1766
+ { syncMode: "ads", tableName: TABLES.adgroups, label: "SP ad groups", coverageGranularity: "day", required: true, expectedLagDays: ADS_DAILY_LAG_DAYS, lookbackDays: ADS_LOOKBACK_DAYS },
1767
+ { syncMode: "ads", tableName: TABLES.placements, label: "SP placements", coverageGranularity: "day", required: true, expectedLagDays: ADS_DAILY_LAG_DAYS, lookbackDays: ADS_LOOKBACK_DAYS },
1768
+ { syncMode: "ads", tableName: TABLES.advertisedProducts, label: "SP advertised products", coverageGranularity: "day", required: true, expectedLagDays: ADS_DAILY_LAG_DAYS, lookbackDays: ADS_LOOKBACK_DAYS },
1769
+ { syncMode: "ads", tableName: TABLES.purchasedProducts, label: "SP purchased products", coverageGranularity: "day", required: true, expectedLagDays: ADS_DAILY_LAG_DAYS, lookbackDays: ADS_LOOKBACK_DAYS },
1770
+ { syncMode: "ads", tableName: TABLES.searchTerms, label: "SP search terms", coverageGranularity: "day", required: true, expectedLagDays: ADS_DAILY_LAG_DAYS, lookbackDays: ADS_LOOKBACK_DAYS },
1771
+ { syncMode: "ads", tableName: TABLES.targeting, label: "SP targeting", coverageGranularity: "day", required: true, expectedLagDays: ADS_DAILY_LAG_DAYS, lookbackDays: ADS_LOOKBACK_DAYS },
1772
+ { syncMode: "ads", tableName: TABLES.spGrossAndInvalids, label: "SP gross and invalid traffic", coverageGranularity: "day", required: false, expectedLagDays: ADS_DAILY_LAG_DAYS, lookbackDays: ADS_LOOKBACK_DAYS },
1773
+ { syncMode: "sb_ads", tableName: TABLES.sbCampaigns, label: "SB campaigns", coverageGranularity: "day", required: true, expectedLagDays: ADS_DAILY_LAG_DAYS, lookbackDays: ADS_LOOKBACK_DAYS },
1774
+ { syncMode: "sb_ads", tableName: TABLES.sbAds, label: "SB ads", coverageGranularity: "day", required: true, expectedLagDays: ADS_DAILY_LAG_DAYS, lookbackDays: ADS_LOOKBACK_DAYS },
1775
+ { syncMode: "sb_ads", tableName: TABLES.sbSearchTerms, label: "SB search terms", coverageGranularity: "day", required: true, expectedLagDays: ADS_DAILY_LAG_DAYS, lookbackDays: ADS_LOOKBACK_DAYS },
1776
+ { syncMode: "sb_ads", tableName: TABLES.sbTargeting, label: "SB targeting", coverageGranularity: "day", required: true, expectedLagDays: ADS_DAILY_LAG_DAYS, lookbackDays: ADS_LOOKBACK_DAYS },
1777
+ { syncMode: "sb_ads", tableName: TABLES.sbPurchasedProducts, label: "SB purchased products", coverageGranularity: "day", required: true, expectedLagDays: ADS_DAILY_LAG_DAYS, lookbackDays: ADS_LOOKBACK_DAYS },
1778
+ { syncMode: "sb_ads", tableName: TABLES.sbGrossAndInvalids, label: "SB gross and invalid traffic", coverageGranularity: "day", required: false, expectedLagDays: ADS_DAILY_LAG_DAYS, lookbackDays: ADS_LOOKBACK_DAYS },
1779
+ { syncMode: "sd_ads", tableName: TABLES.sdCampaigns, label: "SD campaigns", coverageGranularity: "day", required: true, expectedLagDays: ADS_DAILY_LAG_DAYS, lookbackDays: ADS_LOOKBACK_DAYS },
1780
+ { syncMode: "sd_ads", tableName: TABLES.sdAdvertisedProducts, label: "SD advertised products", coverageGranularity: "day", required: true, expectedLagDays: ADS_DAILY_LAG_DAYS, lookbackDays: ADS_LOOKBACK_DAYS },
1781
+ { syncMode: "sd_ads", tableName: TABLES.sdTargeting, label: "SD targeting", coverageGranularity: "day", required: true, expectedLagDays: ADS_DAILY_LAG_DAYS, lookbackDays: ADS_LOOKBACK_DAYS },
1782
+ { syncMode: "sd_ads", tableName: TABLES.sdPurchasedProducts, label: "SD purchased products", coverageGranularity: "day", required: true, expectedLagDays: ADS_DAILY_LAG_DAYS, lookbackDays: ADS_LOOKBACK_DAYS },
1783
+ { syncMode: "sd_ads", tableName: TABLES.sdGrossAndInvalids, label: "SD gross and invalid traffic", coverageGranularity: "day", required: false, expectedLagDays: ADS_DAILY_LAG_DAYS, lookbackDays: ADS_LOOKBACK_DAYS },
1784
+ { syncMode: "business", tableName: TABLES.salesAndTraffic, label: "Sales and traffic", coverageGranularity: "day", required: true, expectedLagDays: SP_DAILY_LAG_DAYS, lookbackDays: SP_LOOKBACK_DAYS },
1785
+ { syncMode: "inventory", tableName: TABLES.inventoryLedger, label: "Inventory ledger", coverageGranularity: "day", required: true, expectedLagDays: SP_DAILY_LAG_DAYS, lookbackDays: SP_LOOKBACK_DAYS },
1786
+ { syncMode: "returns", tableName: TABLES.returns, label: "FBA returns", coverageGranularity: "day", required: true, expectedLagDays: 2, lookbackDays: 30 },
1787
+ { syncMode: "reimbursements", tableName: TABLES.reimbursements, label: "FBA reimbursements", coverageGranularity: "day", required: true, expectedLagDays: 2, lookbackDays: 14 },
1788
+ { syncMode: "order_metrics", tableName: TABLES.orderMetrics, label: "Order metrics", coverageGranularity: "snapshot", required: true, freshnessHours: SNAPSHOT_FRESHNESS_HOURS },
1789
+ { syncMode: "sqp", tableName: TABLES.sqp, label: "Search Query Performance", coverageGranularity: "week", required: true, expectedLagDays: WEEKLY_LAG_DAYS, lookbackDays: 35 },
1790
+ { syncMode: "brand_metrics", tableName: TABLES.brandMetrics, label: "Brand Metrics", coverageGranularity: "week", required: false, expectedLagDays: WEEKLY_LAG_DAYS, lookbackDays: 35 },
1791
+ { syncMode: "ba_search_terms", tableName: TABLES.baSearchTerms, label: "Brand Analytics search terms", coverageGranularity: "week", required: false, expectedLagDays: WEEKLY_LAG_DAYS, lookbackDays: 35 },
1792
+ { syncMode: "ba_market_basket", tableName: TABLES.baMarketBasket, label: "Brand Analytics market basket", coverageGranularity: "week", required: false, expectedLagDays: WEEKLY_LAG_DAYS, lookbackDays: 35 },
1793
+ { syncMode: "ba_repeat_purchase", tableName: TABLES.baRepeatPurchase, label: "Brand Analytics repeat purchase", coverageGranularity: "week", required: false, expectedLagDays: WEEKLY_LAG_DAYS, lookbackDays: 35 },
1794
+ { syncMode: "ba_search_catalog", tableName: TABLES.baSearchCatalog, label: "Brand Analytics search catalog", coverageGranularity: "week", required: false, expectedLagDays: WEEKLY_LAG_DAYS, lookbackDays: 35 },
1795
+ { syncMode: "inventory", tableName: TABLES.fbaInventory, label: "FBA inventory snapshot", coverageGranularity: "snapshot", required: true, freshnessHours: SNAPSHOT_FRESHNESS_HOURS },
1796
+ { syncMode: "inventory", tableName: TABLES.inventoryHealth, label: "Inventory health snapshot", coverageGranularity: "snapshot", required: true, freshnessHours: SNAPSHOT_FRESHNESS_HOURS },
1797
+ { syncMode: "listings", tableName: TABLES.activeListings, label: "Active listings snapshot", coverageGranularity: "snapshot", required: true, freshnessHours: SNAPSHOT_FRESHNESS_HOURS },
1798
+ { syncMode: "suppressed_listings", tableName: TABLES.suppressedListings, label: "Suppressed listings snapshot", coverageGranularity: "snapshot", required: false, freshnessHours: SNAPSHOT_FRESHNESS_HOURS },
1799
+ { syncMode: "awd", tableName: TABLES.awdInventory, label: "AWD inventory snapshot", coverageGranularity: "snapshot", required: false, freshnessHours: SNAPSHOT_FRESHNESS_HOURS },
1800
+ { syncMode: "fba_inbound", tableName: TABLES.fbaInboundShipments, label: "FBA inbound shipments", coverageGranularity: "snapshot", required: false, freshnessHours: 36 },
1801
+ { syncMode: "fees", tableName: TABLES.referralFees, label: "Referral fees snapshot", coverageGranularity: "snapshot", required: false, freshnessHours: 168 },
1802
+ { syncMode: "fees", tableName: TABLES.fbaStorageFeeCharges, label: "FBA storage fee charges", coverageGranularity: "snapshot", required: false, freshnessHours: 168 },
1803
+ { syncMode: "fees", tableName: TABLES.fbaLongTermStorageFeeCharges, label: "FBA long-term storage fee charges", coverageGranularity: "day", required: false, expectedLagDays: 35, lookbackDays: 45 },
1804
+ { syncMode: "catalog", tableName: TABLES.catalogItems, label: "Catalog snapshot", coverageGranularity: "snapshot", required: true, freshnessHours: 48 },
1805
+ { syncMode: "listing_quality", tableName: TABLES.listingQuality, label: "Listing quality snapshot", coverageGranularity: "snapshot", required: false, freshnessHours: 192 },
1806
+ { syncMode: "pricing", tableName: TABLES.pricingSnapshots, label: "Pricing snapshot", coverageGranularity: "snapshot", required: false, freshnessHours: 48 },
1807
+ { syncMode: "replenishment", tableName: TABLES.replenishmentOffers, label: "Replenishment offers snapshot", coverageGranularity: "snapshot", required: false, freshnessHours: 48 },
1808
+ { syncMode: "customer_feedback", tableName: TABLES.customerFeedbackSnapshots, label: "Customer Feedback snapshot", coverageGranularity: "snapshot", required: false, freshnessHours: 192 },
1809
+ { syncMode: "keyword_rank", tableName: TABLES.keywordRanks, label: "Keyword rank snapshot", coverageGranularity: "snapshot", required: false, freshnessHours: 192 },
1810
+ { syncMode: "settlements", tableName: TABLES.settlements, label: "Settlements reports", coverageGranularity: "event", required: true, freshnessHours: 72 },
1811
+ { syncMode: "financial_events", tableName: TABLES.financialEvents, label: "Financial events", coverageGranularity: "event", required: true, freshnessHours: 36 }
1812
+ ];
1813
+ var MAX_REPORT_SECTIONS = 12;
1814
+ var MAX_REPORT_KPIS = 12;
1815
+ var MAX_REPORT_TABLE_ROWS = 250;
1816
+ var MAX_REPORT_CHART_ROWS = 120;
1817
+ var MAX_REPORT_CHART_SERIES = 6;
1818
+ var MAX_REPORT_COLUMNS = 12;
1819
+ var MAX_REPORT_SPEC_BYTES = 512 * 1024;
1820
+ var KEY_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]{0,63}$/;
1821
+ var ANCHOR_PATTERN = /^[a-zA-Z][a-zA-Z0-9_-]{0,79}$/;
1822
+ var shortText = (max) => z3.string().trim().min(1).max(max);
1823
+ var optionalText = (max) => z3.preprocess(
1824
+ (value) => value === null || value === "" ? void 0 : value,
1825
+ z3.string().trim().min(1).max(max).optional()
1826
+ );
1827
+ var reportKeySchema = z3.string().regex(KEY_PATTERN, "Use letters, numbers, and underscores; start with a letter or underscore").describe("Row key used by table columns and chart axes");
1828
+ var reportCellValueSchema = z3.union([
1829
+ z3.string().max(1e3),
1830
+ z3.number().finite(),
1831
+ z3.boolean(),
1832
+ z3.null()
1833
+ ]);
1834
+ var reportColumnSchema = z3.object({
1835
+ key: reportKeySchema,
1836
+ label: shortText(80),
1837
+ type: z3.enum(["text", "number", "currency", "percent", "date", "boolean", "image"]).default("text")
1838
+ }).strict();
1839
+ var baseSectionSchema = z3.object({
1840
+ id: z3.string().regex(ANCHOR_PATTERN, "Use letters, numbers, dashes, and underscores; start with a letter").optional(),
1841
+ title: optionalText(120),
1842
+ description: optionalText(500)
1843
+ }).strict();
1844
+ var reportToneSchema = z3.enum(["neutral", "info", "good", "warning", "bad"]);
1845
+ var reportKpiSchema = z3.object({
1846
+ label: shortText(80),
1847
+ value: z3.union([z3.string().max(200), z3.number().finite()]),
1848
+ unit: optionalText(24),
1849
+ change: optionalText(120),
1850
+ tone: reportToneSchema.default("neutral")
1851
+ }).strict();
1852
+ var reportKpiGridSectionSchema = baseSectionSchema.extend({
1853
+ type: z3.literal("kpi_grid"),
1854
+ kpis: z3.array(reportKpiSchema).min(1).max(MAX_REPORT_KPIS)
1855
+ });
1856
+ var tableRowsSchema = z3.array(z3.record(reportCellValueSchema)).max(MAX_REPORT_TABLE_ROWS);
1857
+ function isValidReportImageUrl(value) {
1858
+ try {
1859
+ const url = new URL(value);
1860
+ return url.protocol === "https:" && !url.username && !url.password;
1861
+ } catch {
1862
+ return false;
1863
+ }
1864
+ }
1865
+ var reportTableSectionSchema = baseSectionSchema.extend({
1866
+ type: z3.literal("table"),
1867
+ columns: z3.array(reportColumnSchema).min(1).max(MAX_REPORT_COLUMNS),
1868
+ rows: tableRowsSchema,
1869
+ total_rows: z3.number().int().nonnegative().optional(),
1870
+ truncated: z3.boolean().default(false)
1871
+ }).superRefine((section, ctx) => {
1872
+ const columnKeys = section.columns.map((column) => column.key);
1873
+ const uniqueKeys = new Set(columnKeys);
1874
+ if (uniqueKeys.size !== columnKeys.length) {
1875
+ ctx.addIssue({
1876
+ code: z3.ZodIssueCode.custom,
1877
+ path: ["columns"],
1878
+ message: "Column keys must be unique"
1879
+ });
1880
+ }
1881
+ for (const [rowIndex, row] of section.rows.entries()) {
1882
+ for (const key of Object.keys(row)) {
1883
+ if (!uniqueKeys.has(key)) {
1884
+ ctx.addIssue({
1885
+ code: z3.ZodIssueCode.custom,
1886
+ path: ["rows", rowIndex, key],
1887
+ message: `Unknown table column key: ${key}`
1888
+ });
1889
+ }
1890
+ }
1891
+ }
1892
+ const imageKeys = new Set(section.columns.filter((column) => column.type === "image").map((column) => column.key));
1893
+ for (const [rowIndex, row] of section.rows.entries()) {
1894
+ for (const key of imageKeys) {
1895
+ const value = row[key];
1896
+ if (value === void 0 || value === null) continue;
1897
+ if (typeof value !== "string" || !isValidReportImageUrl(value)) {
1898
+ ctx.addIssue({
1899
+ code: z3.ZodIssueCode.custom,
1900
+ path: ["rows", rowIndex, key],
1901
+ message: "Image columns must contain HTTPS image URLs or null"
1902
+ });
1903
+ }
1904
+ }
1905
+ }
1906
+ if (section.total_rows !== void 0 && section.total_rows < section.rows.length) {
1907
+ ctx.addIssue({
1908
+ code: z3.ZodIssueCode.custom,
1909
+ path: ["total_rows"],
1910
+ message: "total_rows must be greater than or equal to the rendered row count"
1911
+ });
1912
+ }
1913
+ });
1914
+ var chartRowsSchema = z3.array(z3.record(reportCellValueSchema)).min(1).max(MAX_REPORT_CHART_ROWS);
1915
+ var reportChartSeriesSchema = z3.object({
1916
+ key: reportKeySchema,
1917
+ label: shortText(80),
1918
+ tone: reportToneSchema.optional()
1919
+ }).strict();
1920
+ var chartBaseSectionSchema = baseSectionSchema.extend({
1921
+ x_key: reportKeySchema,
1922
+ y_key: reportKeySchema.optional(),
1923
+ series: z3.array(reportChartSeriesSchema).min(1).max(MAX_REPORT_CHART_SERIES).optional(),
1924
+ x_label: optionalText(80),
1925
+ y_label: optionalText(80),
1926
+ value_type: z3.enum(["number", "currency", "percent"]).default("number"),
1927
+ stacked: z3.boolean().default(false),
1928
+ rows: chartRowsSchema
1929
+ });
1930
+ function validateChartRows(section, ctx) {
1931
+ const series = section.series ?? (section.y_key ? [{ key: section.y_key, label: section.y_label ?? section.y_key }] : []);
1932
+ if (series.length === 0) {
1933
+ ctx.addIssue({
1934
+ code: z3.ZodIssueCode.custom,
1935
+ path: ["y_key"],
1936
+ message: "Provide y_key or at least one series entry"
1937
+ });
1938
+ }
1939
+ const seriesKeys = series.map((item) => item.key);
1940
+ if (new Set(seriesKeys).size !== seriesKeys.length) {
1941
+ ctx.addIssue({
1942
+ code: z3.ZodIssueCode.custom,
1943
+ path: ["series"],
1944
+ message: "Series keys must be unique"
1945
+ });
1946
+ }
1947
+ for (const [rowIndex, row] of section.rows.entries()) {
1948
+ if (!(section.x_key in row)) {
1949
+ ctx.addIssue({
1950
+ code: z3.ZodIssueCode.custom,
1951
+ path: ["rows", rowIndex, section.x_key],
1952
+ message: `Missing x_key value: ${section.x_key}`
1953
+ });
1954
+ }
1955
+ for (const item of series) {
1956
+ if (!(item.key in row)) {
1957
+ ctx.addIssue({
1958
+ code: z3.ZodIssueCode.custom,
1959
+ path: ["rows", rowIndex, item.key],
1960
+ message: `Missing chart series value: ${item.key}`
1961
+ });
1962
+ continue;
1963
+ }
1964
+ if (typeof row[item.key] !== "number") {
1965
+ ctx.addIssue({
1966
+ code: z3.ZodIssueCode.custom,
1967
+ path: ["rows", rowIndex, item.key],
1968
+ message: `Chart series must reference numeric values: ${item.key}`
1969
+ });
1970
+ }
1971
+ }
1972
+ }
1973
+ }
1974
+ var reportBarChartSectionSchema = chartBaseSectionSchema.extend({
1975
+ type: z3.literal("bar_chart")
1976
+ }).superRefine(validateChartRows);
1977
+ var reportLineChartSectionSchema = chartBaseSectionSchema.extend({
1978
+ type: z3.literal("line_chart")
1979
+ }).superRefine(validateChartRows);
1980
+ var reportNoteSectionSchema = baseSectionSchema.extend({
1981
+ type: z3.literal("note"),
1982
+ body: shortText(2e3),
1983
+ tone: reportToneSchema.default("neutral")
1984
+ });
1985
+ var reportSectionSchema = z3.union([
1986
+ reportKpiGridSectionSchema,
1987
+ reportTableSectionSchema,
1988
+ reportBarChartSectionSchema,
1989
+ reportLineChartSectionSchema,
1990
+ reportNoteSectionSchema
1991
+ ]);
1992
+ var reportSpecV1Schema = z3.object({
1993
+ title: shortText(140),
1994
+ summary: optionalText(1e3),
1995
+ source: optionalText(500),
1996
+ sections: z3.array(reportSectionSchema).min(1).max(MAX_REPORT_SECTIONS)
1997
+ }).strict().superRefine((spec, ctx) => {
1998
+ const bytes = Buffer.byteLength(JSON.stringify(spec), "utf8");
1999
+ if (bytes > MAX_REPORT_SPEC_BYTES) {
2000
+ ctx.addIssue({
2001
+ code: z3.ZodIssueCode.custom,
2002
+ path: [],
2003
+ message: `Report spec exceeds ${MAX_REPORT_SPEC_BYTES} bytes`
2004
+ });
2005
+ }
2006
+ });
2007
+ var CURRENCY_MONEY_POLICIES = Object.freeze({
2008
+ USD: { currencyCode: "USD", minorUnit: 2, defaultDisplayLocale: "en-US", minBid: 0.02, maxBid: 100, maxPrice: 1e4 },
2009
+ CAD: { currencyCode: "CAD", minorUnit: 2, defaultDisplayLocale: "en-CA", minBid: 0.02, maxBid: 100, maxPrice: 1e4 },
2010
+ GBP: { currencyCode: "GBP", minorUnit: 2, defaultDisplayLocale: "en-GB", minBid: 0.02, maxBid: 100, maxPrice: 1e4 },
2011
+ EUR: { currencyCode: "EUR", minorUnit: 2, defaultDisplayLocale: "de-DE", minBid: 0.02, maxBid: 100, maxPrice: 1e4 },
2012
+ MXN: { currencyCode: "MXN", minorUnit: 2, defaultDisplayLocale: "es-MX", minBid: 0.1, maxBid: 2e3, maxPrice: 2e5 },
2013
+ BRL: { currencyCode: "BRL", minorUnit: 2, defaultDisplayLocale: "pt-BR", minBid: 0.05, maxBid: 500, maxPrice: 5e4 },
2014
+ SEK: { currencyCode: "SEK", minorUnit: 2, defaultDisplayLocale: "sv-SE", minBid: 0.1, maxBid: 1e3, maxPrice: 1e5 },
2015
+ ZAR: { currencyCode: "ZAR", minorUnit: 2, defaultDisplayLocale: "en-ZA", minBid: 0.1, maxBid: 1500, maxPrice: 15e4 },
2016
+ PLN: { currencyCode: "PLN", minorUnit: 2, defaultDisplayLocale: "pl-PL", minBid: 0.05, maxBid: 400, maxPrice: 4e4 },
2017
+ EGP: { currencyCode: "EGP", minorUnit: 2, defaultDisplayLocale: "ar-EG", minBid: 0.5, maxBid: 3e3, maxPrice: 3e5 },
2018
+ TRY: { currencyCode: "TRY", minorUnit: 2, defaultDisplayLocale: "tr-TR", minBid: 0.1, maxBid: 2e3, maxPrice: 2e5 },
2019
+ AED: { currencyCode: "AED", minorUnit: 2, defaultDisplayLocale: "ar-AE", minBid: 0.1, maxBid: 350, maxPrice: 35e3 },
2020
+ INR: { currencyCode: "INR", minorUnit: 2, defaultDisplayLocale: "en-IN", minBid: 1, maxBid: 5e3, maxPrice: 5e5 },
2021
+ SGD: { currencyCode: "SGD", minorUnit: 2, defaultDisplayLocale: "en-SG", minBid: 0.02, maxBid: 150, maxPrice: 15e3 },
2022
+ JPY: { currencyCode: "JPY", minorUnit: 0, defaultDisplayLocale: "ja-JP", minBid: 2, maxBid: 1e4, maxPrice: 1e6 },
2023
+ AUD: { currencyCode: "AUD", minorUnit: 2, defaultDisplayLocale: "en-AU", minBid: 0.02, maxBid: 150, maxPrice: 15e3 },
2024
+ SAR: { currencyCode: "SAR", minorUnit: 2, defaultDisplayLocale: "ar-SA", minBid: 0.1, maxBid: 350, maxPrice: 35e3 }
2025
+ });
2026
+ function fallbackMoneyPolicyForKnownCurrency(currencyCode) {
2027
+ return {
2028
+ currencyCode,
2029
+ minorUnit: 2,
2030
+ defaultDisplayLocale: "en",
2031
+ minBid: 0.02,
2032
+ maxBid: 100,
2033
+ maxPrice: 1e4
2034
+ };
2035
+ }
2036
+ function getMarketplaceMoneyPolicyForDefinition(marketplace) {
2037
+ return CURRENCY_MONEY_POLICIES[marketplace.currencyCode] ?? fallbackMoneyPolicyForKnownCurrency(marketplace.currencyCode);
2038
+ }
2039
+ var CUSTOMER_FEEDBACK_MARKETPLACE_IDS = [...CUSTOMER_FEEDBACK_SUPPORTED_MARKETPLACE_IDS];
2040
+ var ADS_BRAND_METRICS_MARKETPLACE_IDS = [...ADS_BRAND_METRICS_SUPPORTED_MARKETPLACE_IDS];
2041
+ var ADS_SPONSORED_PRODUCTS_CAMPAIGN_MANAGEMENT_MARKETPLACE_IDS = [
2042
+ ...ADS_SPONSORED_PRODUCTS_CAMPAIGN_MANAGEMENT_SUPPORTED_MARKETPLACE_IDS
2043
+ ];
2044
+ var ADS_SPONSORED_PRODUCTS_BID_RECOMMENDATION_MARKETPLACE_IDS = [
2045
+ ...ADS_SPONSORED_PRODUCTS_BID_RECOMMENDATION_SUPPORTED_MARKETPLACE_IDS
2046
+ ];
2047
+ var ADS_SPONSORED_PRODUCTS_BUDGET_RECOMMENDATION_MARKETPLACE_IDS = [
2048
+ ...ADS_SPONSORED_PRODUCTS_BUDGET_RECOMMENDATION_SUPPORTED_MARKETPLACE_IDS
2049
+ ];
2050
+ var AWD_MARKETPLACE_IDS = [...AWD_SUPPORTED_MARKETPLACE_IDS];
2051
+ var BRAND_ANALYTICS_REPORT_MARKETPLACE_IDS = [...BRAND_ANALYTICS_REPORT_SUPPORTED_MARKETPLACE_IDS];
2052
+ var FBA_INVENTORY_PLANNING_MARKETPLACE_IDS = [...FBA_INVENTORY_PLANNING_SUPPORTED_MARKETPLACE_IDS];
2053
+ var FULFILLMENT_INBOUND_MARKETPLACE_IDS = [...FULFILLMENT_INBOUND_SUPPORTED_MARKETPLACE_IDS];
2054
+ var DEFAULT_SUPPORT_RULE = Object.freeze({ support: "all" });
2055
+ var TOOL_MARKETPLACE_SUPPORT_DECLARED_TOOL_NAMES = [
2056
+ "get_campaign_performance",
2057
+ "get_campaign_snapshots",
2058
+ "get_adgroup_performance",
2059
+ "get_keyword_performance",
2060
+ "get_product_performance",
2061
+ "get_purchased_products",
2062
+ "get_search_terms",
2063
+ "get_placement_breakdown",
2064
+ "get_sb_campaign_performance",
2065
+ "get_sd_campaign_performance",
2066
+ "get_sponsored_ads_report",
2067
+ "get_dsp_performance",
2068
+ "get_dsp_advertisers_live",
2069
+ "get_dsp_entities_live",
2070
+ "get_store_performance",
2071
+ "get_portfolio_performance",
2072
+ "get_sales_and_traffic",
2073
+ "get_tacos",
2074
+ "get_ads_change_history",
2075
+ "get_search_query_performance",
2076
+ "get_repeat_purchase_behavior",
2077
+ "get_search_query_ad_coverage",
2078
+ "diagnose_performance",
2079
+ "get_sp_entities_live",
2080
+ "get_sponsored_ads_entities_live",
2081
+ "get_sp_targeting_options",
2082
+ "get_sponsored_ads_targeting_options",
2083
+ "create_sb_campaigns",
2084
+ "update_sb_campaign_budget",
2085
+ "update_sb_campaign_state",
2086
+ "archive_sb_campaigns",
2087
+ "create_sb_ad_groups",
2088
+ "update_sb_ad_group_state",
2089
+ "archive_sb_ad_groups",
2090
+ "create_sb_ads",
2091
+ "update_sb_ad_state",
2092
+ "archive_sb_ads",
2093
+ "create_sb_targets",
2094
+ "update_sb_target_bids",
2095
+ "update_sb_target_state",
2096
+ "archive_sb_targets",
2097
+ "create_sb_negative_targets",
2098
+ "update_sb_negative_target_state",
2099
+ "archive_sb_negative_targets",
2100
+ "update_keyword_bids",
2101
+ "update_target_bids",
2102
+ "update_keyword_state",
2103
+ "archive_keywords",
2104
+ "update_adgroup_bid",
2105
+ "update_campaign_bidding",
2106
+ "update_campaign_budget",
2107
+ "update_campaign_state",
2108
+ "archive_campaigns",
2109
+ "create_sd_campaigns",
2110
+ "update_sd_campaign_budget",
2111
+ "update_sd_campaign_state",
2112
+ "archive_sd_campaigns",
2113
+ "create_sd_ad_groups",
2114
+ "update_sd_ad_group_bid",
2115
+ "update_sd_ad_group_state",
2116
+ "archive_sd_ad_groups",
2117
+ "create_sd_product_ads",
2118
+ "update_sd_product_ad_state",
2119
+ "archive_sd_product_ads",
2120
+ "create_sd_targets",
2121
+ "update_sd_target_bids",
2122
+ "update_sd_target_state",
2123
+ "archive_sd_targets",
2124
+ "create_sd_negative_targets",
2125
+ "update_sd_negative_target_state",
2126
+ "archive_sd_negative_targets",
2127
+ "update_campaign_audience_bid_adjustment",
2128
+ "create_keywords",
2129
+ "create_negative_keywords",
2130
+ "create_sp_campaigns",
2131
+ "create_sp_ad_groups",
2132
+ "create_sp_product_ads",
2133
+ "update_sp_ad_entities",
2134
+ "create_sp_targets",
2135
+ "update_sp_target_state",
2136
+ "archive_sp_targets",
2137
+ "create_sp_negative_targets",
2138
+ "update_sp_negative_keyword_state",
2139
+ "archive_sp_negative_keywords",
2140
+ "update_sp_negative_target_state",
2141
+ "archive_sp_negative_targets",
2142
+ "get_bid_recommendations",
2143
+ "get_budget_recommendations",
2144
+ "get_budget_pacing",
2145
+ "get_ad_eligibility",
2146
+ "get_brand_health",
2147
+ "get_share_of_voice",
2148
+ "get_attribution_performance",
2149
+ "get_audience_segments",
2150
+ "get_fba_inventory",
2151
+ "get_inventory_health",
2152
+ "get_fba_storage_fees",
2153
+ "get_inventory_movements",
2154
+ "get_inventory_by_fulfillment_center",
2155
+ "get_awd_inventory",
2156
+ "get_awd_shipments",
2157
+ "get_awd_shipment_items",
2158
+ "get_inbound_shipments",
2159
+ "get_shipment_receiving_status",
2160
+ "get_sales_velocity",
2161
+ "get_listing_registry",
2162
+ "get_suppressed_listings",
2163
+ "get_days_of_cover",
2164
+ "get_todays_sales",
2165
+ "get_orders",
2166
+ "get_order_details",
2167
+ "get_returns",
2168
+ "get_reimbursements",
2169
+ "get_seasonality_index",
2170
+ "get_sales_summary",
2171
+ "get_inventory_risk_triage",
2172
+ "get_current_rank",
2173
+ "get_buybox_status",
2174
+ "get_competitive_pricing",
2175
+ "get_offer_listings",
2176
+ "get_subscribe_and_save",
2177
+ "get_fba_eligibility",
2178
+ "get_listing_restrictions",
2179
+ "get_financial_events",
2180
+ "get_profitability_review",
2181
+ "get_payment_transactions",
2182
+ "get_settlement_economics",
2183
+ "get_product_details",
2184
+ "get_sales_ranks",
2185
+ "get_aplus_status",
2186
+ "get_variations",
2187
+ "get_product_reviews",
2188
+ "get_review_trends",
2189
+ "get_listing_quality",
2190
+ "get_catalog_cleanup",
2191
+ "create_listing",
2192
+ "update_listing",
2193
+ "update_price",
2194
+ "update_inventory_quantity",
2195
+ "get_keyword_ranks",
2196
+ "get_shipping_preview",
2197
+ "get_mcf_orders",
2198
+ "create_mcf_order",
2199
+ "manage_returns",
2200
+ "get_account_data_tour",
2201
+ "submit_conversation_feedback",
2202
+ "get_account_info",
2203
+ "get_action_history"
2204
+ ];
2205
+ var ADS_SPONSORED_PRODUCTS_CAMPAIGN_MANAGEMENT_TOOL_NAMES = [
2206
+ "get_sp_entities_live",
2207
+ "get_sp_targeting_options",
2208
+ "update_keyword_bids",
2209
+ "update_target_bids",
2210
+ "update_keyword_state",
2211
+ "archive_keywords",
2212
+ "update_adgroup_bid",
2213
+ "update_campaign_bidding",
2214
+ "update_campaign_budget",
2215
+ "update_campaign_state",
2216
+ "archive_campaigns",
2217
+ "update_campaign_audience_bid_adjustment",
2218
+ "create_keywords",
2219
+ "create_negative_keywords",
2220
+ "create_sp_campaigns",
2221
+ "create_sp_ad_groups",
2222
+ "create_sp_product_ads",
2223
+ "update_sp_ad_entities",
2224
+ "create_sp_targets",
2225
+ "update_sp_target_state",
2226
+ "archive_sp_targets",
2227
+ "create_sp_negative_targets",
2228
+ "update_sp_negative_keyword_state",
2229
+ "archive_sp_negative_keywords",
2230
+ "update_sp_negative_target_state",
2231
+ "archive_sp_negative_targets"
2232
+ ];
2233
+ var ADS_SPONSORED_BRANDS_CAMPAIGN_MANAGEMENT_TOOL_NAMES = [
2234
+ "create_sb_campaigns",
2235
+ "update_sb_campaign_budget",
2236
+ "update_sb_campaign_state",
2237
+ "archive_sb_campaigns",
2238
+ "create_sb_ad_groups",
2239
+ "update_sb_ad_group_state",
2240
+ "archive_sb_ad_groups",
2241
+ "create_sb_ads",
2242
+ "update_sb_ad_state",
2243
+ "archive_sb_ads",
2244
+ "create_sb_targets",
2245
+ "update_sb_target_bids",
2246
+ "update_sb_target_state",
2247
+ "archive_sb_targets",
2248
+ "create_sb_negative_targets",
2249
+ "update_sb_negative_target_state",
2250
+ "archive_sb_negative_targets"
2251
+ ];
2252
+ var BRAND_ANALYTICS_REPORT_TOOL_NAMES = [
2253
+ "get_search_query_performance",
2254
+ "get_repeat_purchase_behavior",
2255
+ "get_search_query_ad_coverage",
2256
+ "get_keyword_ranks"
2257
+ ];
2258
+ var ADS_BRAND_METRICS_TOOL_NAMES = [
2259
+ "get_brand_health",
2260
+ "get_share_of_voice"
2261
+ ];
2262
+ var AWD_TOOL_NAMES = [
2263
+ "get_awd_inventory",
2264
+ "get_awd_shipments",
2265
+ "get_awd_shipment_items"
2266
+ ];
2267
+ var FULFILLMENT_INBOUND_TOOL_NAMES = [
2268
+ "get_inbound_shipments",
2269
+ "get_shipment_receiving_status"
2270
+ ];
2271
+ function assignMarketplaceRule(rules, toolNames, rule) {
2272
+ for (const toolName of toolNames) {
2273
+ rules[toolName] = rule;
2274
+ }
2275
+ }
2276
+ function buildMarketplaceSupportRules() {
2277
+ const rules = {};
2278
+ for (const toolName of TOOL_MARKETPLACE_SUPPORT_DECLARED_TOOL_NAMES) {
2279
+ rules[toolName] = DEFAULT_SUPPORT_RULE;
2280
+ }
2281
+ assignMarketplaceRule(rules, ["get_product_reviews", "get_review_trends"], {
2282
+ support: "marketplaces",
2283
+ marketplaceIds: CUSTOMER_FEEDBACK_MARKETPLACE_IDS,
2284
+ capability: "sp_api_customer_feedback",
2285
+ source: "Amazon Customer Feedback API marketplace validation",
2286
+ note: "Amazon's Customer Feedback API currently accepts US, UK, DE, ES, FR, IT, and JP marketplace IDs."
2287
+ });
2288
+ assignMarketplaceRule(rules, ADS_SPONSORED_PRODUCTS_CAMPAIGN_MANAGEMENT_TOOL_NAMES, {
2289
+ support: "marketplaces",
2290
+ marketplaceIds: ADS_SPONSORED_PRODUCTS_CAMPAIGN_MANAGEMENT_MARKETPLACE_IDS,
2291
+ capability: "amazon_ads_sp_campaign_management",
2292
+ source: "Amazon Ads Sponsored Products feature availability by marketplace",
2293
+ note: "Amazon Ads documents Sponsored Products Campaign Management and Product Recommendations for US, CA, MX, BR, DE, ES, FR, IT, UK, NL, SE, TR, PL, BE, AE, EG, SA, JP, IN, AU, SG, and ZA."
2294
+ });
2295
+ assignMarketplaceRule(rules, ADS_SPONSORED_BRANDS_CAMPAIGN_MANAGEMENT_TOOL_NAMES, {
2296
+ support: "marketplaces",
2297
+ marketplaceIds: ADS_SPONSORED_PRODUCTS_CAMPAIGN_MANAGEMENT_MARKETPLACE_IDS,
2298
+ capability: "amazon_ads_sb_campaign_management",
2299
+ source: "Amazon Ads Common Campaign Management / Sponsored Brands target write availability",
2300
+ note: "Uses the conservative Ads campaign-management marketplace allowlist until a separate Sponsored Brands Common Campaign Management marketplace matrix is pinned."
2301
+ });
2302
+ rules.get_bid_recommendations = {
2303
+ support: "marketplaces",
2304
+ marketplaceIds: ADS_SPONSORED_PRODUCTS_BID_RECOMMENDATION_MARKETPLACE_IDS,
2305
+ capability: "amazon_ads_sp_theme_based_bid_suggestions",
2306
+ source: "Amazon Ads Sponsored Products feature availability by marketplace",
2307
+ note: "Amazon Ads documents Theme-based bid suggestions for US, CA, DE, ES, FR, UK, JP, and IN."
2308
+ };
2309
+ rules.get_budget_recommendations = {
2310
+ support: "marketplaces",
2311
+ marketplaceIds: ADS_SPONSORED_PRODUCTS_BUDGET_RECOMMENDATION_MARKETPLACE_IDS,
2312
+ capability: "amazon_ads_sp_budget_recommendations",
2313
+ source: "Amazon Ads Sponsored Products feature availability by marketplace",
2314
+ note: "Amazon Ads documents budget recommendations for US, CA, MX, DE, ES, FR, UK, IT, JP, IN, AU, and AE."
2315
+ };
2316
+ assignMarketplaceRule(rules, ADS_BRAND_METRICS_TOOL_NAMES, {
2317
+ support: "marketplaces",
2318
+ marketplaceIds: ADS_BRAND_METRICS_MARKETPLACE_IDS,
2319
+ capability: "amazon_ads_brand_metrics",
2320
+ source: "Amazon Ads Brand Metrics API open beta eligibility",
2321
+ note: "Amazon Ads documents Brand Metrics API eligibility for US, CA, MX, UK, DE, FR, IN, IT, ES, JP, and AU."
2322
+ });
2323
+ assignMarketplaceRule(rules, BRAND_ANALYTICS_REPORT_TOOL_NAMES, {
2324
+ support: "marketplaces",
2325
+ marketplaceIds: BRAND_ANALYTICS_REPORT_MARKETPLACE_IDS,
2326
+ capability: "sp_api_brand_analytics_reports",
2327
+ source: "Amazon SP-API Analytics report type marketplace availability",
2328
+ note: "Amazon documents SQP/Search Catalog/Market Basket/Repeat Purchase reports for NA all marketplaces, FE all marketplaces, and ES, UK, FR, NL, DE, IT, SE, TR, SA, AE, and IN in the EU endpoint region."
2329
+ });
2330
+ assignMarketplaceRule(rules, AWD_TOOL_NAMES, {
2331
+ support: "marketplaces",
2332
+ marketplaceIds: AWD_MARKETPLACE_IDS,
2333
+ capability: "sp_api_awd",
2334
+ source: "Amazon SP-API Amazon Warehousing and Distribution API marketplace availability",
2335
+ note: "Amazon documents AWD v2024-05-09 as available in the US marketplace."
2336
+ });
2337
+ assignMarketplaceRule(rules, FULFILLMENT_INBOUND_TOOL_NAMES, {
2338
+ support: "marketplaces",
2339
+ marketplaceIds: FULFILLMENT_INBOUND_MARKETPLACE_IDS,
2340
+ capability: "sp_api_fulfillment_inbound",
2341
+ source: "Amazon SP-API Fulfillment Inbound API marketplace availability",
2342
+ note: "Amazon documents Fulfillment Inbound shipment creation as supported in all marketplaces except Brazil."
2343
+ });
2344
+ rules.get_inventory_health = {
2345
+ support: "marketplaces",
2346
+ marketplaceIds: FBA_INVENTORY_PLANNING_MARKETPLACE_IDS,
2347
+ capability: "sp_api_fba_inventory_planning_report",
2348
+ source: "Amazon SP-API FBA Manage Inventory Health report marketplace availability",
2349
+ note: "Amazon documents GET_FBA_INVENTORY_PLANNING_DATA as unavailable in the NL, PL, SE, and BE marketplaces."
2350
+ };
2351
+ return rules;
2352
+ }
2353
+ var TOOL_MARKETPLACE_SUPPORT = Object.freeze(
2354
+ buildMarketplaceSupportRules()
2355
+ );
2356
+ var DOMAIN_BY_TOOL = /* @__PURE__ */ new Map();
2357
+ var WRITE_TOOL_NAMES = /* @__PURE__ */ new Set();
2358
+ for (const domain of TOOL_DOMAINS) {
2359
+ for (const tool of domain.tools) {
2360
+ DOMAIN_BY_TOOL.set(tool.name, domain.serverDomain);
2361
+ if (tool.write) WRITE_TOOL_NAMES.add(tool.name);
2362
+ }
2363
+ }
2364
+ for (const tool of UTILITY_TOOLS) {
2365
+ DOMAIN_BY_TOOL.set(tool.name, "utility");
2366
+ if (tool.write) WRITE_TOOL_NAMES.add(tool.name);
2367
+ }
2368
+ var MARKETPLACE_CAPABILITY_POLICY_VERSION = "marketplace-capabilities-v2-enabled-2026-05-26";
2369
+ var US_WRITE_EVIDENCE_VERSION = "phase1-us-write-baseline";
2370
+ var CANADA_CAPABILITY_EVIDENCE_VERSION = "marketplace-capabilities-v2-ca-enabled-2026-05-26";
2371
+ var CANADA_BASE_EVIDENCE_IDS = [
2372
+ "ca.registry-facts.v1",
2373
+ "ca.seller-central-url.v1",
2374
+ "ca.timezone-source.v1",
2375
+ "ca.promotion-effects.v1"
2376
+ ];
2377
+ var CANADA_ADS_ENABLED_EVIDENCE_IDS = ["ca.ads-write-enabled.repo-contract.v1"];
2378
+ var CANADA_CATALOG_ENABLED_EVIDENCE_IDS = [
2379
+ "ca.catalog-update-price-cad-preview.repo-proof.v1",
2380
+ "ca.catalog-write-enabled.repo-contract.v1"
2381
+ ];
2382
+ var CANADA_FULFILLMENT_ENABLED_EVIDENCE_IDS = ["ca.fulfillment-write-enabled.repo-contract.v1"];
2383
+ function policyKey(marketplaceId, toolFamily) {
2384
+ return `${marketplaceId}:${toolFamily}`;
2385
+ }
2386
+ var MARKETPLACE_CAPABILITY_POLICIES = [
2387
+ {
2388
+ marketplaceId: DEFAULT_MARKETPLACE_ID,
2389
+ toolFamily: "ads_write",
2390
+ requiredConnection: "ads",
2391
+ evidenceVersion: US_WRITE_EVIDENCE_VERSION,
2392
+ evidenceIds: ["existing-us-ads-write-contract-tests"],
2393
+ capabilityRolloutTrack: "foundation",
2394
+ evidenceStatus: "recorded",
2395
+ requiredEvidence: ["existing_foundation_behavior_preserved"],
2396
+ stages: { preview: "enabled", write: "enabled" },
2397
+ notes: "Existing US Ads write behavior remains enabled while v2 policy is introduced."
2398
+ },
2399
+ {
2400
+ marketplaceId: DEFAULT_MARKETPLACE_ID,
2401
+ toolFamily: "catalog_write",
2402
+ requiredConnection: "sp_api",
2403
+ evidenceVersion: US_WRITE_EVIDENCE_VERSION,
2404
+ evidenceIds: ["existing-us-catalog-write-contract-tests"],
2405
+ capabilityRolloutTrack: "foundation",
2406
+ evidenceStatus: "recorded",
2407
+ requiredEvidence: ["existing_foundation_behavior_preserved"],
2408
+ stages: { preview: "enabled", write: "enabled" },
2409
+ notes: "Existing US catalog write behavior remains enabled while v2 policy is introduced."
2410
+ },
2411
+ {
2412
+ marketplaceId: DEFAULT_MARKETPLACE_ID,
2413
+ toolFamily: "fulfillment_write",
2414
+ requiredConnection: "sp_api",
2415
+ evidenceVersion: US_WRITE_EVIDENCE_VERSION,
2416
+ evidenceIds: ["existing-us-fulfillment-write-contract-tests"],
2417
+ capabilityRolloutTrack: "foundation",
2418
+ evidenceStatus: "recorded",
2419
+ requiredEvidence: ["existing_foundation_behavior_preserved"],
2420
+ stages: { write: "enabled" },
2421
+ notes: "Existing US fulfillment write behavior remains enabled while v2 policy is introduced."
2422
+ },
2423
+ {
2424
+ marketplaceId: "A2EUQ1WTGCTBG2",
2425
+ toolFamily: "ads_write",
2426
+ requiredConnection: "ads",
2427
+ evidenceVersion: CANADA_CAPABILITY_EVIDENCE_VERSION,
2428
+ evidenceIds: [...CANADA_BASE_EVIDENCE_IDS, ...CANADA_ADS_ENABLED_EVIDENCE_IDS],
2429
+ capabilityRolloutTrack: "enabled",
2430
+ evidenceStatus: "recorded",
2431
+ requiredEvidence: ["contract_tests_pass"],
2432
+ stages: { preview: "enabled", write: "enabled" },
2433
+ notes: "Canada Ads writes are enabled. Runtime write safety still requires scoped credentials without endpoint mismatch or tenant-key ambiguity."
2434
+ },
2435
+ {
2436
+ marketplaceId: "A2EUQ1WTGCTBG2",
2437
+ toolFamily: "catalog_write",
2438
+ requiredConnection: "sp_api",
2439
+ evidenceVersion: CANADA_CAPABILITY_EVIDENCE_VERSION,
2440
+ evidenceIds: [...CANADA_BASE_EVIDENCE_IDS, ...CANADA_CATALOG_ENABLED_EVIDENCE_IDS],
2441
+ capabilityRolloutTrack: "enabled",
2442
+ evidenceStatus: "recorded",
2443
+ requiredEvidence: ["contract_tests_pass", "currency_safe_previews_and_audits_verified"],
2444
+ stages: { preview: "enabled", write: "enabled" },
2445
+ notes: "Canada catalog previews and writes are enabled with CAD marketplace facts. Runtime write safety still requires scoped SP-API credentials without endpoint mismatch or tenant-key ambiguity."
2446
+ },
2447
+ {
2448
+ marketplaceId: "A2EUQ1WTGCTBG2",
2449
+ toolFamily: "fulfillment_write",
2450
+ requiredConnection: "sp_api",
2451
+ evidenceVersion: CANADA_CAPABILITY_EVIDENCE_VERSION,
2452
+ evidenceIds: [...CANADA_BASE_EVIDENCE_IDS, ...CANADA_FULFILLMENT_ENABLED_EVIDENCE_IDS],
2453
+ capabilityRolloutTrack: "enabled",
2454
+ evidenceStatus: "recorded",
2455
+ requiredEvidence: ["contract_tests_pass"],
2456
+ stages: { write: "enabled" },
2457
+ notes: "Canada fulfillment writes are enabled. Runtime write safety still requires scoped SP-API credentials without endpoint mismatch or tenant-key ambiguity."
2458
+ }
2459
+ ];
2460
+ var MARKETPLACE_CAPABILITY_POLICY_BY_KEY = new Map(
2461
+ MARKETPLACE_CAPABILITY_POLICIES.map((policy) => [policyKey(policy.marketplaceId, policy.toolFamily), policy])
2462
+ );
2463
+ var MARKETPLACE_CAPABILITY_CAPSULES = MARKETPLACE_DEFINITIONS.map((marketplace) => {
2464
+ const toolFamilies = MARKETPLACE_CAPABILITY_POLICIES.filter(
2465
+ (policy) => policy.marketplaceId === marketplace.marketplaceId
2466
+ );
2467
+ const hasCandidateCapabilityPolicy = toolFamilies.some(
2468
+ (policy) => policy.capabilityRolloutTrack === "v2_candidate"
2469
+ );
2470
+ const hasEnabledCapabilityPolicy = toolFamilies.some(
2471
+ (policy) => policy.capabilityRolloutTrack === "enabled"
2472
+ );
2473
+ return {
2474
+ marketplaceId: marketplace.marketplaceId,
2475
+ capsuleVersion: MARKETPLACE_CAPABILITY_POLICY_VERSION,
2476
+ base: marketplace,
2477
+ money: getMarketplaceMoneyPolicyForDefinition(marketplace),
2478
+ toolFamilies,
2479
+ rolloutGates: hasCandidateCapabilityPolicy ? [
2480
+ "registry_metadata_verified",
2481
+ "contract_tests_pass",
2482
+ "read_only_smoke_evidence_recorded",
2483
+ "currency_safe_previews_and_audits_verified",
2484
+ "write_evidence_recorded_before_promotion"
2485
+ ] : hasEnabledCapabilityPolicy ? ["registry_metadata_verified", "contract_tests_pass", "runtime_write_guardrails_preserved"] : ["existing_foundation_behavior_preserved"]
2486
+ };
2487
+ });
2488
+ var GLOBAL_MARKETPLACE_CAPABILITY_EVIDENCE_SCOPE = "global";
2489
+ var COMMON_MARKETPLACE_CAPABILITY_EVIDENCE_SCOPE = "common";
2490
+ var CANADA_MARKETPLACE_ID = "A2EUQ1WTGCTBG2";
2491
+ var MARKETPLACE_CAPABILITY_EVIDENCE_REGISTRY = [
2492
+ {
2493
+ id: "default-deny",
2494
+ status: "recorded",
2495
+ marketplaceId: GLOBAL_MARKETPLACE_CAPABILITY_EVIDENCE_SCOPE,
2496
+ toolFamily: "all",
2497
+ operation: "all",
2498
+ sourceType: "repo_policy",
2499
+ artifactPath: "packages/shared/src/marketplace-capabilities.ts",
2500
+ supportingArtifactPaths: [
2501
+ "packages/shared/src/marketplace-capabilities.test.ts",
2502
+ "packages/shared/src/marketplace-capabilities.contract.test.ts"
2503
+ ],
2504
+ summary: "Default-deny fallback evidence version for unknown marketplaces and marketplace/tool-family combinations without explicit policy rows.",
2505
+ notes: "Recorded deny behavior only; this evidence record does not grant any marketplace capability."
2506
+ },
2507
+ {
2508
+ id: "existing-us-ads-write-contract-tests",
2509
+ status: "recorded",
2510
+ marketplaceId: DEFAULT_MARKETPLACE_ID,
2511
+ toolFamily: "ads_write",
2512
+ operation: "write",
2513
+ sourceType: "repo_contract_test",
2514
+ artifactPath: "packages/shared/src/marketplace-capabilities.test.ts",
2515
+ supportingArtifactPaths: ["packages/shared/src/marketplace-capabilities.contract.test.ts"],
2516
+ summary: "Existing US Ads write-family behavior is covered by shared marketplace capability tests while v2 policy is introduced."
2517
+ },
2518
+ {
2519
+ id: "existing-us-catalog-write-contract-tests",
2520
+ status: "recorded",
2521
+ marketplaceId: DEFAULT_MARKETPLACE_ID,
2522
+ toolFamily: "catalog_write",
2523
+ operation: "write",
2524
+ sourceType: "repo_contract_test",
2525
+ artifactPath: "packages/shared/src/marketplace-capabilities.test.ts",
2526
+ supportingArtifactPaths: ["packages/shared/src/marketplace-capabilities.contract.test.ts"],
2527
+ summary: "Existing US catalog write-family behavior is covered by shared marketplace capability tests while v2 policy is introduced."
2528
+ },
2529
+ {
2530
+ id: "existing-us-fulfillment-write-contract-tests",
2531
+ status: "recorded",
2532
+ marketplaceId: DEFAULT_MARKETPLACE_ID,
2533
+ toolFamily: "fulfillment_write",
2534
+ operation: "write",
2535
+ sourceType: "repo_contract_test",
2536
+ artifactPath: "packages/shared/src/marketplace-capabilities.test.ts",
2537
+ supportingArtifactPaths: ["packages/shared/src/marketplace-capabilities.contract.test.ts"],
2538
+ summary: "Existing US fulfillment write-family behavior is covered by shared marketplace capability tests while v2 policy is introduced."
2539
+ },
2540
+ {
2541
+ id: "ca.registry-facts.v1",
2542
+ status: "recorded",
2543
+ marketplaceId: CANADA_MARKETPLACE_ID,
2544
+ toolFamily: "all",
2545
+ operation: "all",
2546
+ sourceType: "repo_registry",
2547
+ artifactPath: "packages/shared/src/marketplaces.ts",
2548
+ supportingArtifactPaths: [
2549
+ "packages/shared/src/marketplaces.test.ts",
2550
+ "docs/internal/runbooks/marketplace-capabilities-v2.md"
2551
+ ],
2552
+ summary: "Canada marketplace registry facts are code-owned: marketplace ID, country, domain, currency, reporting timezone, Seller Central host, SP-API endpoint, and Ads endpoint."
2553
+ },
2554
+ {
2555
+ id: "ca.seller-central-url.v1",
2556
+ status: "recorded",
2557
+ marketplaceId: CANADA_MARKETPLACE_ID,
2558
+ toolFamily: "all",
2559
+ operation: "all",
2560
+ sourceType: "repo_registry",
2561
+ artifactPath: "packages/shared/src/marketplaces.ts",
2562
+ supportingArtifactPaths: ["docs/internal/runbooks/marketplace-capabilities-v2.md"],
2563
+ summary: "Canada Seller Central base URL is recorded as https://sellercentral.amazon.ca in the marketplace registry."
2564
+ },
2565
+ {
2566
+ id: "ca.timezone-source.v1",
2567
+ status: "recorded",
2568
+ marketplaceId: CANADA_MARKETPLACE_ID,
2569
+ toolFamily: "all",
2570
+ operation: "all",
2571
+ sourceType: "repo_registry",
2572
+ artifactPath: "packages/shared/src/marketplaces.ts",
2573
+ supportingArtifactPaths: [
2574
+ "packages/shared/src/marketplaces.test.ts",
2575
+ "docs/internal/runbooks/marketplace-capabilities-v2.md"
2576
+ ],
2577
+ summary: "Canada default reporting timezone is recorded as America/Toronto and validated through shared marketplace registry tests."
2578
+ },
2579
+ {
2580
+ id: "ca.promotion-effects.v1",
2581
+ status: "recorded",
2582
+ marketplaceId: CANADA_MARKETPLACE_ID,
2583
+ toolFamily: "all",
2584
+ operation: "all",
2585
+ sourceType: "repo_policy",
2586
+ artifactPath: "packages/shared/src/marketplace-capabilities.ts",
2587
+ supportingArtifactPaths: [
2588
+ "packages/shared/src/marketplace-capabilities.test.ts",
2589
+ "packages/shared/src/marketplace-capabilities.contract.test.ts",
2590
+ "docs/internal/runbooks/marketplace-capabilities-v2.md"
2591
+ ],
2592
+ summary: "Canada policy effects are explicit: Canada Ads, catalog, and fulfillment write-family rows are enabled; UK, Saudi Arabia, unknown marketplaces, and unconfigured marketplace/tool-family combinations remain default-denied."
2593
+ },
2594
+ {
2595
+ id: "ca.ads-write-enabled.repo-contract.v1",
2596
+ status: "recorded",
2597
+ marketplaceId: CANADA_MARKETPLACE_ID,
2598
+ toolFamily: "ads_write",
2599
+ operation: "write",
2600
+ sourceType: "repo_contract_test",
2601
+ artifactPath: "packages/shared/src/marketplace-capabilities.test.ts",
2602
+ supportingArtifactPaths: [
2603
+ "packages/shared/src/marketplace-capabilities.contract.test.ts",
2604
+ "packages/hosted-server/src/util/marketplace-write-safety.test.ts"
2605
+ ],
2606
+ summary: "Repo tests cover Canada Ads write-family policy as enabled with CAD marketplace facts, Ads connection requirements, and runtime endpoint/marketplace-scope write safety preserved."
2607
+ },
2608
+ {
2609
+ id: "ca.catalog-write-enabled.repo-contract.v1",
2610
+ status: "recorded",
2611
+ marketplaceId: CANADA_MARKETPLACE_ID,
2612
+ toolFamily: "catalog_write",
2613
+ operation: "write",
2614
+ sourceType: "repo_contract_test",
2615
+ artifactPath: "packages/shared/src/marketplace-capabilities.test.ts",
2616
+ supportingArtifactPaths: [
2617
+ "packages/shared/src/marketplace-capabilities.contract.test.ts",
2618
+ "packages/hosted-server/src/util/marketplace-write-safety.test.ts",
2619
+ "packages/hosted-server/src/tools/catalog/update-price.test.ts"
2620
+ ],
2621
+ summary: "Repo tests cover Canada catalog preview and write policy as enabled with CAD marketplace facts and runtime endpoint/marketplace-scope write safety preserved."
2622
+ },
2623
+ {
2624
+ id: "ca.fulfillment-write-enabled.repo-contract.v1",
2625
+ status: "recorded",
2626
+ marketplaceId: CANADA_MARKETPLACE_ID,
2627
+ toolFamily: "fulfillment_write",
2628
+ operation: "write",
2629
+ sourceType: "repo_contract_test",
2630
+ artifactPath: "packages/shared/src/marketplace-capabilities.test.ts",
2631
+ supportingArtifactPaths: [
2632
+ "packages/shared/src/marketplace-capabilities.contract.test.ts",
2633
+ "packages/hosted-server/src/util/marketplace-write-safety.test.ts"
2634
+ ],
2635
+ summary: "Repo tests cover Canada fulfillment write-family policy as enabled with CAD marketplace facts, SP-API connection requirements, and runtime endpoint/marketplace-scope write safety preserved."
2636
+ },
2637
+ {
2638
+ id: "ca.ads-readonly-smoke.pending",
2639
+ status: "pending",
2640
+ marketplaceId: CANADA_MARKETPLACE_ID,
2641
+ toolFamily: "ads_write",
2642
+ operation: "read",
2643
+ sourceType: "live_smoke",
2644
+ artifactPath: "docs/internal/evidence/marketplace-capabilities/canada-ads-readonly-smoke-template.md",
2645
+ supportingArtifactPaths: ["docs/internal/runbooks/marketplace-capabilities-v2.md"],
2646
+ summary: "Controlled read-only Canada Ads smoke evidence is pending and has not been performed in this repo-only enablement change.",
2647
+ notes: "Optional live evidence; requires explicit approval, controlled credentials, and no mutation calls before it can be changed to recorded."
2648
+ },
2649
+ {
2650
+ id: "ca.spapi-readonly-smoke.pending",
2651
+ status: "pending",
2652
+ marketplaceId: CANADA_MARKETPLACE_ID,
2653
+ toolFamily: "all",
2654
+ operation: "read",
2655
+ sourceType: "live_smoke",
2656
+ artifactPath: "docs/internal/evidence/marketplace-capabilities/canada-spapi-readonly-smoke-template.md",
2657
+ supportingArtifactPaths: ["docs/internal/runbooks/marketplace-capabilities-v2.md"],
2658
+ summary: "Controlled read-only Canada SP-API smoke evidence is pending and has not been performed in this repo-only enablement change.",
2659
+ notes: "Optional live evidence; requires explicit approval, controlled credentials, and no mutation calls before it can be changed to recorded."
2660
+ },
2661
+ {
2662
+ id: "ca.catalog-update-price-cad-preview.repo-proof.v1",
2663
+ status: "recorded",
2664
+ marketplaceId: CANADA_MARKETPLACE_ID,
2665
+ toolFamily: "catalog_write",
2666
+ operation: "preview",
2667
+ sourceType: "repo_tool_test",
2668
+ artifactPath: "packages/shared/src/marketplace-capabilities.test.ts",
2669
+ supportingArtifactPaths: [
2670
+ "packages/shared/src/marketplace-capabilities.contract.test.ts",
2671
+ "packages/hosted-server/src/util/marketplace-write-safety.test.ts",
2672
+ "packages/hosted-server/src/tools/catalog/update-price.test.ts",
2673
+ "docs/internal/runbooks/marketplace-capabilities-v2.md"
2674
+ ],
2675
+ summary: "Repo tests prove Canada update_price validation preview is CAD-scoped and uses Canada marketplace facts while Canada catalog write-family policy is enabled."
2676
+ }
2677
+ ];
2678
+ var MARKETPLACE_CAPABILITY_EVIDENCE_BY_ID = new Map(
2679
+ MARKETPLACE_CAPABILITY_EVIDENCE_REGISTRY.map((record) => [record.id, record])
2680
+ );
2681
+ function getMarketplaceCapabilityEvidenceRecord(id) {
2682
+ return MARKETPLACE_CAPABILITY_EVIDENCE_BY_ID.get(id);
2683
+ }
2684
+ var MARKETPLACE_CAPABILITY_EVIDENCE_CAPTURE_SCHEMA_VERSION = "marketplace-capability-evidence-capture.v1";
2685
+ var MARKETPLACE_CAPABILITY_EVIDENCE_CAPTURE_STATUSES = ["example", "captured", "failed"];
2686
+ var MARKETPLACE_CAPABILITY_EVIDENCE_CAPTURE_SOURCE_TYPES = [
2687
+ "ads_api_readonly_smoke",
2688
+ "sp_api_readonly_smoke"
2689
+ ];
2690
+ var READ_ONLY_HTTP_METHODS = ["GET", "HEAD", "OPTIONS"];
2691
+ var AMAZON_REGIONS = ["NA", "EU", "FE"];
2692
+ var API_SERVICES = ["ads", "sp_api"];
2693
+ var EVIDENCE_FACT_SOURCES = [
2694
+ "response_body",
2695
+ "response_header",
2696
+ "request_context",
2697
+ "amazon_marketplace_metadata",
2698
+ "repo_registry_fallback",
2699
+ "operator_observation"
2700
+ ];
2701
+ var CAPTURED_AT_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/;
2702
+ var REPO_RELATIVE_PATH_PATTERN = /^(?!\/)(?![a-z][a-z\d+.-]*:)[\w./@-]+$/i;
2703
+ var REDACTION_PLACEHOLDER_PATTERN = /(?:\[(?:redacted|masked)\]|<(?:redacted|masked)>|\b(?:redacted|masked)(?:[_-][a-z0-9]+)*\b|\*{3,})/i;
2704
+ var REDACTED_PATH_SEGMENT = "[redacted-key]";
2705
+ var REDACTED_VALUE_SEGMENT = "[redacted-value]";
2706
+ var EXAMPLE_DOMAIN_PATTERN = /(?:^|\.)example\.(?:invalid|com|net|org)$/i;
2707
+ var BEARER_TOKEN_PATTERN = /\bBearer\s+([^\s"',;]+)/gi;
2708
+ var AUTHORIZATION_HEADER_PATTERN = /\bauthorization\b\s*[:=]\s*["']?(?:(?:Bearer|Basic|AWS4-HMAC-SHA256)\s+)?([^\s"',;]+)/gi;
2709
+ var SENSITIVE_ASSIGNMENT_PATTERN = /\b(?:access[_-]?token|refresh[_-]?token|id[_-]?token|client[_-]?secret|api[_-]?key)\b\s*[:=]\s*["']?([^\s"',;&]+)/gi;
2710
+ var AGENTCENTRAL_API_KEY_PATTERN = /\bac_(?:live|test|dev)_[A-Za-z0-9_-]{8,}\b/g;
2711
+ var AMAZON_TOKEN_PATTERN = /\bamz_[A-Za-z0-9_-]{8,}\b/gi;
2712
+ var AWS_ACCESS_KEY_PATTERN = /\b(?:AKIA|ASIA)[0-9A-Z]{16}\b/g;
2713
+ var EMAIL_ADDRESS_PATTERN = /\b[A-Z0-9._%+-]+@([A-Z0-9.-]+\.[A-Z]{2,})\b/gi;
2714
+ var PHONE_NUMBER_PATTERN = /(?:\+?\d{1,3}[\s.-]*)?(?:\(\d{3}\)|\d{3})[\s.-]\d{3}[\s.-]\d{4}\b/g;
2715
+ var INTERNATIONAL_PHONE_NUMBER_PATTERN = /\+\d{10,15}\b/g;
2716
+ var LONG_KEY_LIKE_PATTERN = /(?<![A-Za-z0-9_+=/-])(?:[A-Za-z0-9_+=/-]{32,})(?![A-Za-z0-9_+=/-])/g;
2717
+ var httpsUrlSchema = z4.string().url().refine((value) => {
2718
+ try {
2719
+ return new URL(value).protocol === "https:";
2720
+ } catch {
2721
+ return false;
2722
+ }
2723
+ }, "Expected an HTTPS URL");
2724
+ var capturedAtSchema = z4.string().regex(CAPTURED_AT_PATTERN, "Expected an ISO-8601 UTC timestamp, for example 2026-05-17T12:34:56.000Z").refine((value) => !Number.isNaN(Date.parse(value)), "Expected a parseable UTC timestamp");
2725
+ var registryEvidenceIdSchema = z4.string().min(1);
2726
+ var evidenceFactSchema = z4.object({
2727
+ expected: z4.string().min(1),
2728
+ observed: z4.string().min(1).nullable(),
2729
+ source: z4.enum(EVIDENCE_FACT_SOURCES),
2730
+ matchesExpected: z4.boolean(),
2731
+ notes: z4.string().min(1).optional()
2732
+ }).strict();
2733
+ var readOnlyCallSummarySchema = z4.object({
2734
+ operationName: z4.string().min(1),
2735
+ method: z4.enum(READ_ONLY_HTTP_METHODS),
2736
+ endpointPath: z4.string().min(1),
2737
+ redactedUrl: z4.string().min(1),
2738
+ responseStatus: z4.number().int().min(100).max(599).optional(),
2739
+ returnedFieldNames: z4.array(z4.string().min(1)).min(1),
2740
+ redactedResponseShape: z4.record(z4.unknown()).optional(),
2741
+ notes: z4.string().min(1).optional()
2742
+ }).strict();
2743
+ var noMutationAttestationSchema = z4.object({
2744
+ requestSetReadOnly: z4.literal(true),
2745
+ noMutationEndpointsCalled: z4.literal(true),
2746
+ noMcpWriteToolsRun: z4.literal(true),
2747
+ noSyncsTriggered: z4.literal(true),
2748
+ noApiKeyMutations: z4.literal(true),
2749
+ noDeployments: z4.literal(true),
2750
+ noProductionOrCustomerDataMutated: z4.literal(true),
2751
+ statement: z4.string().min(1)
2752
+ }).strict();
2753
+ var redactionAttestationSchema = z4.object({
2754
+ tokensAndSecretsRedacted: z4.literal(true),
2755
+ authorizationHeadersRedacted: z4.literal(true),
2756
+ refreshTokensRedacted: z4.literal(true),
2757
+ customerPiiRedacted: z4.literal(true),
2758
+ accountIdentifiersRedacted: z4.literal(true),
2759
+ rawPayloadsMinimized: z4.literal(true),
2760
+ statement: z4.string().min(1)
2761
+ }).strict();
2762
+ var approvalReferenceSchema = z4.object({
2763
+ reference: z4.string().min(1),
2764
+ approvedBy: z4.string().min(1),
2765
+ approvedAt: capturedAtSchema.optional(),
2766
+ approvedReadOnlyEndpoints: z4.array(z4.string().min(1)).min(1),
2767
+ notes: z4.string().min(1).optional()
2768
+ }).strict();
2769
+ var operatorContextSchema = z4.object({
2770
+ environment: z4.string().min(1),
2771
+ commitSha: z4.string().min(1),
2772
+ command: z4.string().min(1),
2773
+ notes: z4.string().min(1).optional()
2774
+ }).strict();
2775
+ var endpointObservationSchema = z4.object({
2776
+ service: z4.enum(API_SERVICES),
2777
+ region: z4.enum(AMAZON_REGIONS),
2778
+ expectedBaseUrl: httpsUrlSchema,
2779
+ observedBaseUrl: httpsUrlSchema,
2780
+ observedHost: z4.string().min(1),
2781
+ notes: z4.string().min(1).optional()
2782
+ }).strict();
2783
+ var artifactReferenceSchema = z4.object({
2784
+ path: z4.string().regex(REPO_RELATIVE_PATH_PATTERN, "Expected a repository-relative artifact path"),
2785
+ kind: z4.enum(["example_fixture", "captured_artifact"]),
2786
+ notes: z4.string().min(1)
2787
+ }).strict();
2788
+ var marketplaceCapabilityEvidenceCaptureBaseSchema = z4.object({
2789
+ schemaVersion: z4.literal(MARKETPLACE_CAPABILITY_EVIDENCE_CAPTURE_SCHEMA_VERSION),
2790
+ captureId: z4.string().min(1),
2791
+ evidenceId: registryEvidenceIdSchema,
2792
+ registryEvidenceIds: z4.array(registryEvidenceIdSchema).min(1),
2793
+ marketplaceId: z4.string().min(1),
2794
+ sourceType: z4.enum(MARKETPLACE_CAPABILITY_EVIDENCE_CAPTURE_SOURCE_TYPES),
2795
+ status: z4.enum(MARKETPLACE_CAPABILITY_EVIDENCE_CAPTURE_STATUSES),
2796
+ capturedAt: capturedAtSchema.optional(),
2797
+ approvalReference: approvalReferenceSchema,
2798
+ operator: operatorContextSchema,
2799
+ endpoint: endpointObservationSchema,
2800
+ observedFacts: z4.object({
2801
+ marketplaceId: evidenceFactSchema,
2802
+ countryCode: evidenceFactSchema,
2803
+ currencyCode: evidenceFactSchema,
2804
+ reportingTimeZone: evidenceFactSchema
2805
+ }).strict(),
2806
+ readOnlyCalls: z4.array(readOnlyCallSummarySchema).min(1),
2807
+ noMutationAttestation: noMutationAttestationSchema,
2808
+ redactionAttestation: redactionAttestationSchema,
2809
+ artifact: artifactReferenceSchema,
2810
+ notes: z4.string().min(1).optional()
2811
+ }).strict();
2812
+ function addIssue(ctx, path, message) {
2813
+ ctx.addIssue({ code: z4.ZodIssueCode.custom, path: sanitizeIssuePath(path), message: safeIssueDisplay(message) });
2814
+ }
2815
+ function hostForUrl(value) {
2816
+ try {
2817
+ return new URL(value).host;
2818
+ } catch {
2819
+ return null;
2820
+ }
2821
+ }
2822
+ function pathToString(path) {
2823
+ const safePath = sanitizeRedactionPath(path);
2824
+ if (safePath.length === 0) {
2825
+ return "capture";
2826
+ }
2827
+ return safePath.reduce((formattedPath, segment) => {
2828
+ if (typeof segment === "number") {
2829
+ return `${formattedPath}[${segment}]`;
2830
+ }
2831
+ return formattedPath ? `${formattedPath}.${segment}` : segment;
2832
+ }, "");
2833
+ }
2834
+ function stripTokenWrapper(value) {
2835
+ return value.trim().replace(/^["'`]+|["'`,.;]+$/g, "");
2836
+ }
2837
+ function hasRedactionPlaceholder(value) {
2838
+ return REDACTION_PLACEHOLDER_PATTERN.test(value);
2839
+ }
2840
+ function isExampleDomain(domain) {
2841
+ return EXAMPLE_DOMAIN_PATTERN.test(domain.toLowerCase());
2842
+ }
2843
+ function isAllowedPlaceholderValue(value) {
2844
+ const trimmed = stripTokenWrapper(value);
2845
+ const lower = trimmed.toLowerCase();
2846
+ return hasRedactionPlaceholder(trimmed) || /^0{12,}$/.test(trimmed) || /^x{6,}$/i.test(trimmed) || /^(?:example|synthetic|fixture)(?:[._:/ -][a-z0-9-]+)*$/i.test(trimmed) || lower === "example_only_no_approval" || lower === "example fixture only" || lower.startsWith("not run - offline example");
2847
+ }
2848
+ function isSensitiveFieldName(segment) {
2849
+ const normalized = segment.replace(/[^a-z0-9]/gi, "").toLowerCase();
2850
+ if (normalized.includes("redacted") || normalized.includes("masked") || normalized.includes("placeholder")) {
2851
+ return false;
2852
+ }
2853
+ return normalized === "authorization" || normalized === "proxyauthorization" || normalized === "apikey" || normalized === "xapikey" || normalized === "apitoken" || normalized === "accesstoken" || normalized === "refreshtoken" || normalized === "idtoken" || normalized === "clientsecret" || normalized === "secret" || normalized.endsWith("apikey") || normalized.endsWith("token") || normalized.endsWith("secret");
2854
+ }
2855
+ function lastStringPathSegment(path) {
2856
+ for (let index = path.length - 1; index >= 0; index -= 1) {
2857
+ const segment = path[index];
2858
+ if (typeof segment === "string") {
2859
+ return segment;
2860
+ }
2861
+ }
2862
+ return null;
2863
+ }
2864
+ function isSensitiveFieldPath(path) {
2865
+ const segment = lastStringPathSegment(path);
2866
+ return segment ? isSensitiveFieldName(segment) : false;
2867
+ }
2868
+ function isCommitShaPath(path) {
2869
+ return lastStringPathSegment(path) === "commitSha";
2870
+ }
2871
+ function shouldSkipGenericLongKeyScan(path) {
2872
+ const segment = lastStringPathSegment(path);
2873
+ return segment === "schemaVersion" || segment === "captureId" || segment === "evidenceId" || segment === "marketplaceId" || segment === "sourceType" || segment === "endpointPath" || segment === "redactedUrl" || segment === "expectedBaseUrl" || segment === "observedBaseUrl" || segment === "observedHost" || segment === "path" || path.includes("registryEvidenceIds") || path.includes("approvedReadOnlyEndpoints") || path.includes("returnedFieldNames");
2874
+ }
2875
+ function isAllowedEmailAddress(value) {
2876
+ const domain = value.split("@").pop();
2877
+ return Boolean(domain && isExampleDomain(domain)) || hasRedactionPlaceholder(value);
2878
+ }
2879
+ function isAllowedPhoneNumber(value) {
2880
+ const digits = value.replace(/\D/g, "");
2881
+ return /^0+$/.test(digits) || /^1?\d{3}55501\d{2}$/.test(digits) || hasRedactionPlaceholder(value);
2882
+ }
2883
+ function looksLikeLongKey(candidate) {
2884
+ if (isAllowedPlaceholderValue(candidate)) {
2885
+ return false;
2886
+ }
2887
+ const hasLetter = /[A-Za-z]/.test(candidate);
2888
+ const hasDigit = /\d/.test(candidate);
2889
+ const hasCredentialSeparator = /[_+=]/.test(candidate);
2890
+ const hasMixedCase = /[a-z]/.test(candidate) && /[A-Z]/.test(candidate);
2891
+ const isHexBlob = /^[a-f0-9]{32,}$/i.test(candidate);
2892
+ return hasLetter && hasDigit && (hasCredentialSeparator || hasMixedCase || isHexBlob);
2893
+ }
2894
+ function addUniqueRedactionCategory(categories, category) {
2895
+ if (!categories.includes(category)) {
2896
+ categories.push(category);
2897
+ }
2898
+ }
2899
+ function collectRedactionIssueCategories(value, path, options = {}) {
2900
+ const categories = [];
2901
+ const checkSensitiveFieldPath = options.checkSensitiveFieldPath ?? true;
2902
+ const checkGenericLongKey = options.checkGenericLongKey ?? true;
2903
+ if (checkSensitiveFieldPath && isSensitiveFieldPath(path) && !isAllowedPlaceholderValue(value)) {
2904
+ addUniqueRedactionCategory(categories, "sensitive field value");
2905
+ }
2906
+ for (const match of value.matchAll(BEARER_TOKEN_PATTERN)) {
2907
+ const token = match[1];
2908
+ if (token && !isAllowedPlaceholderValue(token)) {
2909
+ addUniqueRedactionCategory(categories, "bearer token");
2910
+ }
2911
+ }
2912
+ for (const match of value.matchAll(AUTHORIZATION_HEADER_PATTERN)) {
2913
+ const headerValue = match[1];
2914
+ if (headerValue && !isAllowedPlaceholderValue(headerValue)) {
2915
+ addUniqueRedactionCategory(categories, "authorization header value");
2916
+ }
2917
+ }
2918
+ for (const match of value.matchAll(SENSITIVE_ASSIGNMENT_PATTERN)) {
2919
+ const assignedValue = match[1];
2920
+ if (assignedValue && !isAllowedPlaceholderValue(assignedValue)) {
2921
+ addUniqueRedactionCategory(categories, "token or secret assignment");
2922
+ }
2923
+ }
2924
+ for (const match of value.matchAll(AGENTCENTRAL_API_KEY_PATTERN)) {
2925
+ if (!isAllowedPlaceholderValue(match[0])) {
2926
+ addUniqueRedactionCategory(categories, "agentcentral API key");
2927
+ }
2928
+ }
2929
+ for (const match of value.matchAll(AMAZON_TOKEN_PATTERN)) {
2930
+ if (!isAllowedPlaceholderValue(match[0])) {
2931
+ addUniqueRedactionCategory(categories, "Amazon token");
2932
+ }
2933
+ }
2934
+ for (const match of value.matchAll(AWS_ACCESS_KEY_PATTERN)) {
2935
+ if (!isAllowedPlaceholderValue(match[0])) {
2936
+ addUniqueRedactionCategory(categories, "AWS access key");
2937
+ }
2938
+ }
2939
+ for (const match of value.matchAll(EMAIL_ADDRESS_PATTERN)) {
2940
+ if (!isAllowedEmailAddress(match[0])) {
2941
+ addUniqueRedactionCategory(categories, "email address");
2942
+ }
2943
+ }
2944
+ for (const match of value.matchAll(PHONE_NUMBER_PATTERN)) {
2945
+ if (!isAllowedPhoneNumber(match[0])) {
2946
+ addUniqueRedactionCategory(categories, "phone number");
2947
+ }
2948
+ }
2949
+ for (const match of value.matchAll(INTERNATIONAL_PHONE_NUMBER_PATTERN)) {
2950
+ if (!isAllowedPhoneNumber(match[0])) {
2951
+ addUniqueRedactionCategory(categories, "phone number");
2952
+ }
2953
+ }
2954
+ if (!checkGenericLongKey || isCommitShaPath(path) || shouldSkipGenericLongKeyScan(path)) {
2955
+ return categories;
2956
+ }
2957
+ for (const match of value.matchAll(LONG_KEY_LIKE_PATTERN)) {
2958
+ if (looksLikeLongKey(match[0])) {
2959
+ addUniqueRedactionCategory(categories, "long key-like string");
2960
+ }
2961
+ }
2962
+ return categories;
2963
+ }
2964
+ function shouldRedactCapturedCredentialValue(value) {
2965
+ const normalized = stripTokenWrapper(value).toLowerCase();
2966
+ return normalized !== "token" && normalized !== "secret" && normalized !== "value" && normalized !== "key" && normalized !== "credential" && normalized !== "credentials" && !isAllowedPlaceholderValue(value);
2967
+ }
2968
+ function replaceSensitiveSubstrings(value, placeholder) {
2969
+ let sanitized = value;
2970
+ sanitized = sanitized.replace(BEARER_TOKEN_PATTERN, (match, token) => {
2971
+ if (!token || !shouldRedactCapturedCredentialValue(token)) {
2972
+ return match;
2973
+ }
2974
+ return match.replace(token, placeholder);
2975
+ });
2976
+ sanitized = sanitized.replace(AUTHORIZATION_HEADER_PATTERN, (match, headerValue) => {
2977
+ if (!headerValue || !shouldRedactCapturedCredentialValue(headerValue)) {
2978
+ return match;
2979
+ }
2980
+ return match.replace(headerValue, placeholder);
2981
+ });
2982
+ sanitized = sanitized.replace(SENSITIVE_ASSIGNMENT_PATTERN, (match, assignedValue) => {
2983
+ if (!assignedValue || !shouldRedactCapturedCredentialValue(assignedValue)) {
2984
+ return match;
2985
+ }
2986
+ return match.replace(assignedValue, placeholder);
2987
+ });
2988
+ sanitized = sanitized.replace(AGENTCENTRAL_API_KEY_PATTERN, (match) => {
2989
+ return isAllowedPlaceholderValue(match) ? match : placeholder;
2990
+ });
2991
+ sanitized = sanitized.replace(AMAZON_TOKEN_PATTERN, (match) => {
2992
+ return isAllowedPlaceholderValue(match) ? match : placeholder;
2993
+ });
2994
+ sanitized = sanitized.replace(AWS_ACCESS_KEY_PATTERN, (match) => {
2995
+ return isAllowedPlaceholderValue(match) ? match : placeholder;
2996
+ });
2997
+ sanitized = sanitized.replace(EMAIL_ADDRESS_PATTERN, (match) => {
2998
+ return isAllowedEmailAddress(match) ? match : placeholder;
2999
+ });
3000
+ sanitized = sanitized.replace(PHONE_NUMBER_PATTERN, (match) => {
3001
+ return isAllowedPhoneNumber(match) ? match : placeholder;
3002
+ });
3003
+ sanitized = sanitized.replace(INTERNATIONAL_PHONE_NUMBER_PATTERN, (match) => {
3004
+ return isAllowedPhoneNumber(match) ? match : placeholder;
3005
+ });
3006
+ sanitized = sanitized.replace(LONG_KEY_LIKE_PATTERN, (match) => {
3007
+ return looksLikeLongKey(match) ? placeholder : match;
3008
+ });
3009
+ return sanitized;
3010
+ }
3011
+ function safeIssueDisplay(value) {
3012
+ return replaceSensitiveSubstrings(value, REDACTED_VALUE_SEGMENT);
3013
+ }
3014
+ function safeIssueKeyDisplay(value) {
3015
+ return replaceSensitiveSubstrings(value, REDACTED_PATH_SEGMENT);
3016
+ }
3017
+ function sanitizeIssuePath(path) {
3018
+ return path.map((segment) => {
3019
+ if (typeof segment === "string") {
3020
+ return safeIssueKeyDisplay(segment);
3021
+ }
3022
+ return segment;
3023
+ });
3024
+ }
3025
+ function pathSegmentContainsSensitiveEvidence(segment) {
3026
+ return collectRedactionIssueCategories(segment, [segment], {
3027
+ checkSensitiveFieldPath: false,
3028
+ checkGenericLongKey: true
3029
+ }).length > 0;
3030
+ }
3031
+ function sanitizeRedactionPath(path) {
3032
+ return path.map((segment) => {
3033
+ if (typeof segment === "string" && pathSegmentContainsSensitiveEvidence(segment)) {
3034
+ return REDACTED_PATH_SEGMENT;
3035
+ }
3036
+ return segment;
3037
+ });
3038
+ }
3039
+ function addRedactionIssue(ctx, path, category) {
3040
+ const safePath = sanitizeRedactionPath(path);
3041
+ addIssue(
3042
+ ctx,
3043
+ safePath,
3044
+ `Potential unredacted ${category} in evidence capture at ${pathToString(safePath)}; replace the value or dynamic key with [REDACTED], <redacted>, ***, REDACTED, an example.invalid address, or another explicit synthetic placeholder.`
3045
+ );
3046
+ }
3047
+ function validateEvidenceStringRedaction(value, path, ctx) {
3048
+ collectRedactionIssueCategories(value, path).forEach((category) => {
3049
+ addRedactionIssue(ctx, path, category);
3050
+ });
3051
+ }
3052
+ function validateEvidenceObjectKeyRedaction(key, path, ctx) {
3053
+ const keyPath = [...path, key];
3054
+ collectRedactionIssueCategories(key, keyPath, {
3055
+ checkSensitiveFieldPath: false,
3056
+ checkGenericLongKey: true
3057
+ }).forEach((category) => {
3058
+ addRedactionIssue(ctx, keyPath, `object key ${category}`);
3059
+ });
3060
+ }
3061
+ function validateEvidenceRedactionGuardrails(value, ctx, path = []) {
3062
+ if (typeof value === "string") {
3063
+ validateEvidenceStringRedaction(value, path, ctx);
3064
+ return;
3065
+ }
3066
+ if (Array.isArray(value)) {
3067
+ value.forEach((item, index) => validateEvidenceRedactionGuardrails(item, ctx, [...path, index]));
3068
+ return;
3069
+ }
3070
+ if (value && typeof value === "object") {
3071
+ Object.entries(value).forEach(([key, nestedValue]) => {
3072
+ validateEvidenceObjectKeyRedaction(key, path, ctx);
3073
+ validateEvidenceRedactionGuardrails(nestedValue, ctx, [...path, key]);
3074
+ });
3075
+ }
3076
+ }
3077
+ function validateRegistryLinks(capture, ctx) {
3078
+ const uniqueEvidenceIds = new Set(capture.registryEvidenceIds);
3079
+ if (uniqueEvidenceIds.size !== capture.registryEvidenceIds.length) {
3080
+ addIssue(ctx, ["registryEvidenceIds"], "Expected registry evidence IDs to be unique");
3081
+ }
3082
+ if (!uniqueEvidenceIds.has(capture.evidenceId)) {
3083
+ addIssue(ctx, ["evidenceId"], "Primary evidence ID must also appear in registryEvidenceIds");
3084
+ }
3085
+ const primaryRecord = getMarketplaceCapabilityEvidenceRecord(capture.evidenceId);
3086
+ if (!primaryRecord) {
3087
+ addIssue(ctx, ["evidenceId"], `Unknown marketplace capability evidence ID: ${safeIssueDisplay(capture.evidenceId)}`);
3088
+ } else {
3089
+ if (primaryRecord.sourceType !== "live_smoke") {
3090
+ addIssue(ctx, ["evidenceId"], "Capture artifacts are only valid for live_smoke registry records");
316
3091
  }
317
- if (res.status === 401) {
318
- throw new CliError(
319
- 3 /* AuthError */,
320
- "Authentication failed (HTTP 401): the API key was rejected by the hosted server.",
321
- method
322
- );
3092
+ if (primaryRecord.operation !== "read") {
3093
+ addIssue(ctx, ["evidenceId"], "Capture artifacts are only valid for read-only registry records");
323
3094
  }
324
- if (res.status === 429 || res.status >= 500) {
325
- const retryAfterMs = retry.honorRetryAfter ? parseRetryAfterMs(res.headers.get("retry-after"), Date.now()) : void 0;
326
- throw new RetryableError(`HTTP ${res.status}`, {
327
- status: res.status,
328
- retryAfterMs
329
- });
3095
+ }
3096
+ const nonMarketplaceScopes = /* @__PURE__ */ new Set([
3097
+ GLOBAL_MARKETPLACE_CAPABILITY_EVIDENCE_SCOPE,
3098
+ COMMON_MARKETPLACE_CAPABILITY_EVIDENCE_SCOPE
3099
+ ]);
3100
+ capture.registryEvidenceIds.forEach((evidenceId, index) => {
3101
+ const record = getMarketplaceCapabilityEvidenceRecord(evidenceId);
3102
+ if (!record) {
3103
+ addIssue(ctx, ["registryEvidenceIds", index], `Unknown marketplace capability evidence ID: ${safeIssueDisplay(evidenceId)}`);
3104
+ return;
330
3105
  }
331
- const text = await res.text();
332
- if (!res.ok) {
333
- throw new CliError(
334
- 6 /* TransportFailure */,
335
- `HTTP ${res.status}: ${text.slice(0, 200)}`,
336
- method
3106
+ if (!nonMarketplaceScopes.has(record.marketplaceId) && record.marketplaceId !== capture.marketplaceId) {
3107
+ addIssue(
3108
+ ctx,
3109
+ ["registryEvidenceIds", index],
3110
+ `Evidence ID ${safeIssueDisplay(evidenceId)} is scoped to ${safeIssueDisplay(record.marketplaceId)}, not ${safeIssueDisplay(capture.marketplaceId)}`
337
3111
  );
338
3112
  }
339
- return parseSseJsonRpc(text);
340
- }
341
- async function rpc(method, params, rpcOpts) {
342
- const timeoutMs = rpcOpts?.timeoutMs ?? defaultTimeoutMs;
343
- const id = rpcOpts?.id ?? nextId();
344
- const maxAttempts = Math.max(1, retry.maxAttempts);
345
- let lastReason = "transport failure";
346
- for (let n = 1; n <= maxAttempts; n += 1) {
347
- try {
348
- return await attempt(method, params ?? {}, id, timeoutMs);
349
- } catch (error) {
350
- if (error instanceof CliError) {
351
- throw error;
352
- }
353
- if (!(error instanceof RetryableError)) {
354
- throw error;
355
- }
356
- lastReason = error.message;
357
- if (n >= maxAttempts) break;
358
- const backoffMs = retry.baseBackoffMs * 2 ** (n - 1);
359
- const delayMs = error.retryAfterMs ?? backoffMs;
360
- opts.onRetry?.({ attempt: n, delayMs, reason: lastReason });
361
- await sleep(delayMs);
362
- }
3113
+ });
3114
+ }
3115
+ function validateStatusFields(capture, ctx) {
3116
+ if (capture.status === "example") {
3117
+ if (capture.capturedAt) {
3118
+ addIssue(ctx, ["capturedAt"], "Example captures must omit capturedAt so they are not mistaken for recorded evidence");
363
3119
  }
364
- throw new CliError(
365
- 6 /* TransportFailure */,
366
- `Transport failure after ${maxAttempts} attempt(s): ${lastReason}`,
367
- method
368
- );
369
- }
370
- async function listTools(listOpts) {
371
- const response = await rpc("tools/list", {}, { timeoutMs: listOpts?.timeoutMs });
372
- if (response.error) {
373
- throw new CliError(7 /* ToolExecutionFailed */, response.error.message, "tools/list");
3120
+ if (capture.artifact.kind !== "example_fixture") {
3121
+ addIssue(ctx, ["artifact", "kind"], "Example captures must use artifact.kind=example_fixture");
374
3122
  }
375
- const result = response.result ?? {};
376
- return result.tools ?? [];
3123
+ return;
377
3124
  }
378
- async function callTool(name, args, callOpts) {
379
- const response = await rpc(
380
- "tools/call",
381
- { name, arguments: args },
382
- { timeoutMs: callOpts?.timeoutMs }
383
- );
384
- if (response.error) {
385
- throw new CliError(7 /* ToolExecutionFailed */, response.error.message, name);
3125
+ if (!capture.capturedAt) {
3126
+ addIssue(ctx, ["capturedAt"], "Captured or failed real smoke captures must include capturedAt");
3127
+ }
3128
+ if (capture.artifact.kind !== "captured_artifact") {
3129
+ addIssue(ctx, ["artifact", "kind"], "Real smoke captures must use artifact.kind=captured_artifact");
3130
+ }
3131
+ }
3132
+ function validateMarketplaceFacts(capture, ctx) {
3133
+ const marketplace = getMarketplaceDefinition(capture.marketplaceId);
3134
+ if (!marketplace) {
3135
+ addIssue(ctx, ["marketplaceId"], `Unknown marketplace ID: ${safeIssueDisplay(capture.marketplaceId)}`);
3136
+ return;
3137
+ }
3138
+ const expectedFactValues = {
3139
+ marketplaceId: capture.marketplaceId,
3140
+ countryCode: marketplace.countryCode,
3141
+ currencyCode: marketplace.currencyCode,
3142
+ reportingTimeZone: marketplace.defaultReportingTimeZone
3143
+ };
3144
+ for (const [factName, expectedValue] of Object.entries(expectedFactValues)) {
3145
+ const fact = capture.observedFacts[factName];
3146
+ const factPath = ["observedFacts", factName];
3147
+ if (fact.expected !== expectedValue) {
3148
+ addIssue(ctx, [...factPath, "expected"], `Expected ${factName} to match marketplace registry value ${expectedValue}`);
3149
+ }
3150
+ if (fact.observed === null && fact.matchesExpected) {
3151
+ addIssue(ctx, [...factPath, "matchesExpected"], `Cannot mark ${factName} as matching when observed is null`);
3152
+ }
3153
+ if (fact.observed !== null && fact.matchesExpected !== (fact.observed === fact.expected)) {
3154
+ addIssue(ctx, [...factPath, "matchesExpected"], `matchesExpected must reflect whether observed equals expected for ${factName}`);
3155
+ }
3156
+ if (capture.status !== "failed" && (!fact.observed || !fact.matchesExpected)) {
3157
+ addIssue(ctx, factPath, `Non-failed captures must include matching observed ${factName} evidence`);
386
3158
  }
387
- return response.result ?? {};
388
3159
  }
389
- return { rpc, listTools, callTool };
3160
+ const expectedEndpoint = capture.sourceType === "ads_api_readonly_smoke" ? {
3161
+ service: "ads",
3162
+ region: marketplace.adsRegion,
3163
+ baseUrl: marketplace.adsApiBaseUrl
3164
+ } : {
3165
+ service: "sp_api",
3166
+ region: marketplace.spApiRegion,
3167
+ baseUrl: marketplace.spApiBaseUrl
3168
+ };
3169
+ if (capture.endpoint.service !== expectedEndpoint.service) {
3170
+ addIssue(ctx, ["endpoint", "service"], `Expected endpoint.service=${expectedEndpoint.service} for ${capture.sourceType}`);
3171
+ }
3172
+ if (capture.endpoint.region !== expectedEndpoint.region) {
3173
+ addIssue(ctx, ["endpoint", "region"], `Expected endpoint.region=${safeIssueDisplay(expectedEndpoint.region)} for marketplace ${safeIssueDisplay(capture.marketplaceId)}`);
3174
+ }
3175
+ if (capture.endpoint.expectedBaseUrl !== expectedEndpoint.baseUrl) {
3176
+ addIssue(ctx, ["endpoint", "expectedBaseUrl"], `Expected endpoint base URL to match registry value ${expectedEndpoint.baseUrl}`);
3177
+ }
3178
+ const observedHostFromUrl = hostForUrl(capture.endpoint.observedBaseUrl);
3179
+ if (observedHostFromUrl && observedHostFromUrl !== capture.endpoint.observedHost) {
3180
+ addIssue(ctx, ["endpoint", "observedHost"], "observedHost must match observedBaseUrl host");
3181
+ }
3182
+ const expectedHost = hostForUrl(expectedEndpoint.baseUrl);
3183
+ if (capture.status !== "failed" && expectedHost && capture.endpoint.observedHost !== expectedHost) {
3184
+ addIssue(ctx, ["endpoint", "observedHost"], `Non-failed captures must observe expected host ${expectedHost}`);
3185
+ }
390
3186
  }
391
-
392
- // src/commands/tools.ts
393
- import { readFile, writeFile } from "fs/promises";
394
- import { existsSync as existsSync2 } from "fs";
395
- import { TOOL_DOMAINS } from "@agent-central/shared";
3187
+ var marketplaceCapabilityEvidenceCaptureSchema = marketplaceCapabilityEvidenceCaptureBaseSchema.superRefine((capture, ctx) => {
3188
+ validateRegistryLinks(capture, ctx);
3189
+ validateStatusFields(capture, ctx);
3190
+ validateMarketplaceFacts(capture, ctx);
3191
+ validateEvidenceRedactionGuardrails(capture, ctx);
3192
+ });
396
3193
 
397
3194
  // src/format.ts
398
3195
  function isTabular(value) {
@@ -490,123 +3287,6 @@ function formatOutput(value, format) {
490
3287
  }
491
3288
  }
492
3289
 
493
- // src/exit-codes.ts
494
- var RPC_INVALID_PARAMS = -32602;
495
- var DETAIL_MAX_LENGTH = 180;
496
- var PERMISSION_PATTERN = /no_amazon|not connected|expired|suspended|revoked|past_due|trial expired|permission|not authorized|scope/i;
497
- var VALIDATION_PATTERN = /invalid|validation|must be|required/i;
498
- function writeEnvelopeFrom(result) {
499
- const structured = result.structuredContent;
500
- if (!structured) {
501
- return void 0;
502
- }
503
- const hasWriteShape = "mode" in structured || "status" in structured || "requested_count" in structured;
504
- if (!hasWriteShape) {
505
- return void 0;
506
- }
507
- return structured;
508
- }
509
- function toolClassification(def) {
510
- const hint = def.annotations;
511
- const annotationWrite = hint?.destructiveHint === true || hint?.readOnlyHint === false;
512
- const properties = def.inputSchema.properties;
513
- const props = properties && typeof properties === "object" ? properties : {};
514
- const schemaWrite = "confirm" in props && "idempotency_key" in props;
515
- const isWrite = annotationWrite || schemaWrite;
516
- return {
517
- isWrite,
518
- supportsPreview: isWrite
519
- };
520
- }
521
- function classifyToolText(text) {
522
- if (PERMISSION_PATTERN.test(text)) {
523
- return 4 /* PermissionDenied */;
524
- }
525
- if (VALIDATION_PATTERN.test(text)) {
526
- return 5 /* ValidationFailed */;
527
- }
528
- return void 0;
529
- }
530
- function joinContentText(result) {
531
- return result.content.map((block) => typeof block.text === "string" ? block.text : "").filter((text) => text.length > 0).join(" ").trim();
532
- }
533
- function truncateDetail(text) {
534
- if (text.length <= DETAIL_MAX_LENGTH) {
535
- return text;
536
- }
537
- return `${text.slice(0, DETAIL_MAX_LENGTH)}\u2026`;
538
- }
539
- function classifyWriteStatus(status) {
540
- switch (status) {
541
- case "validation_error":
542
- return 5 /* ValidationFailed */;
543
- case "partial":
544
- return 9 /* PartialWrite */;
545
- case "blocked":
546
- case "failed":
547
- return 7 /* ToolExecutionFailed */;
548
- case "duplicate_blocked":
549
- case "accepted":
550
- case "preview":
551
- default:
552
- return 0 /* Success */;
553
- }
554
- }
555
- function summarizeWriteEnvelope(env) {
556
- const parts = [];
557
- if (typeof env.requested_count === "number") {
558
- parts.push(`requested=${env.requested_count}`);
559
- }
560
- if (typeof env.accepted_count === "number") {
561
- parts.push(`accepted=${env.accepted_count}`);
562
- }
563
- if (typeof env.failed_count === "number") {
564
- parts.push(`failed=${env.failed_count}`);
565
- }
566
- if (typeof env.previewed_count === "number") {
567
- parts.push(`previewed=${env.previewed_count}`);
568
- }
569
- const status = env.status ?? "unknown";
570
- return parts.length > 0 ? `${status} (${parts.join(", ")})` : status;
571
- }
572
- function classifyResponse(response) {
573
- if (response.error) {
574
- const message = response.error.message;
575
- const code = response.error.code === RPC_INVALID_PARAMS ? 5 /* ValidationFailed */ : classifyToolText(message) ?? 7 /* ToolExecutionFailed */;
576
- return {
577
- code,
578
- status: "rpc_error",
579
- detail: message
580
- };
581
- }
582
- const result = response.result;
583
- const env = writeEnvelopeFrom(result);
584
- if (env?.status) {
585
- return {
586
- code: classifyWriteStatus(env.status),
587
- status: env.status,
588
- detail: summarizeWriteEnvelope(env),
589
- result
590
- };
591
- }
592
- if (result.isError) {
593
- const text = joinContentText(result);
594
- const code = classifyToolText(text) ?? 7 /* ToolExecutionFailed */;
595
- return {
596
- code,
597
- status: "tool_error",
598
- detail: truncateDetail(text),
599
- result
600
- };
601
- }
602
- return {
603
- code: 0 /* Success */,
604
- status: "ok",
605
- detail: truncateDetail(joinContentText(result)),
606
- result
607
- };
608
- }
609
-
610
3290
  // src/commands/tools.ts
611
3291
  function parseJsonArgs(text, origin) {
612
3292
  try {
@@ -766,6 +3446,14 @@ function selectOutputValue(result) {
766
3446
  return text;
767
3447
  }
768
3448
  }
3449
+ function warnIfLimitTruncated(ctx, value) {
3450
+ const limit = ctx.flags.limit;
3451
+ if (limit != null && Array.isArray(value) && value.length === limit) {
3452
+ ctx.err(
3453
+ `warning: result returned exactly --limit (${limit}) rows; output may be truncated. Raise --limit or narrow the query.`
3454
+ );
3455
+ }
3456
+ }
769
3457
  function echoWriteSummary(ctx, result) {
770
3458
  const env = writeEnvelopeFrom(result);
771
3459
  if (!env) {
@@ -803,6 +3491,7 @@ async function toolsCall(ctx, name, inputSpec) {
803
3491
  }
804
3492
  echoWriteSummary(ctx, result);
805
3493
  const value = selectOutputValue(result);
3494
+ warnIfLimitTruncated(ctx, value);
806
3495
  const rendered = formatOutput(value, ctx.flags.format);
807
3496
  if (ctx.flags.output) {
808
3497
  await writeFile(ctx.flags.output, rendered, { encoding: "utf8", mode: 384 });
@@ -821,9 +3510,8 @@ async function readStdinOnce() {
821
3510
  }
822
3511
 
823
3512
  // src/commands/mcp.ts
824
- import { TOOL_DOMAINS as TOOL_DOMAINS2 } from "@agent-central/shared";
825
- var DOMAIN_BY_TOOL = new Map(
826
- TOOL_DOMAINS2.flatMap(
3513
+ var DOMAIN_BY_TOOL2 = new Map(
3514
+ TOOL_DOMAINS.flatMap(
827
3515
  (domain) => domain.tools.map((tool) => [tool.name, domain.serverDomain])
828
3516
  )
829
3517
  );
@@ -834,7 +3522,7 @@ function filterToolsList(tools, opts) {
834
3522
  return false;
835
3523
  }
836
3524
  if (domainSet) {
837
- const domain = DOMAIN_BY_TOOL.get(def.name);
3525
+ const domain = DOMAIN_BY_TOOL2.get(def.name);
838
3526
  if (domain !== void 0 && !domainSet.has(domain)) {
839
3527
  return false;
840
3528
  }
@@ -861,7 +3549,7 @@ async function handleMessage(line, client, opts) {
861
3549
  const method = typeof message.method === "string" ? message.method : "";
862
3550
  if (message.id === void 0) {
863
3551
  try {
864
- await client.rpc(method, message.params);
3552
+ await client.rpc(method, message.params, { notification: true });
865
3553
  } catch {
866
3554
  }
867
3555
  return null;
@@ -934,9 +3622,9 @@ function pump(ctx, client, opts, input = process.stdin) {
934
3622
  return new Promise((resolve, reject) => {
935
3623
  input.setEncoding("utf8");
936
3624
  let buffer = "";
937
- let chain = Promise.resolve();
3625
+ const inflight = /* @__PURE__ */ new Set();
938
3626
  const dispatch = (line) => {
939
- chain = chain.then(async () => {
3627
+ const task = (async () => {
940
3628
  try {
941
3629
  const out = await handleMessage(line, client, opts);
942
3630
  if (out !== null) {
@@ -945,6 +3633,10 @@ function pump(ctx, client, opts, input = process.stdin) {
945
3633
  } catch (error) {
946
3634
  ctx.err(`bridge error: ${error instanceof Error ? error.message : String(error)}`);
947
3635
  }
3636
+ })();
3637
+ inflight.add(task);
3638
+ void task.finally(() => {
3639
+ inflight.delete(task);
948
3640
  });
949
3641
  };
950
3642
  input.on("data", (data) => {
@@ -966,10 +3658,10 @@ function pump(ctx, client, opts, input = process.stdin) {
966
3658
  if (tail.trim() !== "") {
967
3659
  dispatch(tail);
968
3660
  }
969
- chain.then(() => {
3661
+ Promise.allSettled([...inflight]).then(() => {
970
3662
  ctx.err("bridge stopped (stdin closed)");
971
3663
  resolve(0 /* Success */);
972
- }).catch(reject);
3664
+ }, reject);
973
3665
  });
974
3666
  });
975
3667
  }
@@ -1375,17 +4067,37 @@ async function profilesUse(ctx, name) {
1375
4067
  }
1376
4068
 
1377
4069
  // src/keychain.ts
1378
- import { Entry } from "@napi-rs/keyring";
4070
+ import { createRequire } from "module";
1379
4071
  var SERVICE = "agentcentral-cli";
1380
4072
  var DEFAULT_ACCOUNT = "default";
1381
4073
  var DISABLE_ENV = "AGENT_CENTRAL_DISABLE_KEYCHAIN";
4074
+ var entryClassCache = void 0;
4075
+ var loaderOverride = void 0;
1382
4076
  function disabled() {
1383
4077
  return process.env[DISABLE_ENV] === "1";
1384
4078
  }
4079
+ var requireNative = createRequire(import.meta.url);
4080
+ function loadEntryClass() {
4081
+ if (entryClassCache !== void 0) {
4082
+ return entryClassCache;
4083
+ }
4084
+ try {
4085
+ const loaded = loaderOverride ? loaderOverride() : requireNative("@napi-rs/keyring").Entry;
4086
+ entryClassCache = loaded;
4087
+ return loaded;
4088
+ } catch {
4089
+ entryClassCache = null;
4090
+ return null;
4091
+ }
4092
+ }
1385
4093
  function keychainAvailable() {
1386
4094
  if (disabled()) {
1387
4095
  return false;
1388
4096
  }
4097
+ const Entry = loadEntryClass();
4098
+ if (!Entry) {
4099
+ return false;
4100
+ }
1389
4101
  try {
1390
4102
  const entry = new Entry(SERVICE, DEFAULT_ACCOUNT);
1391
4103
  try {
@@ -1401,6 +4113,10 @@ function keychainGet(account) {
1401
4113
  if (disabled()) {
1402
4114
  return null;
1403
4115
  }
4116
+ const Entry = loadEntryClass();
4117
+ if (!Entry) {
4118
+ return null;
4119
+ }
1404
4120
  try {
1405
4121
  const entry = new Entry(SERVICE, account ?? DEFAULT_ACCOUNT);
1406
4122
  const secret = entry.getPassword();
@@ -1414,6 +4130,10 @@ function keychainSet(account, secret) {
1414
4130
  if (disabled()) {
1415
4131
  return false;
1416
4132
  }
4133
+ const Entry = loadEntryClass();
4134
+ if (!Entry) {
4135
+ return false;
4136
+ }
1417
4137
  try {
1418
4138
  const entry = new Entry(SERVICE, account ?? DEFAULT_ACCOUNT);
1419
4139
  entry.setPassword(secret);
@@ -1426,6 +4146,10 @@ function keychainDelete(account) {
1426
4146
  if (disabled()) {
1427
4147
  return false;
1428
4148
  }
4149
+ const Entry = loadEntryClass();
4150
+ if (!Entry) {
4151
+ return false;
4152
+ }
1429
4153
  try {
1430
4154
  const entry = new Entry(SERVICE, account ?? DEFAULT_ACCOUNT);
1431
4155
  return entry.deletePassword();
@@ -1514,7 +4238,6 @@ function extraFlags(ctx) {
1514
4238
  const flags = ctx.flags;
1515
4239
  return {
1516
4240
  since: flags.since,
1517
- groupBy: flags.groupBy,
1518
4241
  asin: flags.asin,
1519
4242
  fulfillmentChannel: flags.fulfillmentChannel
1520
4243
  };
@@ -1549,6 +4272,14 @@ function selectOutputValue2(result) {
1549
4272
  return text;
1550
4273
  }
1551
4274
  }
4275
+ function warnIfLimitTruncated2(ctx, value) {
4276
+ const limit = ctx.flags.limit;
4277
+ if (limit != null && Array.isArray(value) && value.length === limit) {
4278
+ ctx.err(
4279
+ `warning: result returned exactly --limit (${limit}) rows; output may be truncated. Raise --limit or narrow the query.`
4280
+ );
4281
+ }
4282
+ }
1552
4283
  async function emit(ctx, name, args) {
1553
4284
  const client = await ctx.getClient();
1554
4285
  const response = await client.rpc(
@@ -1565,6 +4296,7 @@ async function emit(ctx, name, args) {
1565
4296
  return classified.code;
1566
4297
  }
1567
4298
  const value = selectOutputValue2(result);
4299
+ warnIfLimitTruncated2(ctx, value);
1568
4300
  const rendered = formatOutput(value, ctx.flags.format);
1569
4301
  if (ctx.flags.output) {
1570
4302
  await writeFile2(ctx.flags.output, rendered, { encoding: "utf8", mode: 384 });
@@ -1844,9 +4576,9 @@ async function run(argv) {
1844
4576
  withGlobalOptions(cli.command("inventory health", "summarize inventory health")).action(
1845
4577
  (options) => dispatch((ctx) => inventoryHealth(ctx), options)
1846
4578
  );
1847
- withGlobalOptions(cli.command("ads performance", "summarize campaign performance")).option("--since <dur>", "lookback window: a relative duration like 30d or a YYYY-MM-DD date").option("--group-by <field>", "advisory grain hint (documented; not wired server-side)").action(
4579
+ withGlobalOptions(cli.command("ads performance", "summarize campaign performance")).option("--since <dur>", "lookback window: a relative duration like 30d or a YYYY-MM-DD date").action(
1848
4580
  (options) => dispatch((ctx) => adsPerformance(ctx), options, {
1849
- extra: { since: asString(options.since), groupBy: asString(options.groupBy) }
4581
+ extra: { since: asString(options.since) }
1850
4582
  })
1851
4583
  );
1852
4584
  withGlobalOptions(cli.command("catalog quality", "summarize listing quality")).option("--asin <asin>", "scope to a single ASIN").action(