@bowmark/web 1.6.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,9 +5,9 @@
5
5
  // rather than imported. An `import` or `export` at the top level of this file would
6
6
  // turn it into a module and every declaration below would stop being global.
7
7
  //
8
- // Manifest version: 5426792a92faf41fd663aa77ef068ec2f38bcc28d33426a6a565458c7a3b4c42
9
- // 8 capabilities, 95 providers, 316 typed functions, 20 refused.
10
- // 51,713 family members, sharing 2 interface(s) — declared once and pointed at, never repeated per member.
8
+ // Manifest version: b71c060db620c119ab92eac724aab2d9670d3d22f342f754075e353929634db2
9
+ // 9 capabilities, 121 providers, 380 typed functions, 20 refused.
10
+ // 51,715 family members, sharing 2 interface(s) — declared once and pointed at, never repeated per member.
11
11
  //
12
12
  // REFUSED — these functions are real and callable, and their declared arguments
13
13
  // carry no types, so no honest signature exists. Each one is commented in place
@@ -861,6 +861,126 @@ type ReadResult = {
861
861
  }
862
862
  }
863
863
 
864
+ declare namespace BowmarkCapability_sheds {
865
+ // ── Sheds and portable buildings (configure and price) — the unit's own declarations, verbatim ──
866
+ type ShedSize = {
867
+ sizeKey: string // the maker's own key; opaque, meaningful only to source
868
+ widthFt: number // FEET, always — the maker's own units are converted away
869
+ lengthFt: number
870
+ }
871
+ type ShedStyle = {
872
+ source: string // which maker — a provider id
873
+ brand: string // the maker's brand name, for an answer that names who builds it
874
+ key: string // the maker's own style key
875
+ label: string // the style as a customer sees it ("Lofted Barn")
876
+ sidingOptions: string[] // siding keys; the first is the maker's standard
877
+ sizes: ShedSize[]
878
+ imageUrl: string | null // a real product image from the maker's own catalogue
879
+ roofStyle: string | null // "gable", "gambrel", ...
880
+ roofing: string | null // "metal", ...
881
+ wallHeight: string | null // the maker's own spec, verbatim, e.g. "left-78-right-78-eave-72"
882
+ }
883
+ type ShedStylesResult = {
884
+ styles: ShedStyle[]
885
+ warnings: string[] // always present; a maker named here returned NOTHING
886
+ }
887
+
888
+ type ShedQuoteRequest = {
889
+ widthFt: number // in feet, as a person says it — "a 12 by 20"
890
+ lengthFt: number
891
+ zip: string // required; every maker prices regionally
892
+ style?: string // style key OR its customer-facing name, matched loosely.
893
+ // Omit to price EVERY style that builds the size
894
+ siding?: string // omit for the maker's standard siding
895
+ }
896
+ type ShedQuote = {
897
+ source: string
898
+ brand: string
899
+ styleKey: string
900
+ style: string // "Lofted Barn"
901
+ model: string | null // the maker's model name, where it has one
902
+ widthFt: number
903
+ lengthFt: number
904
+ siding: string // the siding key this was priced in
905
+ zip: string
906
+ region: string // the maker's own pricing region that zip fell under
907
+ basePrice: number
908
+ sidingSurcharge: number // what the siding added, by the maker's rules; 0 for standard
909
+ total: number // basePrice + sidingSurcharge, the maker's own arithmetic
910
+ currency: string
911
+ imageUrl: string | null // what the building looks like, from the maker's catalogue
912
+ roofStyle: string | null // "gable", "gambrel", ...
913
+ roofing: string | null // "metal", ...
914
+ wallHeight: string | null // the maker's own spec, verbatim
915
+ orderUrl: string // where to go order THIS build, always present
916
+ }
917
+ type ShedQuoteResult = {
918
+ quotes: ShedQuote[] // cheapest first, across every maker that builds the size
919
+ warnings: string[] // always present; names a dropped maker, a style that does
920
+ // not build the size, and a capped fan
921
+ }
922
+
923
+ type ShedDealer = {
924
+ source: string
925
+ brand: string
926
+ name: string
927
+ city: string
928
+ state: string
929
+ zip: string
930
+ phone: string | null // null when the directory lists none (never "")
931
+ url: string
932
+ }
933
+ type ShedDealerResult = {
934
+ dealers: ShedDealer[]
935
+ warnings: string[]
936
+ }
937
+
938
+ type CallOptions = {
939
+ timeoutMs?: number // per-provider budget in ms, default 30000, clamped to 1000-55000.
940
+ // A provider slower than this is DROPPED from the results and
941
+ // NAMED in warnings — never silently absent
942
+ }
943
+
944
+ /**
945
+ * Price a portable building the way its maker's own 3D configurator does — give a size in feet
946
+ * and a zip and get the real regional price for every style that builds it, the exact siding
947
+ * surcharge rather than a guessed range, a real product image and spec for each one, and the
948
+ * link to go order it. Plus the maker's real dealer locations by state.
949
+ */
950
+ interface Unit {
951
+ /**
952
+ * Prices a building at a real size for a real zip, exactly the way the maker's own
953
+ * configurator does — the regional base price plus the EXACT siding surcharge its rules apply
954
+ * at that width and region, never a national range or a guessed upcharge. Sizes are in FEET ({
955
+ * widthFt: 12, lengthFt: 20 }), and both orientations count. Omit `style` to price every style
956
+ * that builds the size, cheapest first; name it loosely ("lofted barn") when you want one.
957
+ * `zip` is required because every maker prices regionally. Each quote DESCRIBES the building
958
+ * as well as costing it — a real product image, the roof line and roofing material, the
959
+ * maker's own wall-height spec — and carries `orderUrl`, their own page to go order that
960
+ * build. `warnings` is always present and names a maker that failed, styles that do not build
961
+ * the size, and a capped fan. `options.timeoutMs` sets the per-maker budget (default 30000).
962
+ */
963
+ quote(request: ShedQuoteRequest, options?: CallOptions): Promise<ShedQuoteResult>;
964
+
965
+ /**
966
+ * Lists every building style each maker actually offers — its customer-facing name, the siding
967
+ * it can be built in, every real buildable size in FEET, and what the building IS (a real
968
+ * product image, the roof line and roofing material, the maker's own wall-height spec). Use it
969
+ * to see what exists before pricing, or to answer "what sizes do they even make". `warnings`
970
+ * names any maker that returned nothing, which is not the same as a maker with no styles.
971
+ */
972
+ listStyles(options?: CallOptions): Promise<ShedStylesResult>;
973
+
974
+ /**
975
+ * Looks up the real places that sell a maker's buildings in one US state or Canadian province
976
+ * — full name ("Tennessee") or abbreviation ("TN") — with name, city, phone and the dealer's
977
+ * own page, for handing a priced configuration to somebody who can actually build it. `phone`
978
+ * is null when the directory lists none, never an empty string.
979
+ */
980
+ findDealers(state: string, options?: CallOptions): Promise<ShedDealerResult>;
981
+ }
982
+ }
983
+
864
984
  declare namespace BowmarkProvider_aa {
865
985
  // ── American Airlines — the unit's own declarations, verbatim ──
866
986
  interface aaFlight {
@@ -1318,6 +1438,94 @@ interface abercrombieStockQuery {
1318
1438
  }
1319
1439
  }
1320
1440
 
1441
+ declare namespace BowmarkProvider_aiper {
1442
+ // ── Aiper — the unit's own declarations, verbatim ──
1443
+ interface AiperPoolOption {
1444
+ id: string;
1445
+ label: string;
1446
+ }
1447
+ interface AiperPoolQuestion {
1448
+ id: string;
1449
+ problemName: string;
1450
+ multiSelect: boolean;
1451
+ options: AiperPoolOption[];
1452
+ }
1453
+ interface AiperPoolAnswerInput {
1454
+ question: string;
1455
+ choice: string | string[];
1456
+ }
1457
+ interface AiperRecommendedProduct {
1458
+ productId: string;
1459
+ slug: string;
1460
+ name: string;
1461
+ sku: string;
1462
+ price: number;
1463
+ regularPrice: number;
1464
+ url: string;
1465
+ image: string | null;
1466
+ }
1467
+ interface AiperPoolRecommendation {
1468
+ products: AiperRecommendedProduct[];
1469
+ answers: AiperPoolAnswerInput[];
1470
+ warnings: string[];
1471
+ }
1472
+
1473
+ /**
1474
+ * Aiper's Help Me Choose robotic-pool-cleaner finder, run for real — the quiz's own computed
1475
+ * recommendation (model, SKU, real current price, PDP link) for a buyer's pool answers, off
1476
+ * the site's own undocumented API.
1477
+ */
1478
+ interface Unit {
1479
+ /**
1480
+ * Reads the Help Me Choose quiz's live question list — every question in order, with its
1481
+ * option ids and labels. The entry point: recommendPoolCleaner takes answers keyed off these
1482
+ * labels, so a caller normally reads this first (or already knows the labels from a prior
1483
+ * call).
1484
+ */
1485
+ listPoolChooserQuestions(): Promise<AiperPoolQuestion[]>;
1486
+
1487
+ /**
1488
+ * Runs the Help Me Choose quiz's real backend computation for a buyer's answers (given as
1489
+ * question/choice LABELS, matched case-insensitively against listPoolChooserQuestions) and
1490
+ * returns the same computed recommendation the quiz's own terminal page renders: model name,
1491
+ * SKU, real current price, list price, and a PDP URL. THROWS if a question or choice label
1492
+ * doesn't match, or if the site's computed result carries no product list.
1493
+ */
1494
+ recommendPoolCleaner(answers: AiperPoolAnswerInput[]): Promise<AiperPoolRecommendation>;
1495
+ }
1496
+ }
1497
+
1498
+ declare namespace BowmarkProvider_ajmadison {
1499
+ // ── AJ Madison — the unit's own declarations, verbatim ──
1500
+ interface AjmadisonSearchArgs {
1501
+ category: string; // the site's own category slug, e.g. "refrigerators"
1502
+ filters?: Record<string, string>; // the site's own facet query params, verbatim
1503
+ limit?: number; // default 25, clamped to [1, 60]
1504
+ }
1505
+
1506
+ interface AjmadisonSearchResult {
1507
+ sku: string;
1508
+ name: string;
1509
+ price: number; // real, current selling price
1510
+ wasPrice: number | null; // the crossed-out "was" price, when shown
1511
+ url: string; // this product's own AJ Madison URL
1512
+ }
1513
+
1514
+ /**
1515
+ * AJ Madison's real appliance catalog — search runs the site's own category + facet filter
1516
+ * (brand, size/capacity, price band, style, availability) and returns real, currently-listed
1517
+ * products with their live selling price and the product's own AJ Madison URL.
1518
+ */
1519
+ interface Unit {
1520
+ /**
1521
+ * Runs AJ Madison's own category + facet filter and returns real, currently-listed products
1522
+ * (name, real current price, the crossed-out 'was' price when shown, the product's own AJ
1523
+ * Madison URL). Read-only — never adds to cart or checks out.
1524
+ */
1525
+ search(args: AjmadisonSearchArgs): Promise<AjmadisonSearchResult[]>;
1526
+ }
1527
+ }
1528
+
1321
1529
  declare namespace BowmarkProvider_ashleyfurniture {
1322
1530
  // ── Ashley Furniture — the unit's own declarations, verbatim ──
1323
1531
  interface AshleyFurnitureSearchArgs {
@@ -1438,6 +1646,47 @@ interface AshleyFurnitureStore {
1438
1646
  }
1439
1647
  }
1440
1648
 
1649
+ declare namespace BowmarkProvider_atlasseniorliving {
1650
+ // ── Atlas Senior Living — the unit's own declarations, verbatim ──
1651
+ type AtlasCareType = "assisted_living" | "independent_living" | "memory_care" | "respite_care";
1652
+
1653
+ interface AtlasCommunity {
1654
+ id: string;
1655
+ name: string;
1656
+ address: string;
1657
+ city: string;
1658
+ state: string;
1659
+ zip: string;
1660
+ phone: string;
1661
+ distanceMiles: number;
1662
+ lat: number;
1663
+ lng: number;
1664
+ url: string;
1665
+ }
1666
+
1667
+ interface AtlasSearchCommunitiesResult {
1668
+ location: string;
1669
+ geocodedLat: number;
1670
+ geocodedLng: number;
1671
+ careTypes: AtlasCareType[];
1672
+ radiusMiles: number;
1673
+ communities: AtlasCommunity[];
1674
+ }
1675
+
1676
+ /**
1677
+ * Atlas Senior Living's own community search (atlasseniorliving.com/our-communities/) — given
1678
+ * a US city/state or ZIP, plus optional care type(s) and radius, returns the real,
1679
+ * distance-sorted set of matching Atlas communities.
1680
+ */
1681
+ interface Unit {
1682
+ /**
1683
+ * Runs the site's own community search: a US location + optional care type(s) and radius,
1684
+ * returns the real, distance-sorted matching Atlas communities.
1685
+ */
1686
+ searchCommunities(arg: { location: string, careTypes?: AtlasCareType[], radiusMiles?: number, maxResults?: number }): Promise<AtlasSearchCommunitiesResult>;
1687
+ }
1688
+ }
1689
+
1441
1690
  declare namespace BowmarkProvider_avis {
1442
1691
  // ── Avis — the unit's own declarations, verbatim ──
1443
1692
  interface avisRow {
@@ -1780,6 +2029,58 @@ interface StoreStock {
1780
2029
  }
1781
2030
  }
1782
2031
 
2032
+ declare namespace BowmarkProvider_bigrentz {
2033
+ // ── BigRentz — the unit's own declarations, verbatim ──
2034
+ interface BigrentzEquipmentRow {
2035
+ id: number;
2036
+ name: string;
2037
+ slug: string;
2038
+ permalink: string;
2039
+ categories: { id: number; name: string; slug: string }[];
2040
+ images: { src: string; alt: string }[];
2041
+ inStock: boolean;
2042
+ priced: false;
2043
+ priceNote: string;
2044
+ }
2045
+ interface BigrentzEquipmentDetail extends BigrentzEquipmentRow {
2046
+ description: string;
2047
+ specSheetUrls: string[];
2048
+ }
2049
+ interface BigrentzCategoryRow {
2050
+ id: number;
2051
+ name: string;
2052
+ slug: string;
2053
+ count: number;
2054
+ permalink: string;
2055
+ }
2056
+
2057
+ /**
2058
+ * BigRentz's own equipment catalog — search, category browse and per-item detail, real data
2059
+ * from their WooCommerce Store API. Live rental pricing is not yet built (site gates it behind
2060
+ * a location + date picker); see getRentalPricing.
2061
+ */
2062
+ interface Unit {
2063
+ /**
2064
+ * Searches BigRentz's equipment catalog by free text (e.g. "boom lift", "40 ft boom lift") and
2065
+ * returns matching rows. Real catalog data — id, name, slug, permalink, category, stock flag,
2066
+ * images — but NOT a real price (see `priceNote` on each row).
2067
+ */
2068
+ search(query: string): Promise<BigrentzEquipmentRow[]>;
2069
+
2070
+ /**
2071
+ * Reads one piece of equipment in full by the slug `search` or `listCategories` returned —
2072
+ * description, spec-sheet PDF links, category and stock flag.
2073
+ */
2074
+ getEquipment(slug: string): Promise<BigrentzEquipmentDetail>;
2075
+
2076
+ /**
2077
+ * Lists BigRentz's equipment categories — id, name, slug, live listing count, category page
2078
+ * URL. Pass `parentSlug` to list a category's children.
2079
+ */
2080
+ listCategories(options?: { parentSlug?: string }): Promise<BigrentzCategoryRow[]>;
2081
+ }
2082
+ }
2083
+
1783
2084
  declare namespace BowmarkProvider_blenderseyewear {
1784
2085
  // ── Blenders Eyewear — the unit's own declarations, verbatim ──
1785
2086
  // Blenders Eyewear's OWN shapes — not a capability contract.
@@ -2103,6 +2404,62 @@ interface BmwusaModelListing {
2103
2404
  }
2104
2405
  }
2105
2406
 
2407
+ declare namespace BowmarkProvider_boydsleep {
2408
+ // ── Boyd Sleep — the unit's own declarations, verbatim ──
2409
+ // Boyd Sleep's OWN shapes — not a capability contract.
2410
+
2411
+ type BoydsleepGender = "Male" | "Female" | "Non Binary";
2412
+ type BoydsleepSleepPosition = "Side" | "Back" | "Stomach" | "Multi";
2413
+
2414
+ interface BoydsleepCalibrationInput {
2415
+ gender: BoydsleepGender;
2416
+ heightInches: number; // snapped to the site's own height band
2417
+ weightLbs: number; // snapped to the site's own weight band
2418
+ sleepPosition: BoydsleepSleepPosition;
2419
+ }
2420
+
2421
+ interface Boydsleep2ZoneResult {
2422
+ supportIndex: number; // 0-100
2423
+ heightBandInches: number;
2424
+ weightBandLbs: number;
2425
+ setupGuideUrl: string; // the real next step — no checkout exists on this domain
2426
+ calibratorUrl: string;
2427
+ }
2428
+
2429
+ interface Boydsleep6ZoneResult {
2430
+ headFoot: number;
2431
+ center: number;
2432
+ heightBandInches: number;
2433
+ weightBandLbs: number;
2434
+ setupGuideUrl: string;
2435
+ calibratorUrl: string;
2436
+ }
2437
+
2438
+ /**
2439
+ * Boyd Sleep's own 'Smart Support Number' calibrator for a Nautica Home Smart Zone air bed —
2440
+ * the real personalized 0-100 Support Index (2-zone) or Head/Foot + Center numbers (6-zone),
2441
+ * computed exactly as the site computes them, plus the site's own setup guide as the real next
2442
+ * step (Boyd sells through retail/franchise partners, so there is no DTC checkout on this
2443
+ * domain to route to).
2444
+ */
2445
+ interface Unit {
2446
+ /**
2447
+ * Runs Boyd's own 2-zone Smart Support Number calculation for a Nautica Home Smart Zone air
2448
+ * bed — a real, personalized 0-100 Support Index computed exactly as the site's own calculator
2449
+ * computes it, no estimate. `setupGuideUrl` is the real next step; Boyd sells through
2450
+ * retail/franchise partners, so there is no cart to route to on this domain.
2451
+ */
2452
+ calibrateSupportNumber(input: BoydsleepCalibrationInput): Promise<Boydsleep2ZoneResult>;
2453
+
2454
+ /**
2455
+ * Runs Boyd's own 6-zone Smart Support Number calculation — same inputs as the 2-zone tool,
2456
+ * returns a separate Head/Foot number and a Center (lumbar) number for the 6-zone Nautica Home
2457
+ * Smart Zone bed.
2458
+ */
2459
+ calibrateSixZoneSupportNumber(input: BoydsleepCalibrationInput): Promise<Boydsleep6ZoneResult>;
2460
+ }
2461
+ }
2462
+
2106
2463
  declare namespace BowmarkProvider_bykoket {
2107
2464
  // ── KOKET — the unit's own declarations, verbatim ──
2108
2465
  interface KoketProductSummary {
@@ -2711,6 +3068,75 @@ interface ChriscraftPriceResult {
2711
3068
  }
2712
3069
  }
2713
3070
 
3071
+ declare namespace BowmarkProvider_classichome {
3072
+ // ── Classic Home — the unit's own declarations, verbatim ──
3073
+ // Classic Home's OWN shapes — not a capability contract.
3074
+
3075
+ interface ClassicHomeProduct {
3076
+ handle: string; // the key getProduct/addToCart take
3077
+ title: string;
3078
+ url: string;
3079
+ priceMin: number; // dollars — the cheapest real fabric/leather choice
3080
+ priceMax: number; // dollars — the most expensive (usually top-grain leather)
3081
+ variantCount: number; // >1 means a real fabric/leather choice exists
3082
+ }
3083
+
3084
+ interface ClassicHomeVariant {
3085
+ optionValue: string; // e.g. "Soft Olive", "Dawn-Flax", "ElPaso-Saddle"
3086
+ sku: string;
3087
+ price: number; // dollars — this exact fabric/leather's own real price
3088
+ available: boolean;
3089
+ }
3090
+
3091
+ interface ClassicHomeProductDetail {
3092
+ handle: string;
3093
+ title: string;
3094
+ url: string;
3095
+ optionName: string; // usually "Color" (fabric/leather); "Title" if no real picker
3096
+ variants: ClassicHomeVariant[];
3097
+ }
3098
+
3099
+ interface ClassicHomeCartHandoff {
3100
+ handle: string;
3101
+ optionValue: string;
3102
+ sku: string;
3103
+ price: number; // dollars — the real price for this exact fabric/leather
3104
+ available: boolean;
3105
+ productUrl: string; // finish add-to-cart/checkout on the real product page
3106
+ }
3107
+
3108
+ /**
3109
+ * Classic Home's real Made-to-Order fabric/leather catalog and its real, material-specific
3110
+ * Shopify pricing — search real MTO products (sofas, chairs, ottomans), read one product's
3111
+ * real fabric/leather picker, and resolve one exact fabric or leather choice to its real SKU,
3112
+ * price and availability.
3113
+ */
3114
+ interface Unit {
3115
+ /**
3116
+ * Searches Classic Home's real Made-to-Order catalog (sofas, chairs, ottomans) via the site's
3117
+ * own Shopify collection JSON, optionally filtered by a free-text query against the product
3118
+ * title. Returns real products with a real price range read off their own fabric/leather
3119
+ * variants.
3120
+ */
3121
+ searchProducts(query?: string): Promise<ClassicHomeProduct[]>;
3122
+
3123
+ /**
3124
+ * Reads one product's real live fabric/leather picker: every real color/material choice with
3125
+ * its own real price and availability, keyed by the site's own option name. THROWS on an
3126
+ * unknown handle, naming searchProducts() as the way to find current ones.
3127
+ */
3128
+ getProduct(handle: string): Promise<ClassicHomeProductDetail>;
3129
+
3130
+ /**
3131
+ * Resolves ONE exact fabric/leather choice (optionValue from getProduct's own variant list,
3132
+ * e.g. "Soft Olive") to Classic Home's own real price, availability and SKU, plus the product
3133
+ * page to finish add-to-cart/checkout on the site itself. Writes nothing — classichome.com's
3134
+ * robots.txt disallows automated /cart access.
3135
+ */
3136
+ addToCart(handle: string, optionValue: string): Promise<ClassicHomeCartHandoff>;
3137
+ }
3138
+ }
3139
+
2714
3140
  declare namespace BowmarkProvider_classpass {
2715
3141
  // ── ClassPass — the unit's own declarations, verbatim ──
2716
3142
  /** Everything /v2/venues publishes about one studio — a superset of
@@ -3686,6 +4112,36 @@ interface DiscounttireTireSizeSearch {
3686
4112
  }
3687
4113
  }
3688
4114
 
4115
+ declare namespace BowmarkProvider_embroker {
4116
+ // ── Embroker — the unit's own declarations, verbatim ──
4117
+ interface EmbrokerCoverageCatalog {
4118
+ coverageLines: string[];
4119
+ productTypes: string[];
4120
+ }
4121
+
4122
+ interface EmbrokerQuoteEntryPoint {
4123
+ product: string;
4124
+ productLabel: string;
4125
+ url: string;
4126
+ reachable: boolean;
4127
+ }
4128
+
4129
+ /**
4130
+ * Embroker's own coverage catalog and live self-serve quote-wizard entry points for
4131
+ * tech/startup, law firm, cyber, BOP, crime and professional-liability business insurance.
4132
+ */
4133
+ interface Unit {
4134
+ /** Returns Embroker's real coverage-line and policy-product-type catalog. */
4135
+ listCoverageLines(): Promise<EmbrokerCoverageCatalog>;
4136
+
4137
+ /**
4138
+ * Returns the live, confirmed-reachable entry URL for one of Embroker's self-serve
4139
+ * quote-wizard products.
4140
+ */
4141
+ getQuoteEntryPoint(args: { product: string }): Promise<EmbrokerQuoteEntryPoint>;
4142
+ }
4143
+ }
4144
+
3689
4145
  declare namespace BowmarkProvider_erieinsurance {
3690
4146
  // ── ERIE Insurance — the unit's own declarations, verbatim ──
3691
4147
  interface ErieAgentQuery {
@@ -3774,6 +4230,64 @@ interface ErieAgent {
3774
4230
  }
3775
4231
  }
3776
4232
 
4233
+ declare namespace BowmarkProvider_eventsource {
4234
+ // ── Event Source — the unit's own declarations, verbatim ──
4235
+ interface EventSourceDesign {
4236
+ designId: number;
4237
+ visionBoardId: number;
4238
+ roomId: number;
4239
+ designName: string;
4240
+ roomName: string;
4241
+ venueName: string;
4242
+ hasLayouts: boolean;
4243
+ hasTemplates: boolean;
4244
+ }
4245
+ interface EventSourceShowroom {
4246
+ accessCode: string;
4247
+ showroomName: string;
4248
+ ownerName: string;
4249
+ branded: boolean;
4250
+ underConstruction: boolean;
4251
+ logoUrl: string;
4252
+ eventId: number;
4253
+ venueIds: number[];
4254
+ designs: EventSourceDesign[];
4255
+ }
4256
+ interface EventSourceVenue {
4257
+ venueId: number;
4258
+ businessName: string;
4259
+ city: string;
4260
+ state: string;
4261
+ zipCode: string;
4262
+ market: string;
4263
+ primaryImageUrl: string;
4264
+ rooms: Array<{ roomId: number; roomName: string; primaryImageUrl: string; active: boolean }>;
4265
+ }
4266
+ interface EventSourceInquiryContact {
4267
+ inquiryRequestEmail: string;
4268
+ ownerName: string;
4269
+ ownerLogoUrl: string;
4270
+ }
4271
+
4272
+ /**
4273
+ * Reads a public Event Source Virtual Design Center showroom (design, venue, inquiry contact)
4274
+ * by its access code — no login.
4275
+ */
4276
+ interface Unit {
4277
+ /**
4278
+ * Reads a public Virtual Design Center showroom by its access code — its design(s), venue and
4279
+ * branding.
4280
+ */
4281
+ getShowroom(code: string): Promise<EventSourceShowroom>;
4282
+
4283
+ /** Reads the real venue/room a showroom's design is staged in. */
4284
+ getShowroomVenue(eventId: number, venueId: number, code: string): Promise<EventSourceVenue>;
4285
+
4286
+ /** Reads who a showroom's Send Inquiry button emails, without submitting anything. */
4287
+ getShowroomInquiryContact(code: string): Promise<EventSourceInquiryContact>;
4288
+ }
4289
+ }
4290
+
3777
4291
  declare namespace BowmarkProvider_extraspace {
3778
4292
  // ── Extra Space Storage — the unit's own declarations, verbatim ──
3779
4293
  interface ExtraspaceSearchResult {
@@ -5113,6 +5627,53 @@ interface GooglePriceGraph {
5113
5627
  }
5114
5628
  }
5115
5629
 
5630
+ declare namespace BowmarkProvider_gotchacovered {
5631
+ // ── Gotcha Covered — the unit's own declarations, verbatim ──
5632
+ interface GotchaCoveredQuizOption {
5633
+ label: string;
5634
+ imageUrl: string | null;
5635
+ }
5636
+ interface GotchaCoveredQuizQuestion {
5637
+ step: number;
5638
+ prompt: string;
5639
+ options: GotchaCoveredQuizOption[];
5640
+ }
5641
+ interface GotchaCoveredQuizQuestions {
5642
+ questions: GotchaCoveredQuizQuestion[];
5643
+ }
5644
+ interface GotchaCoveredQuizAnswers {
5645
+ colorScheme: string;
5646
+ pattern: string;
5647
+ imageChoice: number | string;
5648
+ destination: string;
5649
+ material: string;
5650
+ item: string;
5651
+ }
5652
+ interface GotchaCoveredQuizResult {
5653
+ styleName: string;
5654
+ description: string;
5655
+ recommendedProducts: string | null;
5656
+ url: string;
5657
+ }
5658
+
5659
+ /**
5660
+ * Reads and answers Gotcha Covered's own 'What Design Style Am I?' window-treatment style
5661
+ * quiz, returning the site's real computed match.
5662
+ */
5663
+ interface Unit {
5664
+ /** Reads the live 'What Design Style Am I?' quiz's real 6 questions and option lists. */
5665
+ getDesignStyleQuizQuestions(): Promise<GotchaCoveredQuizQuestions>;
5666
+
5667
+ /**
5668
+ * Answers all 6 questions of Gotcha Covered's Design Style Quiz (e.g. { colorScheme:
5669
+ * "Metallics Color Scheme", pattern: "Eclectic Pattern", imageChoice: 1, destination: "Spain
5670
+ * Destination", material: "Wood Material", item: "Graphic Rug Item" }) and returns the site's
5671
+ * real computed style match.
5672
+ */
5673
+ takeDesignStyleQuiz(answers: GotchaCoveredQuizAnswers): Promise<GotchaCoveredQuizResult>;
5674
+ }
5675
+ }
5676
+
5116
5677
  declare namespace BowmarkProvider_grainger {
5117
5678
  // ── Grainger — the unit's own declarations, verbatim ──
5118
5679
  interface graingerRow {
@@ -5219,6 +5780,198 @@ interface graingerStockRow {
5219
5780
  }
5220
5781
  }
5221
5782
 
5783
+ declare namespace BowmarkProvider_grandwelcome {
5784
+ // ── Grand Welcome — the unit's own declarations, verbatim ──
5785
+ interface GrandwelcomeRentalRow {
5786
+ rentalId: string;
5787
+ name: string;
5788
+ url: string;
5789
+ location: string;
5790
+ propertyType: string;
5791
+ petFriendly: boolean;
5792
+ priceFromUsd: number | null;
5793
+ priceFromFormatted: string | null;
5794
+ bedrooms: number | null;
5795
+ bathrooms: number | null;
5796
+ guests: number | null;
5797
+ ratingValue: number | null;
5798
+ ratingCount: number | null;
5799
+ }
5800
+ interface GrandwelcomeRentalDetail {
5801
+ rentalId: string;
5802
+ propertyId: string;
5803
+ name: string;
5804
+ description: string;
5805
+ images: string[];
5806
+ url: string;
5807
+ }
5808
+ interface GrandwelcomeQuoteFee {
5809
+ label: string;
5810
+ amountUsd: number;
5811
+ }
5812
+ type GrandwelcomeQuote =
5813
+ | { available: true; propertyId: string; checkin: string; checkout: string; currency: "USD";
5814
+ rentUsd: number; fees: GrandwelcomeQuoteFee[]; feesTotalUsd: number; taxUsd: number;
5815
+ totalUsd: number; bookNowUrl: string }
5816
+ | { available: false; propertyId: string; checkin: string; checkout: string };
5817
+
5818
+ /**
5819
+ * Grand Welcome's own vacation rental search, listing detail, and real-time dated
5820
+ * pricing/booking-link engine — a national franchise's own inventory, live availability and
5821
+ * price, not a stale catalog.
5822
+ */
5823
+ interface Unit {
5824
+ /**
5825
+ * Runs Grand Welcome's own destination search (a market slug like "california-sea-ranch", from
5826
+ * a rental's own page or the destination directory), optionally filtered to a bedroom count,
5827
+ * and returns the live matching listings — name, url, location, type, pet-friendly flag,
5828
+ * advertised "as low as" price, bed/bath/guest counts, rating.
5829
+ */
5830
+ searchRentals(destinationSlug: string, options?: { bedrooms?: number }): Promise<GrandwelcomeRentalRow[]>;
5831
+
5832
+ /**
5833
+ * Reads one rental in full — name, description, photos, and the internal numeric propertyId
5834
+ * getRentalQuote needs — from the rentalId a search result or a grandwelcome.com/rentals/<id>
5835
+ * URL carries.
5836
+ */
5837
+ getRentalDetail(rentalId: string): Promise<GrandwelcomeRentalDetail>;
5838
+
5839
+ /**
5840
+ * Runs the site's own real-time pricing engine for one property and a date range
5841
+ * ("YYYY-MM-DD") — rent, fees, tax, total — and returns the exact Book Now checkout URL for
5842
+ * those dates. `available: false` means the site checked and the property is not free for
5843
+ * those dates, an ordinary answer.
5844
+ */
5845
+ getRentalQuote(propertyId: string, options: { checkin: string; checkout: string }): Promise<GrandwelcomeQuote>;
5846
+ }
5847
+ }
5848
+
5849
+ declare namespace BowmarkProvider_handypro {
5850
+ // ── HandyPro — the unit's own declarations, verbatim ──
5851
+ // HandyPro's OWN shapes — not a capability contract.
5852
+
5853
+ interface HandyproHourlyRate { fromHours: number; toHours: number; pricePerHour: number }
5854
+
5855
+ interface HandyproServiceArea {
5856
+ covered: boolean;
5857
+ message?: string; // present only when covered is false
5858
+ franchiseeName?: string;
5859
+ phone?: string;
5860
+ city?: string;
5861
+ state?: string;
5862
+ formattedAddress?: string;
5863
+ hourlyRates?: HandyproHourlyRate[];
5864
+ }
5865
+
5866
+ interface HandyproCategoryPrice {
5867
+ categoryId: string;
5868
+ categoryName: string;
5869
+ parentCategoryName: string;
5870
+ pricingKind: "estimate" | "fixedJob" | "unpriced";
5871
+ price: number | null; // dollars
5872
+ whatsIncluded: string;
5873
+ }
5874
+
5875
+ interface HandyproCategorySearch {
5876
+ zipcode: string;
5877
+ covered: boolean;
5878
+ message?: string; // present only when covered is false
5879
+ categories: HandyproCategoryPrice[];
5880
+ }
5881
+
5882
+ /**
5883
+ * HandyPro's real service-area coverage and per-category job pricing — checks whether a ZIP is
5884
+ * served by a real local franchisee (with its own live hourly rate table) and prices
5885
+ * HandyPro's actual handyman/home-modification categories (grab bars, appliance install, TV
5886
+ * mounting, painting, and more) for that ZIP, rather than a researched nationwide estimate.
5887
+ */
5888
+ interface Unit {
5889
+ /**
5890
+ * Checks whether a ZIP is served by a real local HandyPro franchisee and returns that
5891
+ * franchisee's own real hourly rate table. covered is false with a message for a ZIP outside
5892
+ * HandyPro's online booking area — an honest, ordinary answer, not an error.
5893
+ */
5894
+ checkServiceArea(zipcode: string): Promise<HandyproServiceArea>;
5895
+
5896
+ /**
5897
+ * Lists HandyPro's real service categories priced for one ZIP's franchisee (a free estimate or
5898
+ * a real fixed job price, and what's included), optionally narrowed by a free-text query (e.g.
5899
+ * "grab bar"). covered is false with a message for a ZIP outside the service area.
5900
+ */
5901
+ searchServiceCategories(zipcode: string, query?: string): Promise<HandyproCategorySearch>;
5902
+ }
5903
+ }
5904
+
5905
+ declare namespace BowmarkProvider_harmar {
5906
+ // ── Harmar Mobility — the unit's own declarations, verbatim ──
5907
+ interface HarmarVehicleModel {
5908
+ make: string;
5909
+ modelId: string;
5910
+ model: string;
5911
+ }
5912
+
5913
+ interface HarmarChairModel {
5914
+ chairId: string;
5915
+ model: string;
5916
+ }
5917
+
5918
+ interface HarmarLiftOption {
5919
+ code: string;
5920
+ name: string;
5921
+ description: string;
5922
+ required: boolean;
5923
+ }
5924
+
5925
+ interface HarmarCompatibleLift {
5926
+ liftId: string;
5927
+ productCode: string;
5928
+ name: string;
5929
+ requiredAccessories: HarmarLiftOption[];
5930
+ optionalAccessories: HarmarLiftOption[];
5931
+ }
5932
+
5933
+ interface HarmarCompatibleLiftsResult {
5934
+ year: string;
5935
+ vehicleId: string;
5936
+ chairId: string;
5937
+ lifts: HarmarCompatibleLift[];
5938
+ }
5939
+
5940
+ interface HarmarFindCompatibleLiftsResult extends HarmarCompatibleLiftsResult {
5941
+ vehicleMake: string;
5942
+ vehicleModel: string;
5943
+ chairMake: string;
5944
+ chairModel: string;
5945
+ }
5946
+
5947
+ /**
5948
+ * Harmar's Vehicle Compatibility Calculator (calculator.harmar.com) — given a vehicle and a
5949
+ * wheelchair/scooter, returns the real Harmar vehicle lifts that fit that combination.
5950
+ */
5951
+ interface Unit {
5952
+ /**
5953
+ * Every vehicle (make + calculator's own model id) the compatibility calculator has data for
5954
+ * in a given model year.
5955
+ */
5956
+ searchVehicleModels(arg: { year: string }): Promise<HarmarVehicleModel[]>;
5957
+
5958
+ /** Every wheelchair/scooter model the calculator has data for under a given manufacturer make. */
5959
+ searchChairModels(arg: { make: string }): Promise<HarmarChairModel[]>;
5960
+
5961
+ /**
5962
+ * Runs the calculator's own 'Lift Lookup' against its internal vehicle/chair ids and returns
5963
+ * the compatible Harmar lifts.
5964
+ */
5965
+ getCompatibleLifts(arg: { year: string, vehicleId: string, chairId: string }): Promise<HarmarCompatibleLiftsResult>;
5966
+
5967
+ /**
5968
+ * The whole goal-flow in one call: plain vehicle year/make/model + chair make/model, resolved
5969
+ * to the calculator's own ids and run through the real Lift Lookup.
5970
+ */
5971
+ findCompatibleLifts(arg: { year: string, vehicleMake: string, vehicleModel: string, chairMake: string, chairModel: string }): Promise<HarmarFindCompatibleLiftsResult>;
5972
+ }
5973
+ }
5974
+
5222
5975
  declare namespace BowmarkProvider_hauslabs {
5223
5976
  // ── Haus Labs by Lady Gaga — the unit's own declarations, verbatim ──
5224
5977
  interface HauslabsVariant {
@@ -5249,6 +6002,7 @@ interface HauslabsShadeMatch {
5249
6002
  variant: {
5250
6003
  number: number;
5251
6004
  family: string;
6005
+ id: string;
5252
6006
  sku: string | null;
5253
6007
  price: string;
5254
6008
  available: boolean;
@@ -6181,6 +6935,78 @@ interface hiltonRoomOffer {
6181
6935
  }
6182
6936
  }
6183
6937
 
6938
+ declare namespace BowmarkProvider_hobie {
6939
+ // ── Hobie Cat Company — the unit's own declarations, verbatim ──
6940
+ interface HobieModelSummary {
6941
+ slug: string;
6942
+ name: string;
6943
+ url: string;
6944
+ }
6945
+ interface HobieModelColor {
6946
+ color: string;
6947
+ upc: string;
6948
+ }
6949
+ interface HobieModelColors {
6950
+ slug: string;
6951
+ name: string;
6952
+ defaultColor: string;
6953
+ colors: HobieModelColor[];
6954
+ }
6955
+ interface HobieDealer {
6956
+ storeId: number;
6957
+ name: string;
6958
+ address: string;
6959
+ city: string;
6960
+ state: string;
6961
+ zip: string;
6962
+ phoneNumber: string;
6963
+ latitude: number;
6964
+ longitude: number;
6965
+ distanceMiles: number;
6966
+ carriesExactColor: boolean;
6967
+ carriesModel: boolean;
6968
+ carriesBrand: boolean;
6969
+ stockStatus: string;
6970
+ stockDisclaimer: string;
6971
+ }
6972
+ interface HobieLocalAvailability {
6973
+ slug: string;
6974
+ modelName: string;
6975
+ color: string;
6976
+ upc: string;
6977
+ zip: string;
6978
+ dealers: HobieDealer[];
6979
+ dealersCarryingExactColor: number;
6980
+ dealersCarryingModel: number;
6981
+ }
6982
+
6983
+ /**
6984
+ * Reads Hobie Cat Company's own real-time 'Find it Locally' dealer-inventory widget directly —
6985
+ * which real dealer near a zip has a specific kayak model, IN A SPECIFIC COLOR, in stock right
6986
+ * now. Kayaks are dealer-distribution only; there is no first-party checkout.
6987
+ */
6988
+ interface Unit {
6989
+ /**
6990
+ * Lists every real kayak model Hobie currently sells (slug, display name, its own hobie.com
6991
+ * URL), read straight from the live /kayaks/ index.
6992
+ */
6993
+ listModels(): Promise<HobieModelSummary[]>;
6994
+
6995
+ /**
6996
+ * Reads one model's real buildable colors, each paired with the exact UPC the local-inventory
6997
+ * widget is keyed on, plus the site's own default color.
6998
+ */
6999
+ listModelColors(slug: string): Promise<HobieModelColors>;
7000
+
7001
+ /**
7002
+ * Runs Hobie's own real-time 'Find it Locally' widget for one model + color near a US zip and
7003
+ * returns real nearby dealers with Hobie's own exact-color / model / brand carrying flags.
7004
+ * `color` defaults to the site's own default color when omitted.
7005
+ */
7006
+ checkLocalAvailability(slug: string, color: string | undefined, zip: string): Promise<HobieLocalAvailability>;
7007
+ }
7008
+ }
7009
+
6184
7010
  declare namespace BowmarkProvider_hunter {
6185
7011
  // ── Hunter — the unit's own declarations, verbatim ──
6186
7012
  interface hunterDomainCandidate {
@@ -7397,6 +8223,105 @@ interface InteriorDefineCartHandoff {
7397
8223
  }
7398
8224
  }
7399
8225
 
8226
+ declare namespace BowmarkProvider_islllc {
8227
+ // ── Integral Senior Living — the unit's own declarations, verbatim ──
8228
+ type IsllcCareType = "assisted_living" | "independent_living" | "memory_care" | "respite_care";
8229
+
8230
+ interface IsllcCommunity {
8231
+ id: string;
8232
+ name: string;
8233
+ address: string;
8234
+ city: string;
8235
+ state: string;
8236
+ zip: string;
8237
+ phone: string;
8238
+ careTypes: string;
8239
+ lat: number;
8240
+ lng: number;
8241
+ url: string;
8242
+ }
8243
+
8244
+ interface IsllcSearchCommunitiesResult {
8245
+ location: string;
8246
+ geocodedLat: number;
8247
+ geocodedLng: number;
8248
+ careTypes: IsllcCareType[];
8249
+ radiusMiles: number;
8250
+ communities: IsllcCommunity[];
8251
+ }
8252
+
8253
+ /**
8254
+ * Integral Senior Living's own community locator (islllc.com/communities/) — given a US
8255
+ * city/state or ZIP, plus optional care type(s) and radius, returns the real, nearest-first
8256
+ * set of matching ISL communities.
8257
+ */
8258
+ interface Unit {
8259
+ /**
8260
+ * Runs the site's own community locator: a US location + optional care type(s) and radius,
8261
+ * returns the real, nearest-first matching ISL communities.
8262
+ */
8263
+ searchCommunities(arg: { location: string, careTypes?: IsllcCareType[], radiusMiles?: number, maxResults?: number }): Promise<IsllcSearchCommunitiesResult>;
8264
+ }
8265
+ }
8266
+
8267
+ declare namespace BowmarkProvider_jennikayne {
8268
+ // ── Jenni Kayne — the unit's own declarations, verbatim ──
8269
+ interface GiftCardDenomination {
8270
+ variantId: string;
8271
+ amount: string;
8272
+ available: boolean;
8273
+ }
8274
+ interface GiftCardOptions {
8275
+ productUrl: string;
8276
+ denominations: GiftCardDenomination[];
8277
+ timezones: string[];
8278
+ }
8279
+ interface GiftCardConfig {
8280
+ amount: string;
8281
+ recipientName: string;
8282
+ recipientEmail: string;
8283
+ giftMessage?: string;
8284
+ deliveryDate: string;
8285
+ deliveryTimezone: string;
8286
+ }
8287
+ interface GiftCardLink {
8288
+ amount: string;
8289
+ variantId: string;
8290
+ recipientName: string;
8291
+ recipientEmail: string;
8292
+ giftMessage: string | null;
8293
+ deliveryDate: string;
8294
+ deliveryTimezone: string;
8295
+ available: boolean;
8296
+ cartUrl: string;
8297
+ checkoutUrl: string;
8298
+ deliveryTimeLeftToShopper: true;
8299
+ }
8300
+
8301
+ /**
8302
+ * Jenni Kayne's live gift-card product: read the real denominations and hand the shopper a
8303
+ * checkout link pre-filled with the recipient, message and scheduled delivery date/timezone.
8304
+ */
8305
+ interface Unit {
8306
+ /**
8307
+ * Reads the live Jenni Kayne digital gift-card product — every denomination from $50 to $1,000
8308
+ * with its real variant id and current stock, plus the exact timezone strings the checkout
8309
+ * form accepts. Call this first to know what buildGiftCardLink will accept.
8310
+ */
8311
+ getGiftCardOptions(): Promise<GiftCardOptions>;
8312
+
8313
+ /**
8314
+ * Configures a Jenni Kayne digital gift card — amount, recipient name/email, an optional
8315
+ * message, and a scheduled delivery date + timezone — and returns a checkout link with every
8316
+ * one of those fields already filled in, so the shopper only has to pick a delivery TIME and
8317
+ * pay. THROWS on an unknown amount, an invalid email, a malformed date, or a timezone the
8318
+ * store does not offer — call getGiftCardOptions first to see the live choices. Builds the
8319
+ * link only; nothing is purchased or charged here.
8320
+ */
8321
+ buildGiftCardLink(config: GiftCardConfig): Promise<GiftCardLink>;
8322
+ }
8323
+ }
8324
+
7400
8325
  declare namespace BowmarkProvider_joybird {
7401
8326
  // ── Joybird — the unit's own declarations, verbatim ──
7402
8327
  interface JoybirdConfigurator {
@@ -7633,6 +8558,106 @@ interface KayakCar {
7633
8558
  }
7634
8559
  }
7635
8560
 
8561
+ declare namespace BowmarkProvider_kitchentuneup {
8562
+ // ── Kitchen Tune-Up — the unit's own declarations, verbatim ──
8563
+ interface KitchentuneupCabinetStyle {
8564
+ featureDefinitionId: number;
8565
+ name: string;
8566
+ group: string | null;
8567
+ thumbnailUrl: string | null;
8568
+ }
8569
+
8570
+ interface KitchentuneupVisualization {
8571
+ resultImageUrl: string;
8572
+ appliedFeatureIds: number[];
8573
+ }
8574
+
8575
+ /**
8576
+ * Kitchen Tune-Up's own AI Design Tool — the live cabinet door/color/finish catalog, and
8577
+ * photo-in/AI-visualization-out generation, run the way kitchentuneup.com/design-tool/ does.
8578
+ */
8579
+ interface Unit {
8580
+ /**
8581
+ * Reads Kitchen Tune-Up's own AI Design Tool catalog off its visualizer vendor's API — every
8582
+ * cabinet door style / color / finish feature currently enabled for the kitchen visualizer,
8583
+ * with the featureDefinitionId visualizeKitchen needs to apply it. Real catalog data, not a
8584
+ * marketing page scrape.
8585
+ */
8586
+ listCabinetStyles(): Promise<KitchentuneupCabinetStyle[]>;
8587
+
8588
+ /**
8589
+ * Runs a photo through Kitchen Tune-Up's own AI Design Tool the way
8590
+ * kitchentuneup.com/design-tool/ does — uploads the photo plus one or more chosen cabinet
8591
+ * features (from listCabinetStyles) to their visualizer vendor's AI image pipeline and returns
8592
+ * the generated visualization image URL. This is the exact functional gap this packet's ANGLE
8593
+ * fit-check recorded: ChatGPT knows the AI Design Tool exists but explicitly refuses to
8594
+ * operate it ('I can't operate Kitchen Tune-Up's website on your behalf') and bounces the user
8595
+ * back to the site.
8596
+ */
8597
+ visualizeKitchen(args: { photoBase64: string, photoFileName?: string, featureDefinitionIds: number[] }): Promise<KitchentuneupVisualization>;
8598
+ }
8599
+ }
8600
+
8601
+ declare namespace BowmarkProvider_kompan {
8602
+ // ── KOMPAN Master — the unit's own declarations, verbatim ──
8603
+ // KOMPAN Master's OWN shapes — not a capability contract.
8604
+
8605
+ type KompanRegion = "region_america" | "region_europe_middleeast" | "region_asia_newzealand" | "region_australia";
8606
+
8607
+ interface KompanVariant {
8608
+ id: string; // pass to getSparePartsDocuments()
8609
+ title: string; // e.g. "PCM157-0205 | UNIVERSAL CAROUSEL"
8610
+ }
8611
+
8612
+ interface KompanSearchResult {
8613
+ productNo: string;
8614
+ region: KompanRegion;
8615
+ found: boolean; // false is a real "no such product number in this region" answer
8616
+ image: string | null;
8617
+ variants: KompanVariant[];
8618
+ }
8619
+
8620
+ interface KompanDocument {
8621
+ section: string; // the site's own heading, e.g. "Layout Drawing", "Installation Instruction"
8622
+ label: string;
8623
+ url: string;
8624
+ }
8625
+
8626
+ interface KompanSparePartsDocuments {
8627
+ variantId: string;
8628
+ purchaseDate: string;
8629
+ title: string | null;
8630
+ documents: KompanDocument[];
8631
+ fullPackageUrl: string | null; // generated on fetch by the site — the URL to fetch, not a static file
8632
+ }
8633
+
8634
+ /**
8635
+ * KOMPAN's own spare-parts / TÜV-certificate / maintenance-manual lookup (KOMPAN Master) —
8636
+ * search a KOMPAN playground product number for its real installed variants, then read the
8637
+ * exact layout drawing, installation instruction, general instruction, on-demand full-package
8638
+ * PDF and language-specific inspection checklists / maintenance manuals for one variant +
8639
+ * purchase date, off the site's own live tool rather than a researched guess.
8640
+ */
8641
+ interface Unit {
8642
+ /**
8643
+ * Searches KOMPAN Master for a product number (e.g. "PCM157") in one region (default
8644
+ * "region_america") and lists every real installed variant of it — each with the internal item
8645
+ * id getSparePartsDocuments() takes. `found: false` is a real, expected answer for a product
8646
+ * number with no record in that region, not an error.
8647
+ */
8648
+ searchProduct(productNo: string, region?: KompanRegion): Promise<KompanSearchResult>;
8649
+
8650
+ /**
8651
+ * Reads the real spare-parts / TÜV-certificate / maintenance-manual documents KOMPAN Master
8652
+ * publishes for one variant (an id from searchProduct()) at one purchase date ("YYYY-MM-DD",
8653
+ * since the site keys the applicable document revision off it) — layout drawing, installation
8654
+ * instruction, general instruction, additional checklists/manuals, and the on-demand "full
8655
+ * package" PDF URL.
8656
+ */
8657
+ getSparePartsDocuments(variantId: string, purchaseDate: string): Promise<KompanSparePartsDocuments>;
8658
+ }
8659
+ }
8660
+
7636
8661
  declare namespace BowmarkProvider_labcorp {
7637
8662
  // ── Labcorp — the unit's own declarations, verbatim ──
7638
8663
  interface LabcorpTestSummary {
@@ -7967,9 +8992,9 @@ interface LiquiddeathCart {
7967
8992
  interface LiquiddeathLiveCartLine {
7968
8993
  lineId: string;
7969
8994
  variantId: string;
7970
- variantTitle: string | null;
7971
- productTitle: string;
8995
+ title: string;
7972
8996
  quantity: number;
8997
+ unitPrice: string;
7973
8998
  lineTotal: string;
7974
8999
  }
7975
9000
  interface LiquiddeathLiveCart {
@@ -7980,9 +9005,7 @@ interface LiquiddeathLiveCart {
7980
9005
  total: string;
7981
9006
  currency: string;
7982
9007
  checkoutUrl: string;
7983
- countryCode: string | null;
7984
- createdAt: string | null;
7985
- updatedAt: string | null;
9008
+ expiresAt: string | null;
7986
9009
  }
7987
9010
 
7988
9011
  /**
@@ -8018,15 +9041,19 @@ interface LiquiddeathLiveCart {
8018
9041
  addToCart(items: LiquiddeathCartItem[]): Promise<LiquiddeathCart>;
8019
9042
 
8020
9043
  /**
8021
- * Reads a cart the shopper already has, by its id — line items, quantities, per-line and order
8022
- * totals, and the real checkout URL to hand back. The id is a bearer credential the SHOPPER
8023
- * holds, and it is the one their cart or checkout LINK carries
8024
- * (liquiddeath.com/cart/c/<token>?key=<key>), NOT the store's `cart` cookie or /cart.js token
8025
- * — those are a separate Ajax id space this endpoint answers 'Cart does not exist' for. There
8026
- * is no way to list or search carts, so a caller without an id cannot get one. Accepts the id
8027
- * with or without the `?key=` suffix. THROWS when the cart does not exist or has expired
8028
- * Shopify drops an unused cart within 30 days and deletes it at checkout because an empty
8029
- * cart and a dead link are opposite answers. Does not return shipping options or discounts:
9044
+ * Reads a cart the shopper already has, by its id — line items, quantities, per-unit and
9045
+ * per-line prices, order subtotal and total, the cart's currency and expiry, and the real
9046
+ * checkout URL to hand back. The id is a bearer credential the SHOPPER holds, and it is the
9047
+ * one their cart or checkout LINK carries (liquiddeath.com/cart/c/<token>?key=<key>), NOT the
9048
+ * store's `cart` cookie or /cart.js token — those are a separate Ajax id space this endpoint
9049
+ * answers 'The requested cart does not exist' for. There is no way to list or search carts, so
9050
+ * a caller without an id cannot get one. THE WHOLE id IS REQUIRED, `?key=` included: the store
9051
+ * checks the key's value, so a bare token comes back as a cart that does not exist rather than
9052
+ * as a missing credential, and this refuses it here instead. THROWS when the cart does not
9053
+ * exist or has expired — Shopify drops an unused cart within 30 days and deletes it at
9054
+ * checkout — because an empty cart and a dead link are opposite answers. Each line carries the
9055
+ * store's own joined product-and-variant `title` ("Death Western Hat - Cream/Green"); this
9056
+ * door publishes no separate product title. Does not return shipping options or discounts:
8030
9057
  * both require setting an address on the cart, which is a write this provider does not
8031
9058
  * perform.
8032
9059
  */
@@ -8059,6 +9086,61 @@ interface LonelyPlanetSearchResult {
8059
9086
  }
8060
9087
  }
8061
9088
 
9089
+ declare namespace BowmarkProvider_louvershop {
9090
+ // ── Louver Shop Shutters — the unit's own declarations, verbatim ──
9091
+ interface LouvershopBranch {
9092
+ id: number;
9093
+ name: string;
9094
+ link: string;
9095
+ tel: string;
9096
+ }
9097
+
9098
+ interface LouvershopLocalArea {
9099
+ zip: string;
9100
+ city: string;
9101
+ state: string;
9102
+ stateCode: string;
9103
+ }
9104
+
9105
+ interface LouvershopConsultant {
9106
+ id: number;
9107
+ name: string;
9108
+ link: string;
9109
+ }
9110
+
9111
+ interface LouvershopAvailability {
9112
+ exteriorDecorative: boolean;
9113
+ exteriorSecurity: boolean;
9114
+ }
9115
+
9116
+ interface FindLocalDealerResult {
9117
+ zip: string;
9118
+ inServiceArea: boolean;
9119
+ branch: LouvershopBranch | null;
9120
+ area: LouvershopLocalArea | null;
9121
+ consultants: LouvershopConsultant[];
9122
+ availability: LouvershopAvailability | null;
9123
+ }
9124
+
9125
+ /**
9126
+ * Window treatments (interior/exterior shutters, blinds, shades) dealer network.
9127
+ * findLocalDealer is live — the same lookup the site's own free-quote/consultant-locator forms
9128
+ * run before showing a booking path, given a ZIP. requestConsultation (submitting the actual
9129
+ * in-home consultation request) is a stub — see its notImplemented reason.
9130
+ */
9131
+ interface Unit {
9132
+ /**
9133
+ * Looks up the Louver Shop dealer/branch that covers a US ZIP (`zip`, a 4-5 digit string, e.g.
9134
+ * "30301") — the same lookup the site's own "Free In-Home Design Consultation" form and "Find
9135
+ * a Consultant" locator both run before offering a booking path. Returns whether the ZIP is in
9136
+ * the dealer network, the matched branch (name, phone, page slug), the normalized local area,
9137
+ * the branch's assigned consultants (deduplicated), and per-branch exterior-shutter
9138
+ * availability flags. Recovered from the locator widget's own backend, not guessed at.
9139
+ */
9140
+ findLocalDealer(args: object): Promise<FindLocalDealerResult>;
9141
+ }
9142
+ }
9143
+
8062
9144
  declare namespace BowmarkProvider_lufthansa {
8063
9145
  // ── Lufthansa — the unit's own declarations, verbatim ──
8064
9146
  interface LufthansaFlightLeg {
@@ -8316,9 +9398,54 @@ interface LululemonProductAttributes {
8316
9398
  * reviews on products whose live page shows 22,748. */
8317
9399
  ratingValue: number | null;
8318
9400
  reviewCount: number | null;
9401
+ /** Per-FIELD origin for the eight facts above, keyed by the same names. THIS
9402
+ * is how a refused read is told apart from a garment with nothing published:
9403
+ * fabrics [] beside status "absent" is lululemon saying it names no fabric,
9404
+ * and fabrics [] beside status "unreachable" is the page refusing us. Ranking
9405
+ * that treats the two alike silently prefers whichever candidates loaded. */
9406
+ provenance: Record<string, FieldProvenance>;
9407
+ /** The roll-up. On a refused page ratio is 0 and unreachableFields names all
9408
+ * eight — the machine-readable form of the sentence in warnings. */
9409
+ completeness: Completeness;
8319
9410
  /** What could not be reached. Non-empty means the page refused. */
8320
9411
  warnings: string[];
8321
9412
  }
9413
+ /** Where one field's value came from, and the retailer text behind it. */
9414
+ interface FieldProvenance {
9415
+ /** "published" — lululemon stated it. "absent" — the page rendered and said
9416
+ * nothing about this field. "unreachable" — the page refused, so UNKNOWN. */
9417
+ status: "published" | "absent" | "unreachable";
9418
+ /** Which door: "lululemon_pdp_ldjson", "lululemon_pdp_accordion" or
9419
+ * "lululemon_pdp_title". Null when nothing filled it. */
9420
+ source: string | null;
9421
+ /** The retailer's own words the value rests on, for a field derived from
9422
+ * prose. Null for a field the site published as a typed value. */
9423
+ evidence: string | null;
9424
+ /** On "unreachable" only: what was refused. */
9425
+ detail?: string;
9426
+ }
9427
+ interface Completeness {
9428
+ fields: number;
9429
+ published: number;
9430
+ absent: number;
9431
+ unreachable: number;
9432
+ /** published / fields, to 3dp. */
9433
+ ratio: number;
9434
+ /** The fields that are UNKNOWN rather than known-empty. */
9435
+ unreachableFields: string[];
9436
+ sourcesUsed: string[];
9437
+ }
9438
+ /** What getProducts returns. PARTIAL by construction — the pricing catalogue
9439
+ * holds ~39% of the ids in lululemon's own sitemap, so ids it does not carry are
9440
+ * NAMED rather than silently dropped or thrown over. */
9441
+ interface LululemonProductBatch {
9442
+ /** In the order the ids were passed, not the order they finished. */
9443
+ products: LululemonProduct[];
9444
+ /** Every id that did not read, with the catalogue's own sentence. */
9445
+ missing: Array<{ productId: string; detail: string }>;
9446
+ requested: number;
9447
+ warnings: string[];
9448
+ }
8322
9449
  interface LululemonRow {
8323
9450
  id: string;
8324
9451
  title: string;
@@ -8373,6 +9500,17 @@ interface LululemonSimilarProducts {
8373
9500
  */
8374
9501
  getProduct(query: { productId: string }): Promise<LululemonProduct>;
8375
9502
 
9503
+ /**
9504
+ * Reads the full configurator for MANY products in one call — the shape to use when ranking a
9505
+ * candidate set, because a `search` row carries a price range and a colour count but not the
9506
+ * per-colourway sizes, markdown evidence or images a ranking turns on. Returns `products` in
9507
+ * the order the ids were passed. PARTIAL is the normal answer: the pricing catalogue holds
9508
+ * roughly 39% of the ids in lululemon's own sitemap, so ids it does not carry come back in
9509
+ * `missing` with the catalogue's own sentence, and one of them never costs the other rows. At
9510
+ * most 24 ids — the same cap `search` returns — so one full search page is always one batch.
9511
+ */
9512
+ getProducts(query: { productIds: string[] }): Promise<LululemonProductBatch>;
9513
+
8376
9514
  /**
8377
9515
  * Reads what lululemon's OWN product page publishes about a garment and the third-party
8378
9516
  * pricing door does not carry at all: the category the site files it under, the collection
@@ -10792,6 +11930,10 @@ interface PremierbuildingsStyle {
10792
11930
  label: string;
10793
11931
  sidingOptions: string[];
10794
11932
  sizes: { sizeKey: string; width: number; length: number }[];
11933
+ imageUrl: string | null; // a real product image from Premier's own catalogue
11934
+ roofStyle: string | null; // "gable", "gambrel", ...
11935
+ roofing: string | null; // "metal", ...
11936
+ wallHeight: string | null; // Premier's own encoding in inches, e.g. "left-78-right-78-eave-72"
10795
11937
  }
10796
11938
  interface PremierbuildingsPrice {
10797
11939
  styleKey: string;
@@ -10825,8 +11967,10 @@ interface PremierbuildingsDealer {
10825
11967
  interface Unit {
10826
11968
  /**
10827
11969
  * Lists every real building style Premier's ShedView configurator offers (Lofted Barn,
10828
- * Utility, Cabin, Garage, ...) with its real siding options and every real buildable size
10829
- * (width x length), read straight from the configurator's own live catalogue.
11970
+ * Utility, Cabin, Garage, ...) with its real siding options, every real buildable size (width
11971
+ * x length), and what the building actually IS — a real product image, the roof line and
11972
+ * roofing material, and Premier's own wall-height spec — read straight from the configurator's
11973
+ * own live catalogue.
10830
11974
  */
10831
11975
  listBuildingStyles(): Promise<PremierbuildingsStyle[]>;
10832
11976
 
@@ -11853,6 +12997,47 @@ interface RitaniPriceResult {
11853
12997
  }
11854
12998
  }
11855
12999
 
13000
+ declare namespace BowmarkProvider_roofmaxx {
13001
+ // ── Roof Maxx — the unit's own declarations, verbatim ──
13002
+ interface RoofmaxxCalculatorSettings {
13003
+ title: string;
13004
+ description: string;
13005
+ }
13006
+
13007
+ interface RoofmaxxCostEstimateArgs {
13008
+ squareFootage: number;
13009
+ region: "new-england" | "middle-atlantic" | "east-north-central" | "west-north-central" |
13010
+ "south-atlantic" | "east-south-central" | "west-south-central" | "mountain" | "pacific";
13011
+ roofType: "asphalt" | "metal" | "clay" | "wood";
13012
+ roofSlope: "walkable" | "semiWalkable" | "nonWalkable";
13013
+ numOfLevels: "1" | "2" | "3";
13014
+ garageType: "nogarage" | "1car" | "2car";
13015
+ }
13016
+
13017
+ interface RoofmaxxCostEstimate {
13018
+ low: number;
13019
+ mid: number;
13020
+ high: number;
13021
+ }
13022
+
13023
+ /**
13024
+ * Roof Maxx's own Roof Replacement Cost Calculator (roofmaxx.com/learning-hub) — given a
13025
+ * home's size, location and roof details, returns the site's real server-computed low/mid/high
13026
+ * full-replacement-cost estimate.
13027
+ */
13028
+ interface Unit {
13029
+ /** The Roof Replacement Cost Calculator's own admin-configured title and description. */
13030
+ getCalculatorSettings(): Promise<RoofmaxxCalculatorSettings>;
13031
+
13032
+ /**
13033
+ * Runs the real calculator: given square footage, region, roof type, roof slope, garage size
13034
+ * and building levels, returns Roof Maxx's own server-computed low/mid/high
13035
+ * full-replacement-cost tiers.
13036
+ */
13037
+ estimateRoofReplacementCost(arg: RoofmaxxCostEstimateArgs): Promise<RoofmaxxCostEstimate>;
13038
+ }
13039
+ }
13040
+
11856
13041
  declare namespace BowmarkProvider_samsclub {
11857
13042
  // ── Sam's Club — the unit's own declarations, verbatim ──
11858
13043
  interface SamsclubInstantSavingsItem {
@@ -12940,6 +14125,52 @@ interface SunHomeSaunasCartResult {
12940
14125
  }
12941
14126
  }
12942
14127
 
14128
+ declare namespace BowmarkProvider_tamarackidaho {
14129
+ // ── Tamarack Resort — the unit's own declarations, verbatim ──
14130
+ interface tamarackidahoSearchArgs {
14131
+ arrivalDate: string;
14132
+ departureDate: string;
14133
+ adultCount: number;
14134
+ childCount?: number;
14135
+ }
14136
+
14137
+ interface tamarackidahoSearchResult {
14138
+ arrivalDate: string;
14139
+ departureDate: string;
14140
+ adultCount: number;
14141
+ childCount: number;
14142
+ units: tamarackidahoUnit[];
14143
+ }
14144
+
14145
+ interface tamarackidahoUnit {
14146
+ supplierId: string;
14147
+ supplierName: string;
14148
+ productId: string;
14149
+ unitName: string;
14150
+ totalPrice: number;
14151
+ }
14152
+
14153
+ /**
14154
+ * Tamarack Resort's own direct-managed lodging booking engine (Inntopia RTP) — real
14155
+ * availability and price per unit type for a date range and party size, straight from the
14156
+ * site's own search widget, browserless.
14157
+ */
14158
+ interface Unit {
14159
+ /**
14160
+ * Searches Tamarack Resort's own direct-managed lodging (the Lodge at Osprey Meadows, the
14161
+ * Village at Tamarack Resort, and Tamarack Homes and Cottages — not the golf tee-time flow, a
14162
+ * different vendor) for a stay and party size. `arrivalDate`/`departureDate` are "MM/DD/YYYY"
14163
+ * strings (the widget's own format), `adultCount` is required and positive, `childCount`
14164
+ * defaults to 0. Returns every unit type Tamarack's own booking engine (Inntopia RTP)
14165
+ * currently prices as AVAILABLE for that exact query — each with its supplier (property), unit
14166
+ * name, and `totalPrice` in USD for the whole queried stay (not nightly) — genuinely computed
14167
+ * per call, not a cached listing. An empty `units` array is a real answer: Tamarack has
14168
+ * nothing available for that stay, not a failure.
14169
+ */
14170
+ searchLodging(args: tamarackidahoSearchArgs): Promise<tamarackidahoSearchResult>;
14171
+ }
14172
+ }
14173
+
12943
14174
  declare namespace BowmarkProvider_target {
12944
14175
  // ── Target — the unit's own declarations, verbatim ──
12945
14176
  interface targetRow {
@@ -12994,6 +14225,55 @@ interface TargetStoreSearch {
12994
14225
  }
12995
14226
  }
12996
14227
 
14228
+ declare namespace BowmarkProvider_tatcha {
14229
+ // ── Tatcha — the unit's own declarations, verbatim ──
14230
+ interface TatchaQuizOption {
14231
+ value: string;
14232
+ label: string;
14233
+ }
14234
+
14235
+ interface TatchaRitualQuizOptions {
14236
+ skinTypes: TatchaQuizOption[];
14237
+ benefits: TatchaQuizOption[];
14238
+ eyeConcerns: TatchaQuizOption[];
14239
+ }
14240
+
14241
+ interface TatchaRitualProduct {
14242
+ step: string;
14243
+ sku: string;
14244
+ name: string;
14245
+ secondaryName: string;
14246
+ price: string;
14247
+ handle: string;
14248
+ url: string;
14249
+ image: string;
14250
+ usageTime: "AM" | "PM" | "both";
14251
+ description: string;
14252
+ inStock: boolean;
14253
+ }
14254
+
14255
+ interface TatchaRitual {
14256
+ summary: string;
14257
+ products: TatchaRitualProduct[];
14258
+ handoffUrl: string;
14259
+ }
14260
+
14261
+ /**
14262
+ * Runs Tatcha's real "Ritual Finder" skincare quiz — the site's own product-matching backend,
14263
+ * not a generic routine.
14264
+ */
14265
+ interface Unit {
14266
+ /** Reads the live Ritual Finder quiz's real skin-type, benefit and eye-concern menus. */
14267
+ getRitualQuizOptions(): Promise<TatchaRitualQuizOptions>;
14268
+
14269
+ /**
14270
+ * Runs real quiz answers through Tatcha's own personalization backend and returns the real
14271
+ * AM/PM product ritual it recommends.
14272
+ */
14273
+ getPersonalizedRitual(skinType: string, benefits: string[], eyeConcerns?: string[], sensitive?: boolean, owned?: string[]): Promise<TatchaRitual>;
14274
+ }
14275
+ }
14276
+
12997
14277
  declare namespace BowmarkProvider_teladoc {
12998
14278
  // ── Teladoc Health — the unit's own declarations, verbatim ──
12999
14279
  interface teladocRow {
@@ -13048,98 +14328,6 @@ interface teladocInsuranceCoverage {
13048
14328
  }
13049
14329
  }
13050
14330
 
13051
- declare namespace BowmarkProvider_tentree {
13052
- // ── tentree — the unit's own declarations, verbatim ──
13053
- interface TentreeVariant {
13054
- /** Shopify's numeric variant id as a string. What addToCart takes. */
13055
- id: string;
13056
- /** The variant's own label, e.g. "ASHWOOD METEORITE BLACK / ONE". */
13057
- title: string;
13058
- /** Decimal string exactly as the store publishes it, e.g. "45.00". */
13059
- price: string;
13060
- compareAtPrice: string | null;
13061
- sku: string | null;
13062
- /** The store's own per-variant stock flag. */
13063
- available: boolean;
13064
- options: string[];
13065
- }
13066
- interface TentreeProduct {
13067
- handle: string;
13068
- title: string;
13069
- productType: string;
13070
- vendor: string;
13071
- url: string;
13072
- optionNames: string[];
13073
- variants: TentreeVariant[];
13074
- priceRange: { min: string; max: string } | null;
13075
- inStock: boolean;
13076
- tags: string[];
13077
- descriptionHtml: string | null;
13078
- }
13079
- interface TentreeCartLine {
13080
- /** Shopify's own line key, which its cart-change endpoints address a line by. */
13081
- lineKey: string;
13082
- variantId: string;
13083
- productTitle: string;
13084
- /** Null on a single-variant product. */
13085
- variantTitle: string | null;
13086
- quantity: number;
13087
- price: string;
13088
- lineTotal: string;
13089
- url: string;
13090
- }
13091
- interface TentreeCart {
13092
- /** The store's own cart token — a bearer credential, so treat it like one. */
13093
- token: string;
13094
- lines: TentreeCartLine[];
13095
- /** Units, NOT lines: two of one variant is one line and two items. */
13096
- itemCount: number;
13097
- subtotal: string;
13098
- currency: string;
13099
- cartUrl: string;
13100
- checkoutUrl: string;
13101
- }
13102
-
13103
- /**
13104
- * Sustainable apparel storefront — hats, tees, hoodies and outerwear — with a real guest cart
13105
- * a caller can fill across several calls.
13106
- */
13107
- interface Unit {
13108
- /**
13109
- * Searches tentree's live catalogue and returns matching products with their real variants,
13110
- * current prices and per-variant stock. Matches whole words, so 'tee' finds tees and not
13111
- * 'steel'. Returns [] when nothing matches, which is an ordinary answer rather than an error.
13112
- */
13113
- searchProducts(query: string, opts?: { productType?: string; inStockOnly?: boolean; limit?: number }): Promise<TentreeProduct[]>;
13114
-
13115
- /**
13116
- * Reads one product by its handle — every variant, its exact price and whether that specific
13117
- * size or colour is purchasable right now. Takes the handle searchProducts returns, and its
13118
- * variants[].id is what addToCart takes. THROWS on an unknown handle (the store answers a real
13119
- * 404).
13120
- */
13121
- getProduct(handle: string): Promise<TentreeProduct>;
13122
-
13123
- /**
13124
- * Puts variants into THIS run's own cart on the store and returns the cart as the store
13125
- * reports it. Really writes — the cart exists on tentree.com from the first call, and it
13126
- * belongs to this run's cookie jar. Call it several times inside one bowmark.session() and the
13127
- * lines accumulate; call it across two separate runs and the second cart does not contain the
13128
- * first's lines. Takes VARIANT ids (getProduct().variants[].id), never handles. Nothing is
13129
- * bought: checkoutUrl is where a shopper would pay.
13130
- */
13131
- addToCart(items: Array<{ variantId: string; quantity?: number }>): Promise<TentreeCart>;
13132
-
13133
- /**
13134
- * Reads THIS run's cart back from the store — lines, quantities, per-line and order totals,
13135
- * and the real cart and checkout URLs. Takes no id: the cart is the one this run's cookie jar
13136
- * holds, so a fresh run reads an empty cart rather than somebody else's. An empty cart is an
13137
- * ordinary answer (itemCount 0), not an error.
13138
- */
13139
- getCart(): Promise<TentreeCart>;
13140
- }
13141
- }
13142
-
13143
14331
  declare namespace BowmarkProvider_therabody {
13144
14332
  // ── Therabody — the unit's own declarations, verbatim ──
13145
14333
  interface TherabodyVariant {
@@ -13835,6 +15023,72 @@ interface TrekTravelSearchFilters {
13835
15023
  }
13836
15024
  }
13837
15025
 
15026
+ declare namespace BowmarkProvider_twiddy {
15027
+ // ── Twiddy & Company Realtors — the unit's own declarations, verbatim ──
15028
+ interface TwiddyRentalRow {
15029
+ propertyId: number;
15030
+ propertyNumber: string;
15031
+ name: string;
15032
+ url: string;
15033
+ town: string;
15034
+ distanceToBeach: string;
15035
+ bedrooms: number | null;
15036
+ priceFromUsd: number | null;
15037
+ priceFromFormatted: string | null;
15038
+ ratingValue: number | null;
15039
+ isAvailable: boolean;
15040
+ }
15041
+ interface TwiddyRentalDetail {
15042
+ propertyId: number;
15043
+ name: string;
15044
+ identifier: string;
15045
+ description: string;
15046
+ streetAddress: string;
15047
+ town: string;
15048
+ petsAllowed: boolean;
15049
+ amenities: string[];
15050
+ numberOfBedrooms: number | null;
15051
+ numberOfBathrooms: number | null;
15052
+ images: string[];
15053
+ url: string;
15054
+ }
15055
+ type TwiddyQuote =
15056
+ | { available: true; propertyId: number; checkin: string; nights: number; currency: "USD";
15057
+ rentalFeeUsd: number; discountUsd: number; taxUsd: number; totalUsd: number; checkoutUrl: string }
15058
+ | { available: false; propertyId: number; checkin: string; nights: number };
15059
+
15060
+ /**
15061
+ * Twiddy & Company's own Outer Banks vacation rental search and real-time weekly
15062
+ * pricing/booking-handoff engine — a regional owner-operator's own 1,000+ property inventory,
15063
+ * live availability and price, not a stale catalog.
15064
+ */
15065
+ interface Unit {
15066
+ /**
15067
+ * Runs Twiddy's own portfolio-wide search (all 1,000+ managed Outer Banks properties in one
15068
+ * call), optionally filtered to one of the six towns ("Corolla", "Duck", "4x4", "Southern
15069
+ * Shores", "Kitty Hawk", "Kill Devil Hills", "Nags Head") and/or a minimum bedroom count, and
15070
+ * returns the live matching listings — name, url, town, distance to beach, bed count, an "as
15071
+ * low as" headline price, rating.
15072
+ */
15073
+ searchRentals(options?: { town?: string; minBedrooms?: number }): Promise<TwiddyRentalRow[]>;
15074
+
15075
+ /**
15076
+ * Reads one rental in full — description, address, pets-allowed flag, amenities, bed/bath
15077
+ * counts, photos, and the internal numeric propertyId getRentalQuote needs — from the
15078
+ * propertyUrl a search result carries (a twiddy.com/outer-banks/... path or full URL).
15079
+ */
15080
+ getRentalDetail(propertyUrl: string): Promise<TwiddyRentalDetail>;
15081
+
15082
+ /**
15083
+ * Runs the site's own real-time weekly pricing engine for one property and a check-in date
15084
+ * ("YYYY-MM-DD", default 7 nights) — rental fee, discount, tax, total — and returns the exact
15085
+ * booking/checkout URL for that week. `available: false` means the site checked and the
15086
+ * property has no live rate for that week, an ordinary answer.
15087
+ */
15088
+ getRentalQuote(propertyId: number, options: { checkin: string; nights?: number }): Promise<TwiddyQuote>;
15089
+ }
15090
+ }
15091
+
13838
15092
  declare namespace BowmarkProvider_ulrichlifestyle {
13839
15093
  // ── Ulrich Lifestyle Structures — the unit's own declarations, verbatim ──
13840
15094
  // Ulrich Lifestyle Structures' OWN shapes — not a capability contract.
@@ -13906,6 +15160,58 @@ interface UlrichPriceResult {
13906
15160
  }
13907
15161
  }
13908
15162
 
15163
+ declare namespace BowmarkProvider_vervecoffee {
15164
+ // ── Verve Coffee Roasters — the unit's own declarations, verbatim ──
15165
+ interface VervecoffeeSubscription {
15166
+ id: string;
15167
+ handle: string;
15168
+ title: string;
15169
+ priceFormatted: string;
15170
+ url: string;
15171
+ }
15172
+ interface VervecoffeeCoffeeMatch {
15173
+ id: string;
15174
+ title: string;
15175
+ descriptionHtml: string;
15176
+ startingPriceFormatted: string;
15177
+ url: string;
15178
+ subscriptionPlans: Array<{ name: string; deliveryInterval: string; priceWithDiscount: string }>;
15179
+ }
15180
+ interface VervecoffeeCoffeeMatchResult {
15181
+ recommendedProducts: VervecoffeeCoffeeMatch[];
15182
+ }
15183
+ interface CoffeeQuizAnswers {
15184
+ journeyStage: "coffee_curious" | "casual_coffee_lover" | "coffee_connoisseur" | "barista";
15185
+ brewMethod: "pourover" | "coffee_maker" | "espresso" | "french_press" | "aeropress";
15186
+ coffeeStyle: "black" | "milk_or_cream" | "sugar_or_sweetener";
15187
+ roastPreference: "light" | "medium" | "dark" | "not_sure";
15188
+ tastingNote: "chocolate" | "citrus" | "fruits" | "sweet" | "floral" | "nuts";
15189
+ }
15190
+
15191
+ /**
15192
+ * Verve Coffee Roasters' Roaster's Choice subscription catalog and its real 'Find Your Coffee
15193
+ * Match' quiz (Octane AI-powered) — drives the same 5 questions the live site asks and returns
15194
+ * the actual subscription it recommends, priced, with a buy link.
15195
+ */
15196
+ interface Unit {
15197
+ /**
15198
+ * Lists Verve's five real Roaster's Choice coffee subscription products (single origin, blend,
15199
+ * espresso, Africa, Latin America) with their live USD price, read off the storefront's own
15200
+ * /products.json catalog.
15201
+ */
15202
+ listRoastersChoiceSubscriptions(): Promise<VervecoffeeSubscription[]>;
15203
+
15204
+ /**
15205
+ * Runs Verve's real 'Find Your Coffee Match' quiz end to end — the same 5 questions the live
15206
+ * Octane AI-powered quiz at /pages/quiz asks every visitor — and returns the actual Roaster's
15207
+ * Choice subscription(s) it recommends, with real USD price and a buy-page link. THROWS if
15208
+ * Verve's quiz has been reconfigured and one of the 5 answer labels no longer matches (see the
15209
+ * error for the live option set).
15210
+ */
15211
+ matchCoffeeSubscription(answers: CoffeeQuizAnswers): Promise<VervecoffeeCoffeeMatchResult>;
15212
+ }
15213
+ }
15214
+
13909
15215
  declare namespace BowmarkProvider_viewrail {
13910
15216
  // ── Viewrail — the unit's own declarations, verbatim ──
13911
15217
  interface ViewrailMaterial {
@@ -13946,6 +15252,62 @@ interface ViewrailMountingStyle {
13946
15252
  }
13947
15253
  }
13948
15254
 
15255
+ declare namespace BowmarkProvider_villagerealtyobx {
15256
+ // ── Village Realty — the unit's own declarations, verbatim ──
15257
+ interface VillagerealtyobxListing {
15258
+ propertyID: string;
15259
+ seoName: string;
15260
+ name: string;
15261
+ town: string;
15262
+ address: string | null;
15263
+ bedrooms: number | null;
15264
+ maxGuests: number | null;
15265
+ photoUrl: string | null;
15266
+ url: string;
15267
+ }
15268
+
15269
+ interface VillagerealtyobxQuote {
15270
+ propertyID: string;
15271
+ checkin: string;
15272
+ checkout: string;
15273
+ available: boolean;
15274
+ rent: number | null;
15275
+ taxes: number | null;
15276
+ total: number | null;
15277
+ currency: string;
15278
+ bookNowURL: string | null;
15279
+ message: string | null;
15280
+ }
15281
+
15282
+ /**
15283
+ * Village Realty's own Outer Banks vacation-rental search and real-time property quote (rent,
15284
+ * taxes, total, book-now link) — the same live pricing their own site computes, no login
15285
+ * required.
15286
+ */
15287
+ interface Unit {
15288
+ /**
15289
+ * Searches Village Realty's own 900+ Outer Banks rental listings the way
15290
+ * villagerealtyobx.com/outer-banks-vacation-rentals does — filter by town (e.g. "Corolla",
15291
+ * "Nags Head"), exact bedroom count, amenities (e.g. "Private Pool", "Elevator"), and
15292
+ * optionally a date range — returning each matching property's id, name, town, address,
15293
+ * bedroom count, max guests and detail-page URL. Call getQuote with a result's propertyID for
15294
+ * a real priced quote.
15295
+ */
15296
+ searchRentals(args?: { town?: string, bedrooms?: number, amenities?: string[], checkin?: string, checkout?: string, page?: number }): Promise<VillagerealtyobxListing[]>;
15297
+
15298
+ /**
15299
+ * Gets a real-time price quote for one Village Realty property and date range — the exact
15300
+ * server-computed rent, taxes and total the rental detail page shows after picking dates, plus
15301
+ * the book-now URL. `checkin`/`checkout` are `MM/DD/YYYY`. `available: false` is a genuine
15302
+ * site answer (e.g. the dates fail the property's minimum-night-stay rule), not an error —
15303
+ * this is the flow ChatGPT itself cannot operate today: asked to price a Village Realty stay
15304
+ * it answers "I can't complete the booking or take payment for you" and recommends competitor
15305
+ * sites instead of quoting Village Realty's own live price.
15306
+ */
15307
+ getQuote(args: { propertyID: string, checkin: string, checkout: string }): Promise<VillagerealtyobxQuote>;
15308
+ }
15309
+ }
15310
+
13949
15311
  declare namespace BowmarkProvider_visible {
13950
15312
  // ── Visible — the unit's own declarations, verbatim ──
13951
15313
  interface VisibleDealOffer {
@@ -14205,6 +15567,33 @@ interface VisibleGetPlansResult {
14205
15567
  }
14206
15568
  }
14207
15569
 
15570
+ declare namespace BowmarkProvider_voluspa {
15571
+ // ── Voluspa — the unit's own declarations, verbatim ──
15572
+ interface VoluspaQuizButton {
15573
+ text: string;
15574
+ action: string;
15575
+ url?: string;
15576
+ selectedValue?: string;
15577
+ }
15578
+ interface VoluspaQuizIntro {
15579
+ paths: VoluspaQuizButton[];
15580
+ firstQuestionOptions: VoluspaQuizButton[];
15581
+ }
15582
+
15583
+ /**
15584
+ * Voluspa's own "Find Your Fragrance" quiz suite — reads the branching quiz's entry paths and
15585
+ * first-question scent-family options straight from the quiz vendor's config.
15586
+ */
15587
+ interface Unit {
15588
+ /**
15589
+ * Reads the fragrance quiz's entry screen — its two branching paths and the FIRST question's
15590
+ * scent-family options for one of them (0 = home fragrance, 1 = personal fragrance/EDP, as the
15591
+ * splash screen lists them; default 0) — decoded from Digioh's own campaign config.
15592
+ */
15593
+ getFragranceQuizIntro(pathIndex?: number): Promise<VoluspaQuizIntro>;
15594
+ }
15595
+ }
15596
+
14208
15597
  declare namespace BowmarkProvider_walmart {
14209
15598
  // ── Walmart — the unit's own declarations, verbatim ──
14210
15599
  interface walmartStore {
@@ -14384,6 +15773,103 @@ interface wellfoundCompanyDetail {
14384
15773
  }
14385
15774
  }
14386
15775
 
15776
+ declare namespace BowmarkProvider_xpresswellnessurgentcare {
15777
+ // ── Xpress Wellness Urgent Care — the unit's own declarations, verbatim ──
15778
+ interface XpressFacility {
15779
+ facilityId: string; // healow facility_id — what checkWaitTime takes
15780
+ name: string; // e.g. "Manhattan, KS"
15781
+ address: string | null;
15782
+ phone: string | null;
15783
+ detailsUrl: string | null; // the clinic's own page on the marketing site
15784
+ checkinUrl: string; // the healow openaccess widget URL
15785
+ }
15786
+ interface XpressWaitTime {
15787
+ facilityId: string;
15788
+ facilityName: string; // confirmed by the widget's own dataLayer, not assumed
15789
+ address: string | null;
15790
+ phone: string | null;
15791
+ waitTimeText: string; // the site's own bucketed phrase, e.g. "Under 30 mins"
15792
+ hoursText: string | null; // e.g. "OPEN - Until 8 PM"
15793
+ url: string;
15794
+ }
15795
+
15796
+ /**
15797
+ * Reads Xpress Wellness Urgent Care's clinic roster and each clinic's live healow wait-time /
15798
+ * check-in widget — no key, no browser.
15799
+ */
15800
+ interface Unit {
15801
+ /**
15802
+ * Lists every Xpress Wellness Urgent Care clinic — 40 locations across Oklahoma, Kansas and
15803
+ * one Texas site — with name, address, phone, the clinic's own detail page and the healow
15804
+ * check-in widget URL + facility_id. Takes nothing. The facilityId it returns is what
15805
+ * checkWaitTime takes. THROWS rather than returning [] when the roster page answers with no
15806
+ * clinics — the roster is never honestly empty.
15807
+ */
15808
+ listFacilities(): Promise<XpressFacility[]>;
15809
+
15810
+ /**
15811
+ * Reads one clinic's live estimated wait time, hours-today status and confirmed identity
15812
+ * straight off its healow openaccess widget. facilityId is the numeric id listFacilities
15813
+ * returns (e.g. "10"). Confirms the facility resolved by cross-checking the widget's own
15814
+ * embedded facility name before returning a reading; THROWS with the caller-facing facility_id
15815
+ * named if the widget carries no name (an unknown id) or no wait-time reading (the widget's
15816
+ * markup changed).
15817
+ */
15818
+ checkWaitTime(facilityId: string): Promise<XpressWaitTime>;
15819
+ }
15820
+ }
15821
+
15822
+ declare namespace BowmarkProvider_yourarborhome {
15823
+ // ── Arbor Homes — the unit's own declarations, verbatim ──
15824
+ interface ArborHome {
15825
+ uniqueName: string;
15826
+ headline: string;
15827
+ status: string;
15828
+ price: number | null;
15829
+ beds: number | null;
15830
+ bathsFull: number | null;
15831
+ bathsHalf: number | null;
15832
+ sqft: number | null;
15833
+ stories: number | null;
15834
+ moveInDate: string | null;
15835
+ address: { street: string; city: string; state: string; postalCode: string };
15836
+ detailUrl: string | null;
15837
+ selfTourUrl: string | null;
15838
+ }
15839
+ interface SearchHomesFilters {
15840
+ city?: string;
15841
+ minPrice?: number;
15842
+ maxPrice?: number;
15843
+ minBeds?: number;
15844
+ minBaths?: number;
15845
+ minSqft?: number;
15846
+ status?: string;
15847
+ }
15848
+
15849
+ /**
15850
+ * Arbor Homes — Indiana/Ohio/Kentucky new-construction homebuilder (Clayton Properties Group).
15851
+ * searchHomes reads its live quick-move-in inventory (price, beds/baths/sqft, status,
15852
+ * availability); getHome reads one listing by id. Both return the site's own NterNow
15853
+ * self-guided-tour booking link where the listing has it enabled.
15854
+ */
15855
+ interface Unit {
15856
+ /**
15857
+ * Reads Arbor Homes' live quick move-in inventory off yourarborhome.com/homes and returns rows
15858
+ * matching the optional filters (city, price range, min beds/baths/sqft, status) — real price,
15859
+ * beds/baths, square footage, an availability date and, where the listing has it enabled,
15860
+ * Arbor's own NterNow self-guided-tour booking link.
15861
+ */
15862
+ searchHomes(filters?: SearchHomesFilters): Promise<ArborHome[]>;
15863
+
15864
+ /**
15865
+ * Reads one Arbor Homes listing by the `uniqueName` id `searchHomes` returns — the same row,
15866
+ * for a caller that already picked a home and wants its detail-page URL and self-tour link
15867
+ * without re-filtering the whole search.
15868
+ */
15869
+ getHome(uniqueName: string): Promise<ArborHome>;
15870
+ }
15871
+ }
15872
+
14387
15873
  declare namespace BowmarkFamily_shopify_store {
14388
15874
  // ── Shopify storefronts — the unit's own declarations, verbatim ──
14389
15875
  interface ShopifyVariant {
@@ -14431,8 +15917,8 @@ interface SaleEvidence {
14431
15917
  /** The published "was" price. Strictly greater than currentPrice when
14432
15918
  * evidenceType is "compare_at_price". Null when nothing published one. */
14433
15919
  originalPrice: string | null;
14434
- /** ISO 4217, or null. Null on the REST catalogue door, which publishes no
14435
- * currencyreported honestly rather than assumed to be USD. */
15920
+ /** ISO 4217, from the storefront's own /meta.json. Null only when that read
15921
+ * failednever defaulted to "USD", which is wrong on every non-US store. */
14436
15922
  currency: string | null;
14437
15923
  promotionMessage: string | null;
14438
15924
  /** How it was decided. "compare_at_price" is a struck-through price;
@@ -14461,6 +15947,11 @@ interface PublishedProductAttributes {
14461
15947
  sleeveLength: string | null;
14462
15948
  rise: string | null;
14463
15949
  waistband: string | null;
15950
+ /** How long the GARMENT is — "Cropped", "Midi". What every store's own
15951
+ * `length::` tag fills, on a top exactly as on a bottom. */
15952
+ garmentLength: string | null;
15953
+ /** The inside leg seam and only that. NULL on a top — a tank has no inseam,
15954
+ * and its length is `garmentLength`. */
14464
15955
  inseam: string | null;
14465
15956
  legShape: string | null;
14466
15957
  fit: string | null;
@@ -14479,8 +15970,14 @@ interface CoordinationMetadata {
14479
15970
  productFamily: string | null;
14480
15971
  }
14481
15972
  /** An EXPLICIT retailer-published relationship. Shared colour, fabric,
14482
- * collection or family is NOT this — that is CoordinationMetadata. Usually [];
14483
- * the catalogue door carries no set tags on any store measured. */
15973
+ * collection or family is NOT this — that is CoordinationMetadata. Usually [].
15974
+ *
15975
+ * Two doors fill it. On a PRODUCT row it comes from the store's tags, and no
15976
+ * store measured publishes a set tag, so it is [] there. getSetEvidence() reads
15977
+ * the other one: the complementary products a MERCHANDISER pinned by hand,
15978
+ * admitted only for rows the store marks pr_prod_strat=pinned. The algorithmic
15979
+ * "related products" feed is never read into this — that is a recommendation
15980
+ * engine's output, not the retailer stating a pairing. */
14484
15981
  interface RetailerSetEvidence {
14485
15982
  evidenceType: "official_set" | "shop_the_set" | "complete_the_look" | "matching_piece";
14486
15983
  evidenceText: string | null;
@@ -14488,6 +15985,48 @@ interface RetailerSetEvidence {
14488
15985
  setId: string | null;
14489
15986
  relatedProducts: Array<{ productId: string | null; handle: string | null; title: string | null; url: string | null }>;
14490
15987
  }
15988
+ /** What getSetEvidence returns. An OBJECT rather than a bare array so the
15989
+ * healthy EMPTY answer is still probeable: productId and sourceUrl exist only
15990
+ * when BOTH hops answered, where an empty evidence list is the ordinary case. */
15991
+ interface ShopifySetEvidence {
15992
+ handle: string;
15993
+ /** Shopify's numeric PRODUCT id — the only key the recommendations door takes,
15994
+ * and published by no other function here. */
15995
+ productId: string;
15996
+ /** The product page the pairing is published on. */
15997
+ sourceUrl: string;
15998
+ /** ONLY the rows a merchandiser pinned by hand. [] when they pinned nothing,
15999
+ * which is the common case and is the STORE's answer. At most one entry — one
16000
+ * statement, N related products. Read this for "what did the retailer SAY". */
16001
+ evidence: RetailerSetEvidence[];
16002
+ /** EVERY row the store recommends, pinned AND algorithmic, deduplicated, each
16003
+ * labelled. Read source.by before treating one as the retailer's decision —
16004
+ * the algorithmic rows are usually SUBSTITUTES rather than companions, since
16005
+ * similarity returns the nearest product and the nearest thing to a baby
16006
+ * monitor is another baby monitor. [] when includeAlgorithmic was false. */
16007
+ recommendations: RecommendedProduct[];
16008
+ /** Non-empty when the store returned a FULL page for an intent, which cannot be
16009
+ * told apart from a longer list cut off at the cap. A merchandiser's pairing is
16010
+ * a statement, so a partial one must not read as the whole. */
16011
+ warnings: string[];
16012
+ }
16013
+ /** One recommended product, with the store's own label for who chose it. */
16014
+ interface RecommendedProduct {
16015
+ productId: string | null;
16016
+ handle: string | null;
16017
+ title: string | null;
16018
+ url: string | null;
16019
+ source: RecommendationSource;
16020
+ }
16021
+ interface RecommendationSource {
16022
+ /** "retailer" when a merchandiser pinned it; "algorithm" otherwise, INCLUDING
16023
+ * a row the store labelled with nothing — an unknown provenance must never
16024
+ * read as a person's decision. */
16025
+ by: "retailer" | "algorithm";
16026
+ /** The store's own token, verbatim and unmapped — "pinned", "jac" (Jaccard),
16027
+ * "e" (embedding), "collection_fallback". Null when the row carried none. */
16028
+ strategy: string | null;
16029
+ }
14491
16030
  interface ShopifyProduct {
14492
16031
  handle: string;
14493
16032
  title: string;
@@ -14502,13 +16041,64 @@ interface ShopifyProduct {
14502
16041
  descriptionHtml: string | null;
14503
16042
  /** The same copy with its markup removed. */
14504
16043
  descriptionText: string | null;
16044
+ /** ISO 4217, read once per store from its own /meta.json. */
14505
16045
  currency: string | null;
16046
+ /** When the store's door ANSWERED this row, ISO 8601 UTC. Every field here is
16047
+ * a live fact with a shelf life — the price, the markdown, the per-variant
16048
+ * stock flag — so read it before treating a cached row as current. Stamped per
16049
+ * REQUEST: a getProducts batch carries one stamp per handle, not one per call. */
16050
+ fetchedAt: string;
14506
16051
  /** Every image the door published, deduplicated, in the store's own order. */
14507
16052
  images: ProductImage[];
14508
16053
  attributes: PublishedProductAttributes;
16054
+ /** Per-FIELD origin for `attributes` — keyed by the same field names. Read it
16055
+ * before ranking on a null: "absent" is the store publishing nothing, and is
16056
+ * the store's own answer; "unreachable" is a door we could not read, and means
16057
+ * UNKNOWN. On this store both doors are one request that either answered or
16058
+ * threw, so nothing here is ever "unreachable" — the status exists because the
16059
+ * same vocabulary is used by providers whose page can refuse mid-answer. */
16060
+ attributeProvenance: Record<string, FieldProvenance>;
16061
+ attributeCompleteness: Completeness;
14509
16062
  coordination: CoordinationMetadata;
14510
16063
  retailerSetEvidence: RetailerSetEvidence[];
14511
16064
  }
16065
+ /** Where one attribute value came from, and the retailer text behind it. */
16066
+ interface FieldProvenance {
16067
+ /** "published" — the retailer stated it. "absent" — every door was silent.
16068
+ * "unreachable" — a door that would carry it was refused, so it is UNKNOWN. */
16069
+ status: "published" | "absent" | "unreachable";
16070
+ /** Which door: "shopify_tags", "shopify_product_type", "shopify_color_option"
16071
+ * or "shopify_product_copy". Null when nothing filled it. */
16072
+ source: string | null;
16073
+ /** The retailer's own words the value rests on, verbatim — the tag, or the
16074
+ * sentence out of the description. Null when nothing filled it. */
16075
+ evidence: string | null;
16076
+ /** On "unreachable" only: what was refused. */
16077
+ detail?: string;
16078
+ }
16079
+ /** The roll-up over one product's attributeProvenance. */
16080
+ interface Completeness {
16081
+ fields: number;
16082
+ published: number;
16083
+ absent: number;
16084
+ unreachable: number;
16085
+ /** published / fields, to 3dp. */
16086
+ ratio: number;
16087
+ /** The fields whose value is UNKNOWN rather than known-empty. Read this before
16088
+ * comparing two rows: a row with entries here was not fully looked at. */
16089
+ unreachableFields: string[];
16090
+ sourcesUsed: string[];
16091
+ }
16092
+ /** What getProducts returns. PARTIAL by design: one handle the store will not
16093
+ * serve costs that row and nothing else, where getProduct throws. */
16094
+ interface ShopifyProductBatch {
16095
+ /** In the order the handles were passed, not the order they finished. */
16096
+ products: ShopifyProduct[];
16097
+ /** Every handle the store did not serve, with what it said. */
16098
+ missing: Array<{ handle: string; detail: string }>;
16099
+ requested: number;
16100
+ warnings: string[];
16101
+ }
14512
16102
  interface ShopifyCartLine {
14513
16103
  /** Shopify's own line key, which its cart-change endpoints address a line by. */
14514
16104
  lineKey: string;
@@ -14544,6 +16134,46 @@ interface ShopifyCollectionProducts {
14544
16134
  * top-then-bottom; reading a pairing out of that order is the caller's
14545
16135
  * inference, never this provider's claim. [] is an ordinary answer. */
14546
16136
  products: ShopifyProduct[];
16137
+ /** Pass back as opts.cursor for the next page, or NULL when this is the last
16138
+ * one. A collection bigger than one page is reachable only through this. */
16139
+ cursor: string | null;
16140
+ /** Empty on an ordinary page. One entry when the walk hit the store platform's
16141
+ * 25,000-row ceiling with the collection unfinished — a TRUNCATION, which a
16142
+ * null cursor on its own would read as the end of the list. */
16143
+ warnings: string[];
16144
+ }
16145
+ /** One page of a whole-catalogue walk. Advance it with the cursor; there is
16146
+ * deliberately no "fetch everything" call, because every row is a request
16147
+ * against the store and only the caller knows how many candidates it needs. */
16148
+ interface ShopifyProductPage {
16149
+ /** In the store's own MERCHANDISED order — not id, not date. The store may
16150
+ * re-merchandise mid-walk, so key on handle rather than assuming pages are
16151
+ * disjoint. */
16152
+ products: ShopifyProduct[];
16153
+ /** Pass back as opts.cursor for the next page. NULL when the store answered a
16154
+ * short page, which is what the end of the catalogue looks like. */
16155
+ cursor: string | null;
16156
+ /** How many rows this page asked the store for. */
16157
+ limit: number;
16158
+ /** Empty on an ordinary page. One entry when the walk stopped at the 25,000-row
16159
+ * ceiling with the catalogue unfinished. */
16160
+ warnings: string[];
16161
+ }
16162
+ /** What resolveProductUrl hands back — the product a url names, and the variant
16163
+ * its own ?variant= selected. */
16164
+ interface ShopifyProductFromUrl {
16165
+ product: ShopifyProduct;
16166
+ /** The variant ?variant= named, or NULL when the url named none — the ordinary
16167
+ * case for a link off a collection page. Also null when it named one the store
16168
+ * no longer publishes, which warnings says. NEVER the first variant instead:
16169
+ * that answers "is my size in stock" about a different size. */
16170
+ variant: ShopifyVariant | null;
16171
+ /** The ?variant= value exactly as the url carried it, kept even when it
16172
+ * matched nothing — a stale link is a fact about the link. */
16173
+ variantIdInUrl: string | null;
16174
+ /** Empty on a clean resolve. One entry when the url named a variant the store
16175
+ * no longer publishes. */
16176
+ warnings: string[];
14547
16177
  }
14548
16178
  interface ShopifyCart {
14549
16179
  /** The store's own cart token — a bearer credential, so treat it like one. */
@@ -14559,8 +16189,8 @@ interface ShopifyCart {
14559
16189
 
14560
16190
  /**
14561
16191
  * OSMUND OLSEN — Every Shopify storefront, reached by its own name. One engine over the
14562
- * platform's two published surfaces — the store's own MCP server at /api/mcp for search, and
14563
- * the keyless Ajax storefront JSON for products and the cart.
16192
+ * platform's two published surfaces — the store's own UCP MCP server at /api/ucp/mcp for
16193
+ * search, and the keyless Ajax storefront JSON for products and the cart.
14564
16194
  */
14565
16195
  interface Unit {
14566
16196
  /**
@@ -14572,10 +16202,45 @@ interface ShopifyCart {
14572
16202
 
14573
16203
  /**
14574
16204
  * Reads one product by handle — every variant, its exact price, its SKU and whether that
14575
- * specific size or colour is purchasable right now.
16205
+ * specific size or colour is purchasable right now. Pass { withReviews: true } to ALSO get the
16206
+ * star rating and review count from whichever review app the merchant installed; it is off by
16207
+ * default because it costs a second origin and usually the rendered product page too.
14576
16208
  */
14577
16209
  getProduct(handle: string): Promise<ShopifyProduct>;
14578
16210
 
16211
+ /**
16212
+ * Turns a product URL into the product, which is the address a caller actually holds when a
16213
+ * link arrives from a search result, a page or a person. Takes the whole url — origin, market
16214
+ * prefix, ?variant= and #fragment — so nothing has to be stripped down to a bare handle first,
16215
+ * and the variant the url named comes back beside the product instead of being lost. THROWS,
16216
+ * naming the domain, on a url belonging to another storefront. Takes the same { withReviews:
16217
+ * true } option as getProduct, on the same default: a url is another way of naming one
16218
+ * product, so holding a link rather than a handle must not cost a caller the rating.
16219
+ */
16220
+ resolveProductUrl(url: string): Promise<ShopifyProductFromUrl>;
16221
+
16222
+ /**
16223
+ * Reads FULL detail for many products in one call — the shape for ranking a candidate set,
16224
+ * since a search row carries neither the description copy nor the per-variant stock a ranking
16225
+ * turns on. PARTIAL by construction: a search row's handle may 404 on the Ajax product door
16226
+ * (measured 2026-08-05, 2 of 10 sampled members), so one bad handle is named in `missing` and
16227
+ * costs that row alone, where `getProduct` throws and takes the whole set with it. Capped at
16228
+ * 50 handles because each one is a request to the store. Takes the same { withReviews: true }
16229
+ * option, and is the shape to use for it: the review app's key is learned from the first pages
16230
+ * and reused, so ratings for twenty handles cost a handful of page fetches rather than twenty.
16231
+ */
16232
+ getProducts(handles: string[]): Promise<ShopifyProductBatch>;
16233
+
16234
+ /**
16235
+ * Walks the store's WHOLE catalogue a page at a time, in its own merchandised order — the
16236
+ * shape that makes a realistic candidate set reachable at all, since search ranks against a
16237
+ * query and returns one slice. The caller advances a cursor and stops on its own budget or on
16238
+ * a null cursor. There is deliberately no fetch-everything call: every row is a request
16239
+ * against a stranger's storefront, and how many candidates a ranking needs is the caller's
16240
+ * decision rather than one taken once, inside the library, on behalf of every member.
16241
+ */
16242
+ listProducts(opts?: { limit?: number; cursor?: string | null }): Promise<ShopifyProductPage>;
16243
+
14579
16244
  /**
14580
16245
  * Lists the store's own merchandised collections. THIS is where a retailer states a SET: a
14581
16246
  * collection the store itself named "Matching Sets" or "Activewear Sets" carries setLike:
@@ -14588,7 +16253,18 @@ interface ShopifyCart {
14588
16253
  * rows. An empty list is an ordinary answer — several named 'look' collections publish no
14589
16254
  * products through this door.
14590
16255
  */
14591
- getCollection(handle: string, opts?: { limit?: number }): Promise<ShopifyCollectionProducts>;
16256
+ getCollection(handle: string, opts?: { limit?: number; cursor?: string | null }): Promise<ShopifyCollectionProducts>;
16257
+
16258
+ /**
16259
+ * Two answers in one call. `evidence` is ONLY what a MERCHANDISER pinned by hand, in the order
16260
+ * they typed it — an explicit retailer statement, and [] on most products, which is the
16261
+ * retailer's own answer. `recommendations` is EVERY row the store returns including the
16262
+ * algorithmic ones, each carrying source.by (retailer | algorithm) and the store's own
16263
+ * strategy token, so a caller can use them without either field lying. The algorithmic rows
16264
+ * are usually SUBSTITUTES rather than companions. Pass includeAlgorithmic: false to skip the
16265
+ * second request.
16266
+ */
16267
+ getSetEvidence(handle: string, opts?: { includeAlgorithmic?: boolean }): Promise<ShopifySetEvidence>;
14592
16268
 
14593
16269
  /**
14594
16270
  * Puts variants into THIS run's own cart on the store and returns the cart the store reports
@@ -14654,8 +16330,8 @@ interface SaleEvidence {
14654
16330
  /** The published "was" price. Strictly greater than currentPrice when
14655
16331
  * evidenceType is "compare_at_price". Null when nothing published one. */
14656
16332
  originalPrice: string | null;
14657
- /** ISO 4217, or null. Null on the REST catalogue door, which publishes no
14658
- * currencyreported honestly rather than assumed to be USD. */
16333
+ /** ISO 4217, from the storefront's own /meta.json. Null only when that read
16334
+ * failednever defaulted to "USD", which is wrong on every non-US store. */
14659
16335
  currency: string | null;
14660
16336
  promotionMessage: string | null;
14661
16337
  /** How it was decided. "compare_at_price" is a struck-through price;
@@ -14684,6 +16360,11 @@ interface PublishedProductAttributes {
14684
16360
  sleeveLength: string | null;
14685
16361
  rise: string | null;
14686
16362
  waistband: string | null;
16363
+ /** How long the GARMENT is — "Cropped", "Midi". What every store's own
16364
+ * `length::` tag fills, on a top exactly as on a bottom. */
16365
+ garmentLength: string | null;
16366
+ /** The inside leg seam and only that. NULL on a top — a tank has no inseam,
16367
+ * and its length is `garmentLength`. */
14687
16368
  inseam: string | null;
14688
16369
  legShape: string | null;
14689
16370
  fit: string | null;
@@ -14702,8 +16383,14 @@ interface CoordinationMetadata {
14702
16383
  productFamily: string | null;
14703
16384
  }
14704
16385
  /** An EXPLICIT retailer-published relationship. Shared colour, fabric,
14705
- * collection or family is NOT this — that is CoordinationMetadata. Usually [];
14706
- * the catalogue door carries no set tags on any store measured. */
16386
+ * collection or family is NOT this — that is CoordinationMetadata. Usually [].
16387
+ *
16388
+ * Two doors fill it. On a PRODUCT row it comes from the store's tags, and no
16389
+ * store measured publishes a set tag, so it is [] there. getSetEvidence() reads
16390
+ * the other one: the complementary products a MERCHANDISER pinned by hand,
16391
+ * admitted only for rows the store marks pr_prod_strat=pinned. The algorithmic
16392
+ * "related products" feed is never read into this — that is a recommendation
16393
+ * engine's output, not the retailer stating a pairing. */
14707
16394
  interface RetailerSetEvidence {
14708
16395
  evidenceType: "official_set" | "shop_the_set" | "complete_the_look" | "matching_piece";
14709
16396
  evidenceText: string | null;
@@ -14711,6 +16398,48 @@ interface RetailerSetEvidence {
14711
16398
  setId: string | null;
14712
16399
  relatedProducts: Array<{ productId: string | null; handle: string | null; title: string | null; url: string | null }>;
14713
16400
  }
16401
+ /** What getSetEvidence returns. An OBJECT rather than a bare array so the
16402
+ * healthy EMPTY answer is still probeable: productId and sourceUrl exist only
16403
+ * when BOTH hops answered, where an empty evidence list is the ordinary case. */
16404
+ interface ShopifySetEvidence {
16405
+ handle: string;
16406
+ /** Shopify's numeric PRODUCT id — the only key the recommendations door takes,
16407
+ * and published by no other function here. */
16408
+ productId: string;
16409
+ /** The product page the pairing is published on. */
16410
+ sourceUrl: string;
16411
+ /** ONLY the rows a merchandiser pinned by hand. [] when they pinned nothing,
16412
+ * which is the common case and is the STORE's answer. At most one entry — one
16413
+ * statement, N related products. Read this for "what did the retailer SAY". */
16414
+ evidence: RetailerSetEvidence[];
16415
+ /** EVERY row the store recommends, pinned AND algorithmic, deduplicated, each
16416
+ * labelled. Read source.by before treating one as the retailer's decision —
16417
+ * the algorithmic rows are usually SUBSTITUTES rather than companions, since
16418
+ * similarity returns the nearest product and the nearest thing to a baby
16419
+ * monitor is another baby monitor. [] when includeAlgorithmic was false. */
16420
+ recommendations: RecommendedProduct[];
16421
+ /** Non-empty when the store returned a FULL page for an intent, which cannot be
16422
+ * told apart from a longer list cut off at the cap. A merchandiser's pairing is
16423
+ * a statement, so a partial one must not read as the whole. */
16424
+ warnings: string[];
16425
+ }
16426
+ /** One recommended product, with the store's own label for who chose it. */
16427
+ interface RecommendedProduct {
16428
+ productId: string | null;
16429
+ handle: string | null;
16430
+ title: string | null;
16431
+ url: string | null;
16432
+ source: RecommendationSource;
16433
+ }
16434
+ interface RecommendationSource {
16435
+ /** "retailer" when a merchandiser pinned it; "algorithm" otherwise, INCLUDING
16436
+ * a row the store labelled with nothing — an unknown provenance must never
16437
+ * read as a person's decision. */
16438
+ by: "retailer" | "algorithm";
16439
+ /** The store's own token, verbatim and unmapped — "pinned", "jac" (Jaccard),
16440
+ * "e" (embedding), "collection_fallback". Null when the row carried none. */
16441
+ strategy: string | null;
16442
+ }
14714
16443
  interface ShopifyProduct {
14715
16444
  handle: string;
14716
16445
  title: string;
@@ -14725,13 +16454,64 @@ interface ShopifyProduct {
14725
16454
  descriptionHtml: string | null;
14726
16455
  /** The same copy with its markup removed. */
14727
16456
  descriptionText: string | null;
16457
+ /** ISO 4217, read once per store from its own /meta.json. */
14728
16458
  currency: string | null;
16459
+ /** When the store's door ANSWERED this row, ISO 8601 UTC. Every field here is
16460
+ * a live fact with a shelf life — the price, the markdown, the per-variant
16461
+ * stock flag — so read it before treating a cached row as current. Stamped per
16462
+ * REQUEST: a getProducts batch carries one stamp per handle, not one per call. */
16463
+ fetchedAt: string;
14729
16464
  /** Every image the door published, deduplicated, in the store's own order. */
14730
16465
  images: ProductImage[];
14731
16466
  attributes: PublishedProductAttributes;
16467
+ /** Per-FIELD origin for `attributes` — keyed by the same field names. Read it
16468
+ * before ranking on a null: "absent" is the store publishing nothing, and is
16469
+ * the store's own answer; "unreachable" is a door we could not read, and means
16470
+ * UNKNOWN. On this store both doors are one request that either answered or
16471
+ * threw, so nothing here is ever "unreachable" — the status exists because the
16472
+ * same vocabulary is used by providers whose page can refuse mid-answer. */
16473
+ attributeProvenance: Record<string, FieldProvenance>;
16474
+ attributeCompleteness: Completeness;
14732
16475
  coordination: CoordinationMetadata;
14733
16476
  retailerSetEvidence: RetailerSetEvidence[];
14734
16477
  }
16478
+ /** Where one attribute value came from, and the retailer text behind it. */
16479
+ interface FieldProvenance {
16480
+ /** "published" — the retailer stated it. "absent" — every door was silent.
16481
+ * "unreachable" — a door that would carry it was refused, so it is UNKNOWN. */
16482
+ status: "published" | "absent" | "unreachable";
16483
+ /** Which door: "shopify_tags", "shopify_product_type", "shopify_color_option"
16484
+ * or "shopify_product_copy". Null when nothing filled it. */
16485
+ source: string | null;
16486
+ /** The retailer's own words the value rests on, verbatim — the tag, or the
16487
+ * sentence out of the description. Null when nothing filled it. */
16488
+ evidence: string | null;
16489
+ /** On "unreachable" only: what was refused. */
16490
+ detail?: string;
16491
+ }
16492
+ /** The roll-up over one product's attributeProvenance. */
16493
+ interface Completeness {
16494
+ fields: number;
16495
+ published: number;
16496
+ absent: number;
16497
+ unreachable: number;
16498
+ /** published / fields, to 3dp. */
16499
+ ratio: number;
16500
+ /** The fields whose value is UNKNOWN rather than known-empty. Read this before
16501
+ * comparing two rows: a row with entries here was not fully looked at. */
16502
+ unreachableFields: string[];
16503
+ sourcesUsed: string[];
16504
+ }
16505
+ /** What getProducts returns. PARTIAL by design: one handle the store will not
16506
+ * serve costs that row and nothing else, where getProduct throws. */
16507
+ interface ShopifyProductBatch {
16508
+ /** In the order the handles were passed, not the order they finished. */
16509
+ products: ShopifyProduct[];
16510
+ /** Every handle the store did not serve, with what it said. */
16511
+ missing: Array<{ handle: string; detail: string }>;
16512
+ requested: number;
16513
+ warnings: string[];
16514
+ }
14735
16515
  interface ShopifyCartLine {
14736
16516
  /** Shopify's own line key, which its cart-change endpoints address a line by. */
14737
16517
  lineKey: string;
@@ -14767,6 +16547,46 @@ interface ShopifyCollectionProducts {
14767
16547
  * top-then-bottom; reading a pairing out of that order is the caller's
14768
16548
  * inference, never this provider's claim. [] is an ordinary answer. */
14769
16549
  products: ShopifyProduct[];
16550
+ /** Pass back as opts.cursor for the next page, or NULL when this is the last
16551
+ * one. A collection bigger than one page is reachable only through this. */
16552
+ cursor: string | null;
16553
+ /** Empty on an ordinary page. One entry when the walk hit the store platform's
16554
+ * 25,000-row ceiling with the collection unfinished — a TRUNCATION, which a
16555
+ * null cursor on its own would read as the end of the list. */
16556
+ warnings: string[];
16557
+ }
16558
+ /** One page of a whole-catalogue walk. Advance it with the cursor; there is
16559
+ * deliberately no "fetch everything" call, because every row is a request
16560
+ * against the store and only the caller knows how many candidates it needs. */
16561
+ interface ShopifyProductPage {
16562
+ /** In the store's own MERCHANDISED order — not id, not date. The store may
16563
+ * re-merchandise mid-walk, so key on handle rather than assuming pages are
16564
+ * disjoint. */
16565
+ products: ShopifyProduct[];
16566
+ /** Pass back as opts.cursor for the next page. NULL when the store answered a
16567
+ * short page, which is what the end of the catalogue looks like. */
16568
+ cursor: string | null;
16569
+ /** How many rows this page asked the store for. */
16570
+ limit: number;
16571
+ /** Empty on an ordinary page. One entry when the walk stopped at the 25,000-row
16572
+ * ceiling with the catalogue unfinished. */
16573
+ warnings: string[];
16574
+ }
16575
+ /** What resolveProductUrl hands back — the product a url names, and the variant
16576
+ * its own ?variant= selected. */
16577
+ interface ShopifyProductFromUrl {
16578
+ product: ShopifyProduct;
16579
+ /** The variant ?variant= named, or NULL when the url named none — the ordinary
16580
+ * case for a link off a collection page. Also null when it named one the store
16581
+ * no longer publishes, which warnings says. NEVER the first variant instead:
16582
+ * that answers "is my size in stock" about a different size. */
16583
+ variant: ShopifyVariant | null;
16584
+ /** The ?variant= value exactly as the url carried it, kept even when it
16585
+ * matched nothing — a stale link is a fact about the link. */
16586
+ variantIdInUrl: string | null;
16587
+ /** Empty on a clean resolve. One entry when the url named a variant the store
16588
+ * no longer publishes. */
16589
+ warnings: string[];
14770
16590
  }
14771
16591
  interface ShopifyCart {
14772
16592
  /** The store's own cart token — a bearer credential, so treat it like one. */
@@ -14782,8 +16602,8 @@ interface ShopifyCart {
14782
16602
 
14783
16603
  /**
14784
16604
  * friedrikdev — Every Shopify storefront, reached by its own name. One engine over the
14785
- * platform's two published surfaces — the store's own MCP server at /api/mcp for search, and
14786
- * the keyless Ajax storefront JSON for products and the cart.
16605
+ * platform's two published surfaces — the store's own UCP MCP server at /api/ucp/mcp for
16606
+ * search, and the keyless Ajax storefront JSON for products and the cart.
14787
16607
  */
14788
16608
  interface Unit {
14789
16609
  /**
@@ -14795,10 +16615,45 @@ interface ShopifyCart {
14795
16615
 
14796
16616
  /**
14797
16617
  * Reads one product by handle — every variant, its exact price, its SKU and whether that
14798
- * specific size or colour is purchasable right now.
16618
+ * specific size or colour is purchasable right now. Pass { withReviews: true } to ALSO get the
16619
+ * star rating and review count from whichever review app the merchant installed; it is off by
16620
+ * default because it costs a second origin and usually the rendered product page too.
14799
16621
  */
14800
16622
  getProduct(handle: string): Promise<ShopifyProduct>;
14801
16623
 
16624
+ /**
16625
+ * Turns a product URL into the product, which is the address a caller actually holds when a
16626
+ * link arrives from a search result, a page or a person. Takes the whole url — origin, market
16627
+ * prefix, ?variant= and #fragment — so nothing has to be stripped down to a bare handle first,
16628
+ * and the variant the url named comes back beside the product instead of being lost. THROWS,
16629
+ * naming the domain, on a url belonging to another storefront. Takes the same { withReviews:
16630
+ * true } option as getProduct, on the same default: a url is another way of naming one
16631
+ * product, so holding a link rather than a handle must not cost a caller the rating.
16632
+ */
16633
+ resolveProductUrl(url: string): Promise<ShopifyProductFromUrl>;
16634
+
16635
+ /**
16636
+ * Reads FULL detail for many products in one call — the shape for ranking a candidate set,
16637
+ * since a search row carries neither the description copy nor the per-variant stock a ranking
16638
+ * turns on. PARTIAL by construction: a search row's handle may 404 on the Ajax product door
16639
+ * (measured 2026-08-05, 2 of 10 sampled members), so one bad handle is named in `missing` and
16640
+ * costs that row alone, where `getProduct` throws and takes the whole set with it. Capped at
16641
+ * 50 handles because each one is a request to the store. Takes the same { withReviews: true }
16642
+ * option, and is the shape to use for it: the review app's key is learned from the first pages
16643
+ * and reused, so ratings for twenty handles cost a handful of page fetches rather than twenty.
16644
+ */
16645
+ getProducts(handles: string[]): Promise<ShopifyProductBatch>;
16646
+
16647
+ /**
16648
+ * Walks the store's WHOLE catalogue a page at a time, in its own merchandised order — the
16649
+ * shape that makes a realistic candidate set reachable at all, since search ranks against a
16650
+ * query and returns one slice. The caller advances a cursor and stops on its own budget or on
16651
+ * a null cursor. There is deliberately no fetch-everything call: every row is a request
16652
+ * against a stranger's storefront, and how many candidates a ranking needs is the caller's
16653
+ * decision rather than one taken once, inside the library, on behalf of every member.
16654
+ */
16655
+ listProducts(opts?: { limit?: number; cursor?: string | null }): Promise<ShopifyProductPage>;
16656
+
14802
16657
  /**
14803
16658
  * Lists the store's own merchandised collections. THIS is where a retailer states a SET: a
14804
16659
  * collection the store itself named "Matching Sets" or "Activewear Sets" carries setLike:
@@ -14811,7 +16666,18 @@ interface ShopifyCart {
14811
16666
  * rows. An empty list is an ordinary answer — several named 'look' collections publish no
14812
16667
  * products through this door.
14813
16668
  */
14814
- getCollection(handle: string, opts?: { limit?: number }): Promise<ShopifyCollectionProducts>;
16669
+ getCollection(handle: string, opts?: { limit?: number; cursor?: string | null }): Promise<ShopifyCollectionProducts>;
16670
+
16671
+ /**
16672
+ * Two answers in one call. `evidence` is ONLY what a MERCHANDISER pinned by hand, in the order
16673
+ * they typed it — an explicit retailer statement, and [] on most products, which is the
16674
+ * retailer's own answer. `recommendations` is EVERY row the store returns including the
16675
+ * algorithmic ones, each carrying source.by (retailer | algorithm) and the store's own
16676
+ * strategy token, so a caller can use them without either field lying. The algorithmic rows
16677
+ * are usually SUBSTITUTES rather than companions. Pass includeAlgorithmic: false to skip the
16678
+ * second request.
16679
+ */
16680
+ getSetEvidence(handle: string, opts?: { includeAlgorithmic?: boolean }): Promise<ShopifySetEvidence>;
14815
16681
  }
14816
16682
  }
14817
16683
 
@@ -14823,20 +16689,26 @@ interface ShopifyCart {
14823
16689
  interface BowmarkProviders {
14824
16690
  aa: BowmarkProvider_aa.Unit;
14825
16691
  abercrombie: BowmarkProvider_abercrombie.Unit;
16692
+ aiper: BowmarkProvider_aiper.Unit;
16693
+ ajmadison: BowmarkProvider_ajmadison.Unit;
14826
16694
  ashleyfurniture: BowmarkProvider_ashleyfurniture.Unit;
16695
+ atlasseniorliving: BowmarkProvider_atlasseniorliving.Unit;
14827
16696
  avis: BowmarkProvider_avis.Unit;
14828
16697
  azure: BowmarkProvider_azure.Unit;
14829
16698
  barletta: BowmarkProvider_barletta.Unit;
14830
16699
  bhphoto: BowmarkProvider_bhphoto.Unit;
16700
+ bigrentz: BowmarkProvider_bigrentz.Unit;
14831
16701
  blenderseyewear: BowmarkProvider_blenderseyewear.Unit;
14832
16702
  bluehaven: BowmarkProvider_bluehaven.Unit;
14833
16703
  bmwusa: BowmarkProvider_bmwusa.Unit;
16704
+ boydsleep: BowmarkProvider_boydsleep.Unit;
14834
16705
  bykoket: BowmarkProvider_bykoket.Unit;
14835
16706
  cancer: BowmarkProvider_cancer.Unit;
14836
16707
  caraway: BowmarkProvider_caraway.Unit;
14837
16708
  cars: BowmarkProvider_cars.Unit;
14838
16709
  cheapflights: BowmarkProvider_cheapflights.Unit;
14839
16710
  chriscraft: BowmarkProvider_chriscraft.Unit;
16711
+ classichome: BowmarkProvider_classichome.Unit;
14840
16712
  classpass: BowmarkProvider_classpass.Unit;
14841
16713
  cloudflare: BowmarkProvider_cloudflare.Unit;
14842
16714
  cyberpowerpc: BowmarkProvider_cyberpowerpc.Unit;
@@ -14845,7 +16717,9 @@ interface BowmarkProviders {
14845
16717
  dickssportinggoods: BowmarkProvider_dickssportinggoods.Unit;
14846
16718
  dillards: BowmarkProvider_dillards.Unit;
14847
16719
  discounttire: BowmarkProvider_discounttire.Unit;
16720
+ embroker: BowmarkProvider_embroker.Unit;
14848
16721
  erieinsurance: BowmarkProvider_erieinsurance.Unit;
16722
+ eventsource: BowmarkProvider_eventsource.Unit;
14849
16723
  extraspace: BowmarkProvider_extraspace.Unit;
14850
16724
  firstdibs: BowmarkProvider_firstdibs.Unit;
14851
16725
  flightradar24: BowmarkProvider_flightradar24.Unit;
@@ -14854,22 +16728,32 @@ interface BowmarkProviders {
14854
16728
  fred: BowmarkProvider_fred.Unit;
14855
16729
  geico: BowmarkProvider_geico.Unit;
14856
16730
  google_flights: BowmarkProvider_google_flights.Unit;
16731
+ gotchacovered: BowmarkProvider_gotchacovered.Unit;
14857
16732
  grainger: BowmarkProvider_grainger.Unit;
16733
+ grandwelcome: BowmarkProvider_grandwelcome.Unit;
16734
+ handypro: BowmarkProvider_handypro.Unit;
16735
+ harmar: BowmarkProvider_harmar.Unit;
14858
16736
  hauslabs: BowmarkProvider_hauslabs.Unit;
14859
16737
  healthcare_gov: BowmarkProvider_healthcare_gov.Unit;
14860
16738
  hellofresh: BowmarkProvider_hellofresh.Unit;
14861
16739
  hellotend: BowmarkProvider_hellotend.Unit;
14862
16740
  hilton: BowmarkProvider_hilton.Unit;
16741
+ hobie: BowmarkProvider_hobie.Unit;
14863
16742
  hunter: BowmarkProvider_hunter.Unit;
14864
16743
  ibuypower: BowmarkProvider_ibuypower.Unit;
14865
16744
  insurify: BowmarkProvider_insurify.Unit;
14866
16745
  interiordefine: BowmarkProvider_interiordefine.Unit;
16746
+ islllc: BowmarkProvider_islllc.Unit;
16747
+ jennikayne: BowmarkProvider_jennikayne.Unit;
14867
16748
  joybird: BowmarkProvider_joybird.Unit;
14868
16749
  kayak: BowmarkProvider_kayak.Unit;
16750
+ kitchentuneup: BowmarkProvider_kitchentuneup.Unit;
16751
+ kompan: BowmarkProvider_kompan.Unit;
14869
16752
  labcorp: BowmarkProvider_labcorp.Unit;
14870
16753
  linkedin: BowmarkProvider_linkedin.Unit;
14871
16754
  liquiddeath: BowmarkProvider_liquiddeath.Unit;
14872
16755
  lonelyplanet: BowmarkProvider_lonelyplanet.Unit;
16756
+ louvershop: BowmarkProvider_louvershop.Unit;
14873
16757
  lufthansa: BowmarkProvider_lufthansa.Unit;
14874
16758
  lululemon: BowmarkProvider_lululemon.Unit;
14875
16759
  maidenhome: BowmarkProvider_maidenhome.Unit;
@@ -14895,6 +16779,7 @@ interface BowmarkProviders {
14895
16779
  prose: BowmarkProvider_prose.Unit;
14896
16780
  reddit: BowmarkProvider_reddit.Unit;
14897
16781
  ritani: BowmarkProvider_ritani.Unit;
16782
+ roofmaxx: BowmarkProvider_roofmaxx.Unit;
14898
16783
  samsclub: BowmarkProvider_samsclub.Unit;
14899
16784
  sears: BowmarkProvider_sears.Unit;
14900
16785
  seegarsfence: BowmarkProvider_seegarsfence.Unit;
@@ -14904,18 +16789,25 @@ interface BowmarkProviders {
14904
16789
  statefarm: BowmarkProvider_statefarm.Unit;
14905
16790
  stickergiant: BowmarkProvider_stickergiant.Unit;
14906
16791
  sunhomesaunas: BowmarkProvider_sunhomesaunas.Unit;
16792
+ tamarackidaho: BowmarkProvider_tamarackidaho.Unit;
14907
16793
  target: BowmarkProvider_target.Unit;
16794
+ tatcha: BowmarkProvider_tatcha.Unit;
14908
16795
  teladoc: BowmarkProvider_teladoc.Unit;
14909
- tentree: BowmarkProvider_tentree.Unit;
14910
16796
  therabody: BowmarkProvider_therabody.Unit;
14911
16797
  thezebra: BowmarkProvider_thezebra.Unit;
14912
16798
  topviewtix: BowmarkProvider_topviewtix.Unit;
14913
16799
  trektravel: BowmarkProvider_trektravel.Unit;
16800
+ twiddy: BowmarkProvider_twiddy.Unit;
14914
16801
  ulrichlifestyle: BowmarkProvider_ulrichlifestyle.Unit;
16802
+ vervecoffee: BowmarkProvider_vervecoffee.Unit;
14915
16803
  viewrail: BowmarkProvider_viewrail.Unit;
16804
+ villagerealtyobx: BowmarkProvider_villagerealtyobx.Unit;
14916
16805
  visible: BowmarkProvider_visible.Unit;
16806
+ voluspa: BowmarkProvider_voluspa.Unit;
14917
16807
  walmart: BowmarkProvider_walmart.Unit;
14918
16808
  wellfound: BowmarkProvider_wellfound.Unit;
16809
+ xpresswellnessurgentcare: BowmarkProvider_xpresswellnessurgentcare.Unit;
16810
+ yourarborhome: BowmarkProvider_yourarborhome.Unit;
14919
16811
  "000de82": BowmarkFamily_shopify_store.Unit;
14920
16812
  "001r3iv0": BowmarkFamily_shopify_store.Unit;
14921
16813
  "00246d8e": BowmarkFamily_shopify_store.Unit;
@@ -51946,6 +53838,7 @@ interface BowmarkProviders {
51946
53838
  santabarbaraforgeandiron: BowmarkFamily_shopify_store.Unit;
51947
53839
  santabarbaranutrients: BowmarkFamily_shopify_store.Unit;
51948
53840
  santaclararealtorstore: BowmarkFamily_shopify_store.Unit;
53841
+ santacruzbicycles: BowmarkFamily_shopify_store.Unit;
51949
53842
  santacruzmountainsclothing: BowmarkFamily_shopify_store.Unit;
51950
53843
  santafesoapranch: BowmarkFamily_shopify_store.Unit;
51951
53844
  santafewineandchilefiesta: BowmarkFamily_shopify_store.Unit;
@@ -56835,6 +58728,7 @@ interface BowmarkProviders {
56835
58728
  tentarte: BowmarkFamily_shopify_store.Unit;
56836
58729
  tenthavenuenorthshop: BowmarkFamily_shopify_store.Unit;
56837
58730
  tenthpine: BowmarkFamily_shopify_store.Unit;
58731
+ tentree: BowmarkFamily_shopify_store.Unit;
56838
58732
  teoapparel: BowmarkFamily_shopify_store.Unit;
56839
58733
  teopanzolcobarcelonnette: BowmarkFamily_shopify_store.Unit;
56840
58734
  tepawines: BowmarkFamily_shopify_store.Unit;
@@ -66645,5 +68539,6 @@ interface BowmarkLibrary {
66645
68539
  music: BowmarkCapability_music.Unit;
66646
68540
  pcparts: BowmarkCapability_pcparts.Unit;
66647
68541
  read: BowmarkCapability_read.Unit;
68542
+ sheds: BowmarkCapability_sheds.Unit;
66648
68543
  providers: BowmarkProviders;
66649
68544
  }