@bowmark/web 1.4.0 → 1.6.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: 6368edcbec9d9ee7ceb3fd590c7054ade0542a93e43a39f4f88dc6167c0e36da
9
- // 8 capabilities, 74 providers, 233 typed functions, 20 refused.
10
- // 51,712 family members, sharing 2 interface(s) — declared once and pointed at, never repeated per member.
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.
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
@@ -959,10 +959,87 @@ interface aaRetrieveBookingArgs {
959
959
  lastName: string;
960
960
  }
961
961
 
962
+ interface aaBaggageAllowanceArgs {
963
+ /** The country flown FROM — an ISO-3166 alpha-2 code ("US", "GB") or a country
964
+ * name in any capitalisation. Not an airport code: American publishes bag fees
965
+ * by region and its regions are lists of countries, and no surface on its
966
+ * estate resolves an airport to one. */
967
+ origin: string;
968
+ /** The country flown TO, same forms. */
969
+ destination: string;
970
+ }
971
+
972
+ interface aaBaggageAllowance {
973
+ origin: aaBaggageEndpoint;
974
+ destination: aaBaggageEndpoint;
975
+ /** Which row of American's fee table this trip landed on, and how. */
976
+ feeRegion: {
977
+ label: string;
978
+ matchedOn: "country" | "region" | "region-members";
979
+ matchedEndpoint: "origin" | "destination";
980
+ };
981
+ checkedBagFees: aaCheckedBagFee[];
982
+ checkedBagLimits: aaCheckedBagLimits;
983
+ carryOn: aaCarryOnAllowance;
984
+ freeCheckedBags: aaFreeCheckedBagRule[];
985
+ /** Null when American's own bag-count rule names neither end of the trip. */
986
+ maxCheckedBags: number | null;
987
+ maxCheckedBagsRules: aaMaxCheckedBagsRule[];
988
+ footnotes: string[];
989
+ sources: string[];
990
+ }
991
+
992
+ interface aaBaggageEndpoint {
993
+ input: string;
994
+ countryCode: string;
995
+ countryName: string;
996
+ /** Null for a country American files under no bag region — Mexico is the live
997
+ * case, and the fee table names it directly instead. */
998
+ region: string | null;
999
+ }
1000
+
1001
+ interface aaCheckedBagFee {
1002
+ /** "1", "2", "3", "4+". */
1003
+ bag: string;
1004
+ /** The cell verbatim, e.g. "$0 / $85*". */
1005
+ display: string;
1006
+ /** Every dollar figure in the cell, in the order printed. */
1007
+ amountsUsd: number[];
1008
+ footnoteMarkers: string[];
1009
+ }
1010
+
1011
+ interface aaCheckedBagLimits {
1012
+ maxLinearInches: number | null;
1013
+ maxLinearCm: number | null;
1014
+ maxWeightPounds: number | null;
1015
+ maxWeightKilos: number | null;
1016
+ notes: string[];
1017
+ }
1018
+
1019
+ interface aaCarryOnAllowance {
1020
+ carryOnBags: number;
1021
+ personalItems: number;
1022
+ carryOnMaxInches: number[];
1023
+ carryOnMaxCm: number[];
1024
+ personalItemMaxInches: number[];
1025
+ personalItemMaxCm: number[];
1026
+ }
1027
+
1028
+ interface aaFreeCheckedBagRule {
1029
+ bags: number;
1030
+ qualifiers: string[];
1031
+ }
1032
+
1033
+ interface aaMaxCheckedBagsRule {
1034
+ count: number;
1035
+ applies: string[];
1036
+ }
1037
+
962
1038
  /**
963
1039
  * American Airlines' own site — its published fares and award availability, flight status,
964
- * reservation lookup, seat maps, baggage allowance and fee schedules. Flight status and
965
- * reservation lookup are live and browserless; the rest are declared stubs.
1040
+ * reservation lookup, seat maps, baggage allowance and fee schedules. Flight status,
1041
+ * reservation lookup and the published baggage allowance for a route are live and browserless;
1042
+ * the rest are declared stubs.
966
1043
  */
967
1044
  interface Unit {
968
1045
  // UNTYPED, DELIBERATELY OMITTED — `getFlightStatus({ date, flightNumber, origin, destination })` declares no types for
@@ -970,6 +1047,30 @@ interface aaRetrieveBookingArgs {
970
1047
  // It is CALLABLE at runtime; `bowmark.providers.aa.getFlightStatus` is a compile error here on purpose.
971
1048
  // A `(...args: unknown[])` stand-in would compile and tell you nothing.
972
1049
 
1050
+ /**
1051
+ * American Airlines' published baggage allowance and fees for a ROUTE. `origin` and
1052
+ * `destination` are COUNTRIES — an ISO-3166 alpha-2 code ("US", "GB") or a country name
1053
+ * ("United Kingdom"), matched against American's own country list — because American prices
1054
+ * bags by REGION and publishes its regions as lists of countries ("Bag fees are based on these
1055
+ * regions"). An IATA airport code is refused with a message saying so rather than guessed at.
1056
+ * Returns the fee row American's own table lands that trip on (which region, and whether it
1057
+ * matched on the country or its region), the first, second, third and fourth-bag prices with
1058
+ * every dollar figure printed in each cell plus its footnote markers, the checked-bag weight
1059
+ * and size limits (50 lbs / 23 kgs, 62 in / 158 cm at the time of writing, with First/Business
1060
+ * and Australia/New Zealand qualifications in `notes`), the carry-on and personal-item
1061
+ * dimensions, the free-checked-bag entitlements by AAdvantage status, cabin and cardholder
1062
+ * rule, how many bags American will accept on that trip at all, and the table's own footnotes
1063
+ * verbatim. HONEST LIMITS, because they decide what this can be used for: a cell like "$0 /
1064
+ * $85*" is TWO published prices and the footnotes say which of them a given fare and status
1065
+ * pays — this function returns both rather than picking, since American's public pages do not
1066
+ * price an individual ticket and no open surface on aa.com does either. It throws rather than
1067
+ * guess for a trip where neither end is in American's domestic band (every row of the table
1068
+ * describes the other end of such a trip), and for Cuba, which American prices from two
1069
+ * separate direction-of-travel tables this function deliberately does not read as if they were
1070
+ * the same one.
1071
+ */
1072
+ getBaggageAllowance(arg0: aaBaggageAllowanceArgs): Promise<aaBaggageAllowance>;
1073
+
973
1074
  /**
974
1075
  * Reads an existing American Airlines reservation by its six-letter record locator (PNR) and
975
1076
  * the passenger's last name — nothing is signed into, and both are the caller's own details,
@@ -1337,6 +1438,79 @@ interface AshleyFurnitureStore {
1337
1438
  }
1338
1439
  }
1339
1440
 
1441
+ declare namespace BowmarkProvider_avis {
1442
+ // ── Avis — the unit's own declarations, verbatim ──
1443
+ interface avisRow {
1444
+ id: string;
1445
+ }
1446
+
1447
+ interface AvisLocationRow {
1448
+ mnemonic: string;
1449
+ name: string;
1450
+ group: string;
1451
+ address: {
1452
+ line1: string;
1453
+ line2: string | null;
1454
+ city: string;
1455
+ stateCode: string | null;
1456
+ postalCode: string | null;
1457
+ countryCode: string | null;
1458
+ countryName: string | null;
1459
+ };
1460
+ phone: string | null;
1461
+ latitude: number | null;
1462
+ longitude: number | null;
1463
+ drivableDistanceMiles: number | null;
1464
+ is24hoursDropOffAvailable: boolean;
1465
+ isKeyDropLocation: boolean;
1466
+ relPath: string | null;
1467
+ }
1468
+
1469
+ interface AvisLocationDetail extends AvisLocationRow {
1470
+ hoursOfOperation: {
1471
+ dayOfWeek: number;
1472
+ day: "SUNDAY" | "MONDAY" | "TUESDAY" | "WEDNESDAY" | "THURSDAY" | "FRIDAY" | "SATURDAY";
1473
+ intervals: { openMinute: number; closeMinute: number }[];
1474
+ isClosed: boolean;
1475
+ }[];
1476
+ holidays: { scheduleName: string; date: string }[];
1477
+ associatedLocation: { mnemonic: string | null; name: string | null } | null;
1478
+ isCorporate: boolean;
1479
+ isSelfServiceKiosk: boolean;
1480
+ isFreePickup: boolean;
1481
+ isTruck: boolean;
1482
+ isAvisFirstLocation: boolean;
1483
+ maxLengthOfRental: number | null;
1484
+ locationVehicleCategory: string | null;
1485
+ }
1486
+
1487
+ /**
1488
+ * Car rental — availability search, existing-reservation lookup and location directory on
1489
+ * avis.com. searchLocations and getLocation are live; the rest are stubs.
1490
+ */
1491
+ interface Unit {
1492
+ /**
1493
+ * Finds Avis rental locations matching a full city name or an airport code (`query`, e.g.
1494
+ * "Chicago" or "ORD" — an exact token match, not a substring or address search) off the site's
1495
+ * own location-search API, optionally narrowed to one US state (`stateCode`). Returns each
1496
+ * match's station code, display name, site grouping (airport, neighbourhood, city dock, …),
1497
+ * address, phone and coordinates. Empty array on no match, never an error.
1498
+ */
1499
+ searchLocations(args: object): Promise<AvisLocationRow[]>;
1500
+
1501
+ /**
1502
+ * Reads one Avis rental location in full off the site's own location-search API for a station
1503
+ * code (`mnemonic`, e.g. "ORD"). For an airport code, `cityName` is optional and the mnemonic
1504
+ * itself is used; for a non-airport mnemonic the caller must pass the city from a prior
1505
+ * `searchLocations` row. Returns the row's address, phone, latitude/longitude, opening hours
1506
+ * per day (with split shifts that wrap midnight), the holiday schedule, the after-hours
1507
+ * sibling (`associatedLocation`), and the full set of service flags (24h drop-off, key drop,
1508
+ * self-service kiosk, corporate, free pickup, truck, Avis First).
1509
+ */
1510
+ getLocation(args: object): Promise<AvisLocationDetail>;
1511
+ }
1512
+ }
1513
+
1340
1514
  declare namespace BowmarkProvider_azure {
1341
1515
  // ── Microsoft Azure — the unit's own declarations, verbatim ──
1342
1516
  interface AzurePriceRow {
@@ -1684,6 +1858,57 @@ interface BlendersEyewearPriceResult {
1684
1858
  }
1685
1859
  }
1686
1860
 
1861
+ declare namespace BowmarkProvider_bluehaven {
1862
+ // ── Blue Haven Pools & Spas — the unit's own declarations, verbatim ──
1863
+ interface BluehavenPoolDesign {
1864
+ id: number;
1865
+ name: string;
1866
+ category: string;
1867
+ subCategory: string | null;
1868
+ }
1869
+
1870
+ interface BluehavenSiteFeasibility {
1871
+ matchedAddress: string;
1872
+ coordinates: { lat: number; lng: number };
1873
+ apn: string | null;
1874
+ ownerName: string | null;
1875
+ lotAreaSqFt: number | null;
1876
+ existingStructures: unknown[];
1877
+ nearbyUtilityLines: { name: string; features: unknown[] }[];
1878
+ warnings: string[];
1879
+ }
1880
+
1881
+ /**
1882
+ * Blue Haven Pools & Spas' own Canibuild site-planning widget — sited lot feasibility for a
1883
+ * real US address (parcel area, existing structures, nearby utility lines) and their live
1884
+ * inground pool design catalog.
1885
+ */
1886
+ interface Unit {
1887
+ /**
1888
+ * Reads Blue Haven's own live inground pool design catalog off their site-planning widget's
1889
+ * API — every design set (e.g. Oasis, Omega, Oval, Pacific, Rectangle) under every
1890
+ * category/subcategory they currently sell (Pool Studios, Blue Haven Pools, Freeform Pools).
1891
+ * Real catalog data, not a marketing page scrape.
1892
+ */
1893
+ listPoolDesigns(): Promise<BluehavenPoolDesign[]>;
1894
+
1895
+ /**
1896
+ * Runs a US street address through Blue Haven's own site-planning tool the way their homepage
1897
+ * widget does — resolves the address, then reads back the parcel's own lot area, APN/owner
1898
+ * (when on file), any structures the site already has recorded on that parcel, and
1899
+ * utility-line hazards (electrical, oil/gas) near it. This is the address-SITED data ChatGPT's
1900
+ * own knowledge cannot produce (confirmed in this packet's ANGLE fit-check: asked to site a
1901
+ * pool at a real address, it asked the user to upload yard photos or offered a rough satellite
1902
+ * guess, and quoted a national price range instead of anything tied to the parcel). Only
1903
+ * addresses that resolve through Blue Haven's own parcel index carry sited data (most US
1904
+ * residential/commercial street addresses do); a handful of well-known landmark addresses
1905
+ * resolve only to a generic map pin and throw `BluehavenBadRequest`, same as an address with
1906
+ * no match at all.
1907
+ */
1908
+ checkPoolSiteFeasibility(args: { address: string }): Promise<BluehavenSiteFeasibility>;
1909
+ }
1910
+ }
1911
+
1687
1912
  declare namespace BowmarkProvider_bmwusa {
1688
1913
  // ── BMW USA — the unit's own declarations, verbatim ──
1689
1914
  interface BmwusaBuiltVehicleOption {
@@ -1740,6 +1965,84 @@ interface BmwusaCpoSearchOptions {
1740
1965
  maxOdometer?: number;
1741
1966
  }
1742
1967
 
1968
+ interface BmwusaModelTrim {
1969
+ name: string;
1970
+ modelCode: string | null;
1971
+ zeroToSixty: number | null;
1972
+ horsepower: number | null;
1973
+ startingMsrp: number | null;
1974
+ engineType: string | null;
1975
+ drivetrain: string | null;
1976
+ transmission: string | null;
1977
+ fuelType: string | null;
1978
+ fuelEfficiency: { city: number | null; highway: number | null; combined: number | null; unit: string } | null;
1979
+ seatingCapacity: number | null;
1980
+ }
1981
+
1982
+ interface BmwusaModel {
1983
+ name: string;
1984
+ series: string;
1985
+ url: string;
1986
+ trims: BmwusaModelTrim[];
1987
+ }
1988
+
1989
+ interface BmwusaOfferTier {
1990
+ apr: number;
1991
+ months: number;
1992
+ }
1993
+
1994
+ interface BmwusaLeaseOffer {
1995
+ code: string;
1996
+ description: string;
1997
+ monthlyPayment: number;
1998
+ term: number;
1999
+ msrp: number;
2000
+ downPayment: number;
2001
+ acquisitionFee: number;
2002
+ dueAtSigningExceptNy: number | null;
2003
+ loyaltyCredit: number | null;
2004
+ dealerContribution: string | null;
2005
+ allowedMiles: number | null;
2006
+ chargePerExcessMile: number | null;
2007
+ endOfTermPurchaseOption: number | null;
2008
+ startDate: string;
2009
+ endDate: string;
2010
+ }
2011
+
2012
+ interface BmwusaFinanceOffer {
2013
+ code: string;
2014
+ description: string;
2015
+ tiers: BmwusaOfferTier[];
2016
+ loyaltyCredit: number | null;
2017
+ startDate: string;
2018
+ endDate: string;
2019
+ }
2020
+
2021
+ interface BmwusaOffer {
2022
+ modelCode: string;
2023
+ modelName: string;
2024
+ series: string;
2025
+ bodyStyle: string;
2026
+ msrp: number;
2027
+ lease: BmwusaLeaseOffer | null;
2028
+ finance: BmwusaFinanceOffer | null;
2029
+ }
2030
+
2031
+ interface BmwusaOffersResult {
2032
+ region: string;
2033
+ offers: BmwusaOffer[];
2034
+ }
2035
+
2036
+ interface BmwusaModelListing {
2037
+ name: string;
2038
+ url: string;
2039
+ bodyStyle: string | null;
2040
+ powertrain: "electric" | "plugInHybrid" | "performance" | "gasoline" | null;
2041
+ msrpFrom: number | null;
2042
+ msrpTo: number | null;
2043
+ trimCount: number;
2044
+ }
2045
+
1743
2046
  /**
1744
2047
  * BMW US car shopping: the Build Your Own configurator and its option pricing, live VIN-level
1745
2048
  * new and Certified Pre-Owned dealer inventory near a ZIP, the model lineup with trims and
@@ -1766,6 +2069,102 @@ interface BmwusaCpoSearchOptions {
1766
2069
  * buckets, not raw numbers, so this filters honestly rather than guessing bucket boundaries).
1767
2070
  */
1768
2071
  searchCertifiedPreOwned(zip: string, options?: { radius?: number; limit?: number; model?: string; minYear?: number; maxYear?: number; maxPrice?: number; maxOdometer?: number }): Promise<BmwusaCpoVehicle[]>;
2072
+
2073
+ /**
2074
+ * Reads one BMW model's body-style page (path is the segment of the site's own
2075
+ * /vehicles/...html URL, e.g. 'x-models/x5', '2-series/coupe' — read off bmwusa.com's own
2076
+ * navigation or sitemap.xml) and returns its series, model name, and every trim BMW currently
2077
+ * sells on that page: each trim's own name, its build-your-own model code (the same code
2078
+ * buildVehicle takes), 0-60 time, horsepower, starting MSRP (null when the site shows '--' —
2079
+ * not yet published), engine type, drivetrain, transmission, fuel type, fuel efficiency (MPG
2080
+ * or MPGe) and seating capacity.
2081
+ */
2082
+ getModel(path: string): Promise<BmwusaModel>;
2083
+
2084
+ /**
2085
+ * Lists BMW's current US lease and finance offers for a 5-digit ZIP code (resolved server-side
2086
+ * to a sales region, since the site's own offer objects carry per-region eligibility) — every
2087
+ * model with an active offer, each with its own lease (monthly payment, term, MSRP, down
2088
+ * payment, due-at-signing, allowed miles, loyalty credit) and/or finance (APR tiers, loyalty
2089
+ * credit) terms, exactly as bmwusa.com's own /special-offers.html widget resolves them.
2090
+ */
2091
+ listOffers(zip: string): Promise<BmwusaOffersResult>;
2092
+
2093
+ /**
2094
+ * Lists BMW's current US lineup — every model BMW sells, with its bmwusa.com model-overview
2095
+ * URL, body style, powertrain category (electric / plug-in hybrid / performance / gasoline)
2096
+ * and starting MSRP band — so an agent can resolve a person's vague 'a BMW SUV under $60k'
2097
+ * into the specific models that exist, with their real prices, before looking up any one of
2098
+ * them. Reads /all-bmws.html for the 49-card catalog, then fans out (concurrency 5) to each
2099
+ * model-overview page for MSRP; pages with no trim table (BMW iX, certain M models) still
2100
+ * appear in the result with null MSRPs and null body style rather than dropping the model.
2101
+ */
2102
+ listModels(): Promise<BmwusaModelListing[]>;
2103
+ }
2104
+ }
2105
+
2106
+ declare namespace BowmarkProvider_bykoket {
2107
+ // ── KOKET — the unit's own declarations, verbatim ──
2108
+ interface KoketProductSummary {
2109
+ id: string;
2110
+ name: string;
2111
+ url: string;
2112
+ price: number;
2113
+ currency: string;
2114
+ inStock: boolean;
2115
+ }
2116
+
2117
+ interface KoketProduct {
2118
+ id: string;
2119
+ name: string;
2120
+ url: string;
2121
+ reference: string;
2122
+ price: number;
2123
+ priceFormatted: string;
2124
+ listPrice: number;
2125
+ onSale: boolean;
2126
+ currency: string;
2127
+ inStock: boolean;
2128
+ quantityLeft: number | null;
2129
+ availabilityMessage: string;
2130
+ description: string;
2131
+ images: string[];
2132
+ }
2133
+
2134
+ interface KoketAddToCartHandoff {
2135
+ id: string;
2136
+ name: string;
2137
+ url: string;
2138
+ price: number;
2139
+ currency: string;
2140
+ inStock: boolean;
2141
+ note: string;
2142
+ }
2143
+
2144
+ /**
2145
+ * Reads KOKET's public furniture, lighting and textiles storefront (bykoket.com/shop) — search
2146
+ * the catalog, read a product's live price, stock and description, and get the handoff to add
2147
+ * it to cart on the real site.
2148
+ */
2149
+ interface Unit {
2150
+ /**
2151
+ * Searches KOKET's live public catalog (furniture, lighting, textiles) and returns each
2152
+ * match's id, name, product URL, price and stock status.
2153
+ */
2154
+ searchProducts(query: string): Promise<KoketProductSummary[]>;
2155
+
2156
+ /**
2157
+ * Reads one KOKET product's live page — price (list and current, since KOKET runs promotions),
2158
+ * stock count, availability message, description and images.
2159
+ */
2160
+ getProduct(idOrUrl: string): Promise<KoketProduct>;
2161
+
2162
+ /**
2163
+ * Hands back the shopper's own KOKET product page — the exact Add to cart button for this
2164
+ * product — since the site's cart requires a per-session token nobody but the shopper can
2165
+ * supply. Writes nothing.
2166
+ */
2167
+ addToCart(idOrUrl: string): Promise<KoketAddToCartHandoff>;
1769
2168
  }
1770
2169
  }
1771
2170
 
@@ -1803,12 +2202,38 @@ interface cancerCentersResult {
1803
2202
  centers: cancerCenterRow[];
1804
2203
  }
1805
2204
 
2205
+ type cancerInfoAudience = "patient" | "healthProfessional";
2206
+
2207
+ interface cancerInfoSection {
2208
+ /** The PDQ document's own heading, verbatim, e.g. "Stage Information for
2209
+ * Breast Cancer". */
2210
+ heading: string;
2211
+ /** The section's own text, whitespace-normalized. */
2212
+ text: string;
2213
+ }
2214
+
2215
+ interface cancerInfoSummaryResult {
2216
+ topic: string;
2217
+ audience: cancerInfoAudience;
2218
+ /** The PDQ document's own title, verbatim. */
2219
+ title: string;
2220
+ /** The summary's own page on cancer.gov. */
2221
+ url: string;
2222
+ /** ISO 8601 — the PDQ Editorial Board's own "Updated" date for this exact
2223
+ * document. PDQ is a living, continuously revised document; there is no
2224
+ * honest way to use this text without it. */
2225
+ revisionDate: string;
2226
+ sections: cancerInfoSection[];
2227
+ }
2228
+
1806
2229
  /**
1807
2230
  * The US National Cancer Institute: PDQ cancer information, the clinical-trial register,
1808
- * cancer drugs, NCI-designated cancer centers and the cancer dictionaries. The NCI-Designated
1809
- * Cancer Center directory (`findCancerCenters`) is callable now — every center's name,
1810
- * designation type, location and host institution, optionally filtered by state; the other
1811
- * twelve declared functions are still stubs.
2231
+ * cancer drugs, NCI-designated cancer centers and the cancer dictionaries. Callable now: the
2232
+ * NCI-Designated Cancer Center directory (`findCancerCenters`) — every center's name,
2233
+ * designation type, location and host institution, optionally filtered by state and
2234
+ * `getCancerInfoSummary` NCI's own PDQ information summary for a cancer topic, patient or
2235
+ * health-professional version, with its own revision date. The other eleven declared functions
2236
+ * are still stubs.
1812
2237
  */
1813
2238
  interface Unit {
1814
2239
  /**
@@ -1824,6 +2249,121 @@ interface cancerCentersResult {
1824
2249
  * — so `total` and `centers.length` are always equal.
1825
2250
  */
1826
2251
  findCancerCenters(args?: { state?: string }): Promise<cancerCentersResult>;
2252
+
2253
+ /**
2254
+ * NCI's own PDQ information summary for one cancer topic — what the cancer is, its symptoms
2255
+ * and risk factors, how it is diagnosed and staged, the treatment options by stage, and the
2256
+ * prognosis — split into the site's own headed sections, each with its heading and text.
2257
+ * `topic` is cancer.gov's own `/types` path segment (e.g. "breast", "lung", "prostate").
2258
+ * `audience` (default `"patient"`) selects the patient-facing version or the more technical
2259
+ * health-professional one NCI maintains separately; both carry the same `document-dates`
2260
+ * revision block when the topic publishes one. `revisionDate` (ISO 8601) is the PDQ Editorial
2261
+ * Board's own "Updated" date for the exact document returned — PDQ is continuously revised, so
2262
+ * this is not decoration. English only: the Spanish path for the same topic uses different
2263
+ * words, not a parameter substitution on the English slug (breast's HP Spanish page is
2264
+ * `/espanol/tipos/seno/pro/tratamiento-seno-pdq`, not a `breast`/`hp` swap), and reaching it
2265
+ * needs its own resolver over the Spanish `/espanol/tipos` index — unbuilt. Two ways this
2266
+ * throws instead of guessing: `CancerInfoSummaryNotPublishedError` when the topic+audience has
2267
+ * no single consolidated document (NCI is mid-redesign — breast's patient content was migrated
2268
+ * to a task-based hub with no one document or date; its health-professional content is
2269
+ * unaffected), and `CancerInfoSummaryAmbiguousTopicError` when the topic's own index entry
2270
+ * covers more than one genuinely distinct disease, each with its own summary (lung:
2271
+ * non-small-cell and small-cell are both filed under `/types/lung`) — the error names every
2272
+ * option's own URL rather than silently answering for the wrong one.
2273
+ */
2274
+ getCancerInfoSummary(args: { topic: string; audience?: "patient" | "healthProfessional" }): Promise<cancerInfoSummaryResult>;
2275
+ }
2276
+ }
2277
+
2278
+ declare namespace BowmarkProvider_caraway {
2279
+ // ── Caraway Home — the unit's own declarations, verbatim ──
2280
+ interface CarawayVariant {
2281
+ /** Shopify's numeric variant id as a string. */
2282
+ id: string;
2283
+ /** The variant's own label, e.g. "Cream" or "Default Title". */
2284
+ title: string;
2285
+ /** String verbatim from the storefront — "50.00" (dollars) on /products.json, "44500" (cents) on /products/<h>.js. */
2286
+ price: string;
2287
+ /** Same scale as price. Null when the product is not on sale. */
2288
+ compareAtPrice: string | null;
2289
+ /** The store's own SKU. Null on a product without one. */
2290
+ sku: string | null;
2291
+ /** Whether the variant is purchasable right now. */
2292
+ available: boolean;
2293
+ options: string[];
2294
+ }
2295
+ interface CarawayProduct {
2296
+ /** The handle is the only stable identifier across the catalogue. */
2297
+ handle: string;
2298
+ title: string;
2299
+ vendor: string;
2300
+ productType: string;
2301
+ url: string;
2302
+ descriptionHtml: string | null;
2303
+ optionNames: string[];
2304
+ variants: CarawayVariant[];
2305
+ /** Same scale as variants — see CarawayVariant.price. */
2306
+ priceRange: { min: string; max: string } | null;
2307
+ /** True if ANY variant is purchasable. */
2308
+ inStock: boolean;
2309
+ tags: string[];
2310
+ /** Caraway's own images, in the order the storefront publishes them. */
2311
+ images: string[];
2312
+ }
2313
+ interface CarawayCatalogue {
2314
+ /** All matching products, in-stock first, then by handle. */
2315
+ products: CarawayProduct[];
2316
+ /** What the filter DROPPED, in the same register the rest of the library uses. */
2317
+ warnings: string[];
2318
+ }
2319
+ interface CarawayQuizArchetype {
2320
+ /** The archetype slug (e.g. new-customer, 90s-baby). */
2321
+ slug: string;
2322
+ /** Caraway's own copy for the archetype. */
2323
+ label: string;
2324
+ /** Caraway's own one-line archetype blurb. */
2325
+ description: string;
2326
+ /** The product handles the quiz route marks as Recommended. */
2327
+ recommendedHandles: string[];
2328
+ }
2329
+ interface CarawayQuizResult {
2330
+ /** The archetype the quiz terminal page lands on, with the site copy. */
2331
+ archetype: CarawayQuizArchetype;
2332
+ /** The Recommended rail, in stock first. */
2333
+ recommended: CarawayProduct[];
2334
+ /** What the resolver DROPPED, in the same register the rest of the library uses. */
2335
+ warnings: string[];
2336
+ }
2337
+
2338
+ /**
2339
+ * Caraway Home product catalogue — every ceramic cookware piece, its variants, real prices and
2340
+ * stock — read off the live Shopify storefront, plus the buyer-archetype rail the Caraway Home
2341
+ * Quiz terminal renders.
2342
+ */
2343
+ interface Unit {
2344
+ /**
2345
+ * Reads the live Caraway catalogue as Caraway publishes it — every product, its handle, title,
2346
+ * vendor, description, tags, images and the per-variant price the storefront is quoting right
2347
+ * now. Returns [] on a transport failure. The catalog page is the line and the parse is the
2348
+ * unit of work.
2349
+ */
2350
+ listCarawayProducts(opts?: { limit?: number }): Promise<CarawayProduct[]>;
2351
+
2352
+ /**
2353
+ * Reads one product by its handle — every variant, its exact price, the image the storefront
2354
+ * is showing and whether that specific variant is purchasable right now. Takes the handle
2355
+ * listCarawayProducts returns. THROWS on an unknown handle (the store answers a real 404).
2356
+ */
2357
+ getCarawayProduct(handle: string): Promise<CarawayProduct>;
2358
+
2359
+ /**
2360
+ * Routes a quiz's buyer-fit answers to a Caraway archetype and resolves the Recommended rail
2361
+ * the quiz terminal page renders. The archetype slug comes from the quiz's terminal URL
2362
+ * (new-customer, 90s-baby, etc.) and the rail is the live catalogue filtered to the products
2363
+ * Caraway marks for that buyer. THROWS on an unknown archetype — the supported set is encoded
2364
+ * inside the function and surfaced via the same module that owns the catalogue.
2365
+ */
2366
+ runCarawayQuiz(answers: { archetype: string }): Promise<CarawayQuizResult>;
1827
2367
  }
1828
2368
  }
1829
2369
 
@@ -1847,6 +2387,15 @@ interface carsListing {
1847
2387
  hotCar: boolean | null;
1848
2388
  dealer: { name: string | null; status: string | null } | null;
1849
2389
  }
2390
+ interface carsSearch {
2391
+ appliedFilters: { filter: string; value: string | null }[];
2392
+ totalListings: number;
2393
+ totalPages: number;
2394
+ page: number;
2395
+ pageSize: number;
2396
+ sort: string | null;
2397
+ listingIds: string[];
2398
+ }
1850
2399
  interface carsModelResearch {
1851
2400
  year: number;
1852
2401
  make: string;
@@ -1862,14 +2411,41 @@ interface carsModelResearch {
1862
2411
  expertReview: { headline: string; pros: string[]; cons: string[] } | null;
1863
2412
  whatsNew: string | null;
1864
2413
  }
2414
+ interface QuoteIdentity {
2415
+ firstName: string;
2416
+ lastName: string;
2417
+ dob: string;
2418
+ email: string;
2419
+ phone: string;
2420
+ }
2421
+ interface carsVehicleValue {
2422
+ offerCode: string;
2423
+ dealer: { name: string | null; zipCode: string | null } | null;
2424
+ tradeInOffer: number | null;
2425
+ privatePartyValue: number | null;
2426
+ marketLabel: string | null;
2427
+ mileageUsed: number | null;
2428
+ warnings: string[];
2429
+ }
1865
2430
 
1866
2431
  /**
1867
2432
  * Cars.com — the US new/used/certified car marketplace: for-sale inventory with dealer asking
1868
2433
  * prices, one listing's full detail, a valuation for a car you already own, and per-model
1869
- * research (trims, specs, expert and owner reviews). Two functions are built: reading a single
1870
- * listing in full by its id, and one model year's research overview.
2434
+ * research (trims, specs, expert and owner reviews). Three functions are built: searching the
2435
+ * inventory, reading one listing in full, and reading one year/make/model's research overview.
2436
+ * A fourth — the cash-offer valuation — is built too: callers pass a VIN, a ZIP, and the
2437
+ * caller-supplied identity the 2026-07-31 quote-flow ruling requires, and the function returns
2438
+ * the trade-in offer and private-party value perseus published for the assigned local dealer.
1871
2439
  */
1872
2440
  interface Unit {
2441
+ /**
2442
+ * Searches Cars.com's live for-sale inventory the way its own shopping results page does — by
2443
+ * ZIP and radius, new / used / certified-pre-owned, make, model, price, mileage — and returns
2444
+ * the matching listing ids (each one is a getListing argument verbatim), the total match count
2445
+ * across all pages, and the filter set the service actually applied.
2446
+ */
2447
+ search(args: { zipCode?: string; radiusMiles?: number; stockType?: 'new' | 'used' | 'cpo'; make?: string; model?: string; maxPrice?: string; minPrice?: string; maxMileage?: string; page?: number; pageSize?: number; sort?: string }): Promise<carsSearch>;
2448
+
1873
2449
  /**
1874
2450
  * Reads one cars.com listing in full by its id (the uuid in a /vehicledetail/<id>/ url): VIN,
1875
2451
  * asking price, mileage, year/make/model, stock number, CPO status, EPA highway mpg, the
@@ -1884,6 +2460,17 @@ interface carsModelResearch {
1884
2460
  * year — null/absent exactly where cars.com's own page shows nothing for it.
1885
2461
  */
1886
2462
  getModelResearch(args: { make: string; model: string; year: number }): Promise<carsModelResearch>;
2463
+
2464
+ /**
2465
+ * Reads Cars.com's own cash-offer valuation for a car the caller already owns: the trade-in
2466
+ * offer and the private-party value perseus computed for the dealer's assigned ZIP, with the
2467
+ * dealer and mileage the offer was scoped to. Identity is required (caller-supplied, per the
2468
+ * 2026-07-31 quote-flow ruling) so perseus has a person to assign the offer record to. The
2469
+ * function NEVER calls contactDealer, optinDealer, acceptByCode, smsPictureRequest or
2470
+ * media.create — the contact routes the 2026-08-06 standing decision names as the fence for a
2471
+ * cash-offer appraisal.
2472
+ */
2473
+ getVehicleValue(args: { vin: string; identity: QuoteIdentity; postalCode: string; mileage?: number }): Promise<carsVehicleValue>;
1887
2474
  }
1888
2475
  }
1889
2476
 
@@ -2232,6 +2819,32 @@ interface ClasspassScheduleOptions {
2232
2819
  days?: number;
2233
2820
  }
2234
2821
 
2822
+ interface ClasspassSearchQuery {
2823
+ /** Centre of the search, decimal degrees. */
2824
+ lat: number;
2825
+ lon: number;
2826
+ /** Search radius (default 1, clamped to 1-50). */
2827
+ radius: number;
2828
+ /** "mi" (default) or "km". */
2829
+ radiusUnits?: "mi" | "km";
2830
+ /** First day, YYYY-MM-DD. Defaults to TODAY (UTC date). */
2831
+ date?: string;
2832
+ /** Opaque page token from a previous result's `cursor`. */
2833
+ cursor?: string;
2834
+ }
2835
+
2836
+ interface ClasspassSearchResult {
2837
+ results: ClasspassVenue[];
2838
+ /** Opaque page token. Pass back as `query.cursor`; null when the last page is reached. */
2839
+ cursor: string | null;
2840
+ /** The origin's own session id — stable across pages of one search. */
2841
+ searchId: string;
2842
+ /** Always null: the origin does not publish a total. */
2843
+ totalHits: number | null;
2844
+ /** What this function did to the caller's query (defaults applied). */
2845
+ warnings: string[];
2846
+ }
2847
+
2235
2848
  /**
2236
2849
  * ClassPass — fitness, wellness and beauty classes across gyms, studios, spas and salons.
2237
2850
  * `getStudio` reads one studio's whole profile in a single request: what it does, where it is,
@@ -2241,6 +2854,28 @@ interface ClasspassScheduleOptions {
2241
2854
  * search, per-slot availability and membership pricing are declared but not built yet.
2242
2855
  */
2243
2856
  interface Unit {
2857
+ /**
2858
+ * ClassPass's own location search — POST lat/lon/radius and read back the venues in range,
2859
+ * with their identity, address, coordinates, IANA time zone, the activities the venue teaches,
2860
+ * amenities, ratings, distance and the practical details a person needs to decide which to
2861
+ * open. `query.lat` and `query.lon` are required (decimal degrees, finite, in range);
2862
+ * `query.radius` defaults to 1 and is clamped to 1-50; `query.radiusUnits` is `mi` (default)
2863
+ * or `km`; `query.date` is `YYYY-MM-DD` and defaults to TODAY (UTC). Pagination: the response
2864
+ * carries `cursor` (the base64 page token) and `searchId`; pass `cursor` back verbatim as
2865
+ * `query.cursor` on the next call — the body's shape is identical. One call returns up to 50
2866
+ * venues; the origin does not publish a total count, so `totalHits` is always `null` and the
2867
+ * caller pages until `cursor` is also null. Returns `warnings` whenever the function did
2868
+ * anything to the caller's query (radius defaulted, date defaulted) so a caller rendering the
2869
+ * result knows exactly what shape their input landed in. Each venue block carries `activities`
2870
+ * populated (the search response's `schedules[].venue.activities` is a comma-joined string the
2871
+ * parser splits), which `getSchedule`'s venue block does NOT have on a day the studio
2872
+ * publishes nothing — a real difference, not an inconsistency. **`query` shape today:** only
2873
+ * lat/lon/radius/radiusUnits/date/cursor are honored. The help center's rich facets (text
2874
+ * search, activity filter, time-of-day, credit-price band, neighbourhood) are DECLARED on
2875
+ * `search` but NOT WIRED — see manifest `notImplemented`.
2876
+ */
2877
+ search(query: ClasspassSearchQuery): Promise<ClasspassSearchResult>;
2878
+
2244
2879
  /**
2245
2880
  * Reads ONE ClassPass studio's whole profile in a single request — the page a person reads to
2246
2881
  * decide whether a result is worth booking. `studio` is a ClassPass venue id (74359), the
@@ -2378,33 +3013,103 @@ interface CloudflareSearchDomainAvailabilityResult {
2378
3013
  }
2379
3014
  }
2380
3015
 
2381
- declare namespace BowmarkProvider_decked {
2382
- // ── DECKED — the unit's own declarations, verbatim ──
2383
- // DECKED's OWN shapes — not a capability contract.
2384
-
2385
- type DeckedCabSideOption = "Cab-side Gap" | "Load Floor";
2386
-
2387
- interface DeckedFit {
2388
- vehicleClass: string; // the site's own product handle, e.g. "drawers-fullsize"
2389
- vehicleClassTitle: string;
2390
- model: string; // e.g. "Ford F150 (2004-2014)"
2391
- fitOption: string | null; // a bed length or wheel base — null for a class with only "Model" (SUV, Service Body)
2392
- sku: string;
2393
- price: number;
2394
- priceFormatted: string;
2395
- available: boolean;
2396
- url: string; // the class's product page, preselecting this exact variant
2397
- }
2398
-
2399
- interface DeckedVehicleClass {
2400
- handle: string;
2401
- title: string;
3016
+ declare namespace BowmarkProvider_cyberpowerpc {
3017
+ // ── CyberPowerPC — the unit's own declarations, verbatim ──
3018
+ interface CyberpowerpcConfigurator {
3019
+ slug: string;
3020
+ name: string;
2402
3021
  url: string;
2403
- secondOption: string | null; // "Bed Length" | "Wheel Base" | null
2404
- fits: DeckedFit[];
3022
+ price: string | null;
3023
+ priceValue: number | null;
3024
+ listPrice: string | null;
3025
+ listPriceValue: number | null;
3026
+ baselineSpecs: string[];
2405
3027
  }
2406
-
2407
- interface DeckedFitmentResult {
3028
+ interface CyberpowerpcOption {
3029
+ id: string;
3030
+ name: string;
3031
+ sku: string | null;
3032
+ priceDifference: number;
3033
+ isDefault: boolean;
3034
+ }
3035
+ interface CyberpowerpcSection {
3036
+ code: string;
3037
+ label: string;
3038
+ category: "Core Components" | "Accessories" | "Software & Service";
3039
+ required: boolean;
3040
+ defaultOptionId: string | null;
3041
+ options: CyberpowerpcOption[];
3042
+ }
3043
+ interface CyberpowerpcCatalog {
3044
+ slug: string;
3045
+ title: string;
3046
+ basePrice: number;
3047
+ sections: CyberpowerpcSection[];
3048
+ }
3049
+ interface CyberpowerpcPriceResult {
3050
+ slug: string;
3051
+ basePrice: number;
3052
+ totalPrice: number;
3053
+ lines: { sectionCode: string; sectionLabel: string; optionId: string; optionName: string; priceDifference: number }[];
3054
+ }
3055
+
3056
+ /**
3057
+ * Reads and prices CyberPowerPC's real gaming-PC configurators — every component, every
3058
+ * option's exact price.
3059
+ */
3060
+ interface Unit {
3061
+ /**
3062
+ * Lists every base gaming-PC configurator CyberPowerPC currently sells — AMD and Intel,
3063
+ * Mainstream through Extreme — with its slug, current starting price, list price and stock
3064
+ * CPU/GPU/memory/motherboard/storage lines. Takes nothing. The slug it returns is what
3065
+ * getConfigurator and priceBuild take.
3066
+ */
3067
+ listConfigurators(): Promise<CyberpowerpcConfigurator[]>;
3068
+
3069
+ /**
3070
+ * Reads one base configurator's whole component tree — every section (CPU, GPU, memory,
3071
+ * chassis, storage, ...), every option's exact label, SKU and signed price difference versus
3072
+ * that section's default. The section codes and option ids it returns are what priceBuild
3073
+ * takes.
3074
+ */
3075
+ getConfigurator(slug: string): Promise<CyberpowerpcCatalog>;
3076
+
3077
+ /**
3078
+ * Prices an exact build for one configurator given a caller's part selections (one option id
3079
+ * per section code; any section left out uses its own default). Returns the real live total
3080
+ * the site's own configurator computes, plus a per-section breakdown of what each pick added.
3081
+ */
3082
+ priceBuild(slug: string, selections: Record<string, string>): Promise<CyberpowerpcPriceResult>;
3083
+ }
3084
+ }
3085
+
3086
+ declare namespace BowmarkProvider_decked {
3087
+ // ── DECKED — the unit's own declarations, verbatim ──
3088
+ // DECKED's OWN shapes — not a capability contract.
3089
+
3090
+ type DeckedCabSideOption = "Cab-side Gap" | "Load Floor";
3091
+
3092
+ interface DeckedFit {
3093
+ vehicleClass: string; // the site's own product handle, e.g. "drawers-fullsize"
3094
+ vehicleClassTitle: string;
3095
+ model: string; // e.g. "Ford F150 (2004-2014)"
3096
+ fitOption: string | null; // a bed length or wheel base — null for a class with only "Model" (SUV, Service Body)
3097
+ sku: string;
3098
+ price: number;
3099
+ priceFormatted: string;
3100
+ available: boolean;
3101
+ url: string; // the class's product page, preselecting this exact variant
3102
+ }
3103
+
3104
+ interface DeckedVehicleClass {
3105
+ handle: string;
3106
+ title: string;
3107
+ url: string;
3108
+ secondOption: string | null; // "Bed Length" | "Wheel Base" | null
3109
+ fits: DeckedFit[];
3110
+ }
3111
+
3112
+ interface DeckedFitmentResult {
2408
3113
  query: string;
2409
3114
  bedLength: string | null;
2410
3115
  matched: boolean;
@@ -2474,6 +3179,34 @@ interface DeckedCabSideOptionResult {
2474
3179
  }
2475
3180
  }
2476
3181
 
3182
+ declare namespace BowmarkProvider_dice {
3183
+ // ── Dice — the unit's own declarations, verbatim ──
3184
+ interface DiceJobDetails {
3185
+ jobId: string;
3186
+ description: string;
3187
+ skills: string[];
3188
+ warnings: string[];
3189
+ }
3190
+ interface diceRow {
3191
+ id: string;
3192
+ }
3193
+
3194
+ /**
3195
+ * Dice — the US technology-only job board. Reaches each posting's full description and skill
3196
+ * list through Dice's own keyless MCP server at mcp.dice.com/mcp; declares tech-job search,
3197
+ * posting-detail reads, employer profiles and a company's open roles.
3198
+ */
3199
+ interface Unit {
3200
+ /**
3201
+ * Returns one Dice posting in full — the HTML description (the same document the consumer page
3202
+ * renders) and the normalized skills array — by the job id `searchJobs` returns. THROWS on a
3203
+ * missing id, on a non-existent posting (MCP returns isError), and on a transport failure, so
3204
+ * a caller can distinguish "no such job" from "empty result set".
3205
+ */
3206
+ getJob(jobId: string): Promise<DiceJobDetails>;
3207
+ }
3208
+ }
3209
+
2477
3210
  declare namespace BowmarkProvider_dickssportinggoods {
2478
3211
  // ── DICK'S Sporting Goods — the unit's own declarations, verbatim ──
2479
3212
  interface dickssportinggoodsDayHours {
@@ -2655,6 +3388,28 @@ interface dillardsProduct {
2655
3388
  variants: dillardsProductVariant[];
2656
3389
  }
2657
3390
 
3391
+ interface dillardsStoreRow {
3392
+ storeNumber: string;
3393
+ name: string;
3394
+ address1: string | null;
3395
+ address2: string | null;
3396
+ city: string;
3397
+ state: string;
3398
+ stateCode: string;
3399
+ zip: string;
3400
+ phone: string;
3401
+ url: string;
3402
+ latitude: number | null;
3403
+ longitude: number | null;
3404
+ }
3405
+
3406
+ interface dillardsFindStoresQuery {
3407
+ state?: string;
3408
+ city?: string;
3409
+ zip?: string;
3410
+ limit?: number;
3411
+ }
3412
+
2658
3413
  /**
2659
3414
  * Dillard's department store catalog, store-level stock, store locator and wedding/gift
2660
3415
  * registry search.
@@ -2735,6 +3490,23 @@ interface dillardsProduct {
2735
3490
  * through to its item page rather than handing back an unusable list.
2736
3491
  */
2737
3492
  searchRegistry(query: dillardsRegistrySearchQuery): Promise<dillardsRegistry[]>;
3493
+
3494
+ /**
3495
+ * Finds nearby Dillard's store locations the way the site's own /stores locator does — every
3496
+ * row carrying its `storeNumber` (the 4-digit id `checkStock` accepts as its `store`
3497
+ * argument), mall/anchor `name`, `address1`/`address2`, `city`, full `state` and 2-letter
3498
+ * `stateCode`, 5-digit `zip`, 10-digit `phone`, the per-store detail `url`, and the site's own
3499
+ * `latitude`/`longitude` (null when the row omits either). Pass AT LEAST ONE of `state` (full
3500
+ * name like "Ohio" or 2-letter code like "OH" — an unknown state THROWS, naming the 30 the
3501
+ * site publishes), `city` (exact, case-insensitive match against the site's own `city` field —
3502
+ * a name that does not match returns `[]`), or `zip` (5-digit US ZIP, exact match — the site
3503
+ * publishes one store per ZIP today, so this is "the store at this ZIP" without needing a
3504
+ * centroid lookup). Multiple filters narrow; a `state`+`city` request is a per-state page plus
3505
+ * a client-side city filter. Pass `limit` to trim. A query with no filters THROWS, naming
3506
+ * every one the site supports — an empty-argument call would otherwise hand back the full
3507
+ * 272-store list with no way to tell whether that was what the caller meant.
3508
+ */
3509
+ findStores(query: dillardsFindStoresQuery): Promise<dillardsStoreRow[]>;
2738
3510
  }
2739
3511
  }
2740
3512
 
@@ -2751,6 +3523,21 @@ type DiscounttireLocation =
2751
3523
  | { zip: string }
2752
3524
  | { latitude: number; longitude: number };
2753
3525
 
3526
+ /** One tire or wheel, as the site's own product read returns it. Price is
3527
+ * global across stores (verified at three AZ stores on the same sku on the
3528
+ * same day, 2026-08-07), so `getProduct` takes no storeCode even though
3529
+ * productByCode itself requires one. */
3530
+ interface DiscounttireProduct {
3531
+ code: string;
3532
+ name: string | null;
3533
+ brand: string | null;
3534
+ size: string | null;
3535
+ productType: string | null;
3536
+ url: string | null;
3537
+ price: { value: number | null; formatted: string | null } | null;
3538
+ source: string;
3539
+ }
3540
+
2754
3541
  interface DiscounttireStoreRef {
2755
3542
  code: string;
2756
3543
  name: string | null;
@@ -2806,14 +3593,68 @@ interface DiscounttireStock {
2806
3593
  source: string;
2807
3594
  }
2808
3595
 
3596
+ /** A tire size stamped on the sidewall — `225/45R17`. Strings, because the
3597
+ * site's schema declares every field as `String!`. */
3598
+ type TireSize = {
3599
+ diameter: string;
3600
+ width: string;
3601
+ aspectRatio: string;
3602
+ };
3603
+
3604
+ /** One tire product row from the size search. Same shape the site's own
3605
+ * `getProduct` reads back, except price + sku + name + brand, plus the
3606
+ * site's own star rating. */
3607
+ interface DiscounttireTireResult {
3608
+ code: string;
3609
+ name: string | null;
3610
+ brand: string | null;
3611
+ size: string | null;
3612
+ productType: string | null;
3613
+ url: string | null;
3614
+ price: { value: number | null; formatted: string | null } | null;
3615
+ /** `0.0`-`5.0`; null when the line has no reviews. */
3616
+ averageRating: number | null;
3617
+ }
3618
+
3619
+ /** What `searchTiresBySize` returns. */
3620
+ interface DiscounttireTireSizeSearch {
3621
+ /** The storeCode the operation was anchored to (a zip resolves to the
3622
+ * site's nearest store). */
3623
+ storeCode: string;
3624
+ pagination: {
3625
+ currentPage: number | null;
3626
+ numberOfPages: number | null;
3627
+ pageSize: number | null;
3628
+ totalNumberOfResults: number | null;
3629
+ };
3630
+ /** The site's facet names — `Brands`, `Aspect Ratio`, `Price Range`, … */
3631
+ facets: string[];
3632
+ results: DiscounttireTireResult[];
3633
+ source: string;
3634
+ }
3635
+
2809
3636
  /**
2810
3637
  * America's largest independent tire and wheel retailer — which tires and wheels actually fit
2811
3638
  * a given vehicle, what they cost, whether they are in stock near a ZIP, when a store can
2812
- * install them, and the rebates running on them. One function is built: `checkStock` answers
2813
- * whether a specific tire or wheel is gettable near a ZIP, store or coordinate, and on what
2814
- * date. The other fourteen are declared stubs.
3639
+ * install them, and the rebates running on them. Three functions are built: `getProduct` reads
3640
+ * one tire or wheel by its sku (name, brand, size, product type, price, product URL),
3641
+ * `checkStock` answers whether a specific tire or wheel is gettable near a ZIP, store or
3642
+ * coordinate, and on what date, and `searchTiresBySize` searches the tires Discount Tire sells
3643
+ * in a given size (or staggered pair) with prices, ratings and the site's pagination. The
3644
+ * other twelve are declared stubs.
2815
3645
  */
2816
3646
  interface Unit {
3647
+ /**
3648
+ * Reads one tire or wheel product by its sku — name, brand, size, product type, product URL,
3649
+ * and price (value and formatted string). Takes the numeric sku the site's product URLs end in
3650
+ * (/p/<code>), or such a URL. Price is global across stores (verified at three AZ stores on
3651
+ * the same sku on the same day, 2026-08-07), so this function takes no storeCode even though
3652
+ * the underlying `productByCode` operation requires one — the requirement is a schema
3653
+ * compliance constraint, not a per-caller choice. Throws on the site's all-null not-found row,
3654
+ * so a delisted sku surfaces as an error rather than as a row whose every field is null.
3655
+ */
3656
+ getProduct(idOrUrl: string): Promise<DiscounttireProduct>;
3657
+
2817
3658
  /**
2818
3659
  * Answers whether one specific tire or wheel is actually gettable near a place, and when — the
2819
3660
  * site's own availability sentence for the store it resolves to ("Available as soon as
@@ -2827,6 +3668,21 @@ interface DiscounttireStock {
2827
3668
  * "on the shelf right now".
2828
3669
  */
2829
3670
  checkStock(idOrUrl: string, location: { zip: string } | { storeCode: string } | { latitude: number; longitude: number }): Promise<DiscounttireStock>;
3671
+
3672
+ /**
3673
+ * Searches the tires Discount Tire sells in a given size (or staggered pair — `front` and a
3674
+ * different `rear`) and returns what is in stock near a place with prices and star ratings.
3675
+ * `front` and `rear` are stamped-on-the-sidewall sizes like `{ diameter: "17", width: "225",
3676
+ * aspectRatio: "45" }` for `225/45R17`; the site's schema refuses any unknown field on a
3677
+ * `TireSizeInput`, so the function does too. `location` is a 5-digit US zip, an exact store
3678
+ * code, or a coordinate — same three forms `checkStock` takes, same resolution path (zip is
3679
+ * geocoded to its centroid first, then the resolved store is the one the GraphQL operation is
3680
+ * anchored to). `pageNumber` and `pageSize` paginate the result set (pageSize capped at 100).
3681
+ * Returns pagination, the site's own facet list, and a list of tire rows. No
3682
+ * `vehicleAssemblyId` is needed — unlike the by-vehicle searches here, the by-size operations
3683
+ * take `vehicleInfo` as optional and the function never asks for one.
3684
+ */
3685
+ searchTiresBySize(args: { front: { diameter: string; width: string; aspectRatio: string }; rear?: { diameter: string; width: string; aspectRatio: string }; location: { zip: string } | { storeCode: string } | { latitude: number; longitude: number }; pageNumber: number; pageSize: number }): Promise<DiscounttireTireSizeSearch>;
2830
3686
  }
2831
3687
  }
2832
3688
 
@@ -3072,14 +3928,38 @@ interface ExtraspaceNearbyFacility {
3072
3928
  distanceMiles: number | null;
3073
3929
  }
3074
3930
 
3931
+ interface ExtraspaceAvailabilityResult {
3932
+ storeId: number;
3933
+ /** Normalized the way search's unitSize option is, e.g. "10x10". */
3934
+ unitSize: string;
3935
+ /** Every unit CLASS matching the requested size; empty if the facility carries none. */
3936
+ matches: ExtraspaceUnitAvailability[];
3937
+ }
3938
+
3939
+ interface ExtraspaceUnitAvailability {
3940
+ sizeDisplay: string;
3941
+ sizeClass: string;
3942
+ widthFeet: number | null;
3943
+ depthFeet: number | null;
3944
+ squareFeet: number | null;
3945
+ /** Whether the site is currently offering THIS class for rent. */
3946
+ available: boolean;
3947
+ unitsAvailable: number | null;
3948
+ streetRate: number | null;
3949
+ webRate: number | null;
3950
+ promotions: string[];
3951
+ features: string[];
3952
+ }
3953
+
3075
3954
  /**
3076
3955
  * Extra Space Storage — self-storage facility search and detail. `search` takes a US city or
3077
3956
  * ZIP and returns the nearby facilities its own locator would, nearest first, each with its
3078
3957
  * address, distance, amenities and the real monthly price of the cheapest unit in every size
3079
3958
  * it carries. `getFacility` reads one of them in full: street address, both phone lines,
3080
3959
  * office and gate-access hours, what its units offer, starting prices, rating, driving
3081
- * directions and the nearby facilities. Per-size availability and published deals are declared
3082
- * but not built yet.
3960
+ * directions and the nearby facilities. `checkAvailability` checks one specific unit size at
3961
+ * one facility and returns every unit class that matches it, each with its own live
3962
+ * availability and price. Published deals are declared but not built yet.
3083
3963
  */
3084
3964
  interface Unit {
3085
3965
  /**
@@ -3119,6 +3999,70 @@ interface ExtraspaceNearbyFacility {
3119
3999
  * caller-fixable error rather than returning an empty-looking result.
3120
4000
  */
3121
4001
  getFacility(storeId: number | string): Promise<ExtraspaceFacilityDetail>;
4002
+
4003
+ /**
4004
+ * Checks current availability and price for one unit SIZE (e.g. "10x10", "5x15" — width x
4005
+ * depth, in feet) at one Extra Space Storage facility. `storeId` is the same id
4006
+ * `search`/`getFacility` take. Returns every unit CLASS at that facility whose dimensions
4007
+ * match the requested size — a facility routinely lists more than one class of the same
4008
+ * nominal size (a live capture of facility 300125 carries four separate `10' x 10'` classes
4009
+ * with different availability), so this never collapses them to one "best" answer the way
4010
+ * `search`'s roll-up does. Each match reports whether the site is CURRENTLY offering it
4011
+ * (`available`), how many units of that class are free (`unitsAvailable`), both the
4012
+ * struck-through "street" rate and the real "web" rate, any active move-in promotion, and the
4013
+ * class's own features. An empty `matches` array means the facility does not carry that size
4014
+ * at all — a coming-soon facility with zero listed unit classes returns `matches: []` for any
4015
+ * size, with no error, exactly like a fully-open facility that simply does not offer it.
4016
+ * `unitSize` outside `width x depth` form (e.g. "12x40", which nothing in this fixture
4017
+ * carries) is not refused as invalid — it is a value the site may or may not stock, so it is
4018
+ * looked up and answered with an empty array like any other size the facility does not have;
4019
+ * only a string that cannot be PARSED as `<number>x<number>` is a caller error.
4020
+ */
4021
+ checkAvailability(storeId: number | string, unitSize: string): Promise<ExtraspaceAvailabilityResult>;
4022
+ }
4023
+ }
4024
+
4025
+ declare namespace BowmarkProvider_firstdibs {
4026
+ // ── 1stDibs — the unit's own declarations, verbatim ──
4027
+ interface FirstdibsSearchResult {
4028
+ name: string;
4029
+ url: string;
4030
+ price: number;
4031
+ priceCurrency: string;
4032
+ availability: string;
4033
+ image: string | null;
4034
+ }
4035
+ interface FirstdibsCompletingAction {
4036
+ makeOffer: boolean;
4037
+ contactSeller: boolean;
4038
+ purchase: false;
4039
+ }
4040
+ interface FirstdibsListing {
4041
+ name: string;
4042
+ url: string;
4043
+ description: string;
4044
+ brand: string | null;
4045
+ price: number;
4046
+ priceCurrency: string;
4047
+ completingAction: FirstdibsCompletingAction;
4048
+ }
4049
+
4050
+ /**
4051
+ * Search 1stDibs' luxury/vintage marketplace and read a listing's real price plus its concrete
4052
+ * completing action (Make an Offer / Contact Seller) — no login.
4053
+ */
4054
+ interface Unit {
4055
+ /**
4056
+ * Runs 1stDibs' keyword search (or a category-facet URL) and returns real listings with real
4057
+ * price, currency, availability and url.
4058
+ */
4059
+ search(query: string): Promise<FirstdibsSearchResult[]>;
4060
+
4061
+ /**
4062
+ * Reads one listing's real price and its concrete completing action(s) — Make an Offer and/or
4063
+ * Contact Seller, whichever this seller has enabled.
4064
+ */
4065
+ getListing(url: string): Promise<FirstdibsListing>;
3122
4066
  }
3123
4067
  }
3124
4068
 
@@ -3288,21 +4232,177 @@ interface fordNameplateDirectory {
3288
4232
  nameplates: fordNameplate[];
3289
4233
  }
3290
4234
 
4235
+ interface fordOfferProgram {
4236
+ id: string;
4237
+ name: string;
4238
+ /** Ford's own program type, verbatim — "Cash", "APR", and whatever else
4239
+ * Ford introduces. */
4240
+ type: string;
4241
+ /** Whole USD, negative for a discount. null when this program is not a
4242
+ * flat-amount one. */
4243
+ amount: number | null;
4244
+ /** null when this program is not a financing offer. Ford sends one term or
4245
+ * several (e.g. 36/48/60/72/84-month options on the same program). */
4246
+ aprTerms: { apr: number; termMonths: number }[] | null;
4247
+ startDate: string | null;
4248
+ endDate: string | null;
4249
+ disclaimer: string | null;
4250
+ /** Ford's own machine code, e.g. "PC_STANDALONE_APR", "DEALER_CASH". */
4251
+ programType: string | null;
4252
+ /** "Retail" (public), "Private" (military/loyalty/first-responder —
4253
+ * eligibility this function cannot itself verify), "Campaign", or
4254
+ * whatever else Ford uses. */
4255
+ category: string | null;
4256
+ /** True when Ford Motor Credit finances the program. */
4257
+ financeCompany: boolean;
4258
+ /** Ford's own flag for "eligibility depends on something beyond make/model/
4259
+ * ZIP" (military status, trade-in, loyalty). */
4260
+ conditional: boolean;
4261
+ }
4262
+
4263
+ interface fordTrimOffers {
4264
+ trim: string;
4265
+ programs: fordOfferProgram[];
4266
+ }
4267
+
4268
+ interface fordOffers {
4269
+ /** The inventory slug this was resolved from, e.g. "f150". */
4270
+ nameplate: string;
4271
+ modelYear: number;
4272
+ /** The ZIP that was searched — incentives are regional. */
4273
+ postalCode: string;
4274
+ /** Ford's own dealer-region code for that ZIP (e.g. "F48B"), when it sends
4275
+ * one. Opaque outside Ford. */
4276
+ region: string | null;
4277
+ trims: fordTrimOffers[];
4278
+ }
4279
+
4280
+ interface fordVehicleImage {
4281
+ url: string;
4282
+ /** "primary", "exterior" or "interior" — search results carry "primary"
4283
+ * only; this endpoint returns the full set. */
4284
+ role: string;
4285
+ width: number | null;
4286
+ height: number | null;
4287
+ }
4288
+
4289
+ interface fordVehiclePricing {
4290
+ msrp: number;
4291
+ /** null when Ford has no net figure for this vehicle. */
4292
+ netPriceAfterIncentives: number | null;
4293
+ currency: string;
4294
+ /** Ford's own required legal text — show it alongside any displayed price. */
4295
+ disclaimer: string;
4296
+ }
4297
+
4298
+ interface fordVehicleAvailability {
4299
+ /** "in_stock", "in_transit", or a new value Ford introduces. */
4300
+ status: string;
4301
+ asOf: string;
4302
+ }
4303
+
4304
+ interface fordVehicleDealer {
4305
+ name: string;
4306
+ city: string;
4307
+ state: string;
4308
+ distanceMiles: number;
4309
+ phone: string | null;
4310
+ address: string | null;
4311
+ websiteUrl: string | null;
4312
+ }
4313
+
4314
+ interface fordVehicleOptionPackage {
4315
+ name: string;
4316
+ /** null when Ford prices the package into the vehicle's MSRP rather than
4317
+ * itemizing it. */
4318
+ msrp: number | null;
4319
+ }
4320
+
4321
+ interface fordVehicle {
4322
+ vin: string;
4323
+ /** The slug `listNameplates` returns, e.g. "f150", "explorer". */
4324
+ nameplate: string;
4325
+ displayName: string;
4326
+ year: number;
4327
+ trim: string;
4328
+ bodyStyle: string | null;
4329
+ powertrain: string | null;
4330
+ drivetrain: string | null;
4331
+ exteriorColor: string | null;
4332
+ pricing: fordVehiclePricing;
4333
+ availability: fordVehicleAvailability;
4334
+ dealer: fordVehicleDealer;
4335
+ images: fordVehicleImage[];
4336
+ /** Canonical detail page — link every vehicle mention here. */
4337
+ vdpUrl: string;
4338
+ optionPackages: fordVehicleOptionPackage[];
4339
+ }
4340
+
4341
+ interface fordRecallRecord {
4342
+ /** Ford's own campaign identifier, e.g. "23S37", "26S48". */
4343
+ campaignNumber: string | null;
4344
+ title: string | null;
4345
+ /** Issue date as Ford stores it. */
4346
+ issueDate: string | null;
4347
+ description: string | null;
4348
+ safetyRisk: string | null;
4349
+ remedy: string | null;
4350
+ status: string | null;
4351
+ /** True when this is a Field Service Action / Customer Satisfaction Program
4352
+ * (an FSA, NOT a regulator-mandated recall). */
4353
+ isCustomerSatisfactionProgram: boolean;
4354
+ }
4355
+
4356
+ interface fordVehicleRecalls {
4357
+ vin: string;
4358
+ vehicle: {
4359
+ year: string | null;
4360
+ make: string | null;
4361
+ model: string | null;
4362
+ bodyStyle: string | null;
4363
+ fuelType: string | null;
4364
+ };
4365
+ recalls: fordRecallRecord[];
4366
+ customerSatisfactionPrograms: fordRecallRecord[];
4367
+ counts: {
4368
+ recallsCount: number;
4369
+ cspCount: number;
4370
+ totalFsaCount: number;
4371
+ };
4372
+ /** True when the page acknowledges an empty result for this VIN (no
4373
+ * recalls, no FSAs) rather than an error. Ford's own empty-state copy. */
4374
+ noRecalls: boolean;
4375
+ /** True when the upstream recall service failed to answer — the page
4376
+ * surfaces its own API-error message in that case. */
4377
+ apiError: boolean;
4378
+ warnings: string[];
4379
+ }
4380
+
3291
4381
  /**
3292
4382
  * Ford US new-vehicle shopping: live VIN-level dealer inventory near a ZIP, one vehicle by
3293
4383
  * VIN, the model/trim directory and its paint palette, the build-and-price configurator, model
3294
- * specs and MSRP, current incentives, the dealer locator, and recall lookup by VIN. Two
4384
+ * specs and MSRP, current incentives, the dealer locator, and recall lookup by VIN. Five
3295
4385
  * functions are callable now. The dealer locator returns Ford dealers near a US ZIP with full
3296
4386
  * address, phone, coordinates, per-day sales and service hours, Ford's own capability flags
3297
4387
  * (EV-certified, commercial fleet, pickup-and-delivery) and links to the dealer's own site and
3298
4388
  * inventory. The nameplate directory returns every Ford model inventory can be searched by —
3299
4389
  * slug, display name, aliases, body style, model years and trims — and resolves a person's own
3300
- * words ("F-150", "mach e", "Super Duty") to the slug the other inventory endpoints take. The
3301
- * other seven declared functions are still stubs.
4390
+ * words ("F-150", "mach e", "Super Duty") to the slug the other inventory endpoints take.
4391
+ * `getOffers` returns Ford's live, ZIP-regional incentives for a model — cash back, APR
4392
+ * financing (with every term Ford offers, not just the headline one) and any lease programs,
4393
+ * each with its own dates, disclaimer and eligibility category, broken out per trim.
4394
+ * `getVehicle` reads one specific vehicle by VIN — full trim, pricing with Ford's required
4395
+ * disclaimer, availability, the holding dealer's contact details, the FULL image set (exterior
4396
+ * AND interior, not just the one card image a search result carries) and every option package
4397
+ * — and returns `null` rather than throwing when Ford reports the vehicle sold or removed,
4398
+ * which its own docs call a real, non-retryable answer. `getRecalls` returns the open safety
4399
+ * recalls and Customer Satisfaction Programs Ford has published against a VIN — campaign
4400
+ * number, issue date, description, safety risk and remedy for each — splitting
4401
+ * regulator-mandated recalls from Ford's own goodwill FSAs, with `null` for a well-formed VIN
4402
+ * Ford has no record of and an empty result (no recalls, no FSAs) for a known VIN with no open
4403
+ * actions. The other four declared functions are still stubs.
3302
4404
  */
3303
4405
  interface Unit {
3304
- // NO TYPED SURFACE — every function this unit declares is refused above.
3305
- // The unit is real and callable at runtime; nothing here can say so in types.
3306
4406
  // UNTYPED, DELIBERATELY OMITTED — `findDealers({ near, radiusMiles, limit })` declares no types for
3307
4407
  // its argument, so there is no honest signature to emit.
3308
4408
  // It is CALLABLE at runtime; `bowmark.providers.ford.findDealers` is a compile error here on purpose.
@@ -3312,6 +4412,52 @@ interface fordNameplateDirectory {
3312
4412
  // its argument, so there is no honest signature to emit.
3313
4413
  // It is CALLABLE at runtime; `bowmark.providers.ford.listNameplates` is a compile error here on purpose.
3314
4414
  // A `(...args: unknown[])` stand-in would compile and tell you nothing.
4415
+
4416
+ /**
4417
+ * Ford's current incentives for one model near a US ZIP — cash back, APR financing (every term
4418
+ * Ford offers on a program, e.g. 36/48/60/72/84-month options, not just the headline rate) and
4419
+ * any lease programs — broken out per trim, each with its start/end date, Ford's own
4420
+ * disclaimer text, its machine program code, and a `category` ("Retail" public vs. "Private"
4421
+ * military/loyalty/first-responder) so a caller can tell a program anyone qualifies for from
4422
+ * one that needs proof this function cannot itself check. `nameplate` is the slug
4423
+ * `listNameplates` returns ("f150", "bronco-sport"); a handful of commercial-chassis
4424
+ * nameplates the inventory API lists have no incentives page at all and are refused by name,
4425
+ * measured rather than guessed. `postalCode` is required — incentives are regional, and the
4426
+ * SAME model/year at two ZIPs 2,000 miles apart returns genuinely different programs. `year`
4427
+ * defaults to the newest model year Ford is currently running incentives on for that
4428
+ * nameplate.
4429
+ */
4430
+ getOffers(args: { nameplate: string; postalCode: string; year?: number }): Promise<fordOffers>;
4431
+
4432
+ /**
4433
+ * Reads one specific vehicle by its 17-character VIN — full trim, exterior color, complete
4434
+ * pricing with Ford's required disclaimer, live availability, the holding dealer's
4435
+ * name/address/phone/website, the FULL image set (`primary`, `exterior` AND `interior` — a
4436
+ * `searchInventory` result carries `primary` only), every option package, and the canonical
4437
+ * `vdpUrl` Ford's own docs say to link on any mention. `vin` is a required argument, matching
4438
+ * Ford's own pattern (17 characters, excluding I/O/Q) and checked locally before spending a
4439
+ * request. Returns `null` — not an error — when Ford answers `VEHICLE_NOT_FOUND`: Ford's own
4440
+ * docs call a 404 here "sold or removed... not a retryable error", so a vehicle that sold
4441
+ * between search and read is a real, unsurprising answer rather than a failure.
4442
+ */
4443
+ getVehicle(vin: string): Promise<fordVehicle | null>;
4444
+
4445
+ /**
4446
+ * Reads the open safety recalls and Customer Satisfaction Programs (FSAs) Ford has published
4447
+ * against one specific VIN, and what each one says to do — the same answer an owner or a
4448
+ * used-car buyer gets on Ford's owner-support recalls page. `vin` is required and locally
4449
+ * validated against the same 17-character pattern `getVehicle` uses (A-H, J-N, P, R-Z, 0-9).
4450
+ * Returns `null` — not an error — when the VIN is well-formed but unknown to Ford (the page
4451
+ * sets `isVinInvalid: true`); the call surfaces `noRecalls: true` for a known VIN with no open
4452
+ * actions, and the response separates regulator-mandated `recalls` from optional
4453
+ * `customerSatisfactionPrograms` (the latter are Ford's free goodwill fixes, NOT safety
4454
+ * recalls). Each record carries Ford's own campaign number, issue date, the free-form
4455
+ * description, the stated safety risk, the prescribed remedy, and the status Ford reports.
4456
+ * When Ford's recall upstream fails, the call returns a successful shape with `apiError: true`
4457
+ * and the upstream's own error message in `warnings` — a transient 5xx shouldn't kill the
4458
+ * caller. No sign-in: the page is public.
4459
+ */
4460
+ getRecalls(vin: string): Promise<fordVehicleRecalls | null>;
3315
4461
  }
3316
4462
  }
3317
4463
 
@@ -3436,9 +4582,42 @@ interface fredSeries {
3436
4582
  notes: string | null;
3437
4583
  }
3438
4584
 
4585
+ interface fredCategoryRow {
4586
+ id: number;
4587
+ name: string;
4588
+ parentId: number;
4589
+ }
4590
+
4591
+ interface fredCategory {
4592
+ id: number;
4593
+ name: string;
4594
+ parentId: number;
4595
+ children: fredCategoryRow[];
4596
+ series: fredSeries[];
4597
+ }
4598
+
4599
+ interface fredObservation {
4600
+ date: string;
4601
+ /** null where FRED holds no observation for that period — a market holiday in a
4602
+ * daily series, or the first year of a year-over-year transform. */
4603
+ value: number | null;
4604
+ }
4605
+
4606
+ interface fredObservations {
4607
+ seriesId: string;
4608
+ /** The transform FRED reports having applied: "lin" (none), "pc1", "pch", … */
4609
+ units: string;
4610
+ observationStart: string;
4611
+ observationEnd: string;
4612
+ realtimeStart: string;
4613
+ realtimeEnd: string;
4614
+ count: number;
4615
+ observations: fredObservation[];
4616
+ }
4617
+
3439
4618
  /**
3440
- * US economic data releases and their publication calendar, and the agencies FRED republishes
3441
- * data from, off the St. Louis Fed's FRED.
4619
+ * US economic data releases and their publication calendar, the agencies FRED republishes data
4620
+ * from, series metadata, and FRED's own category tree, off the St. Louis Fed's FRED.
3442
4621
  */
3443
4622
  interface Unit {
3444
4623
  /**
@@ -3472,6 +4651,34 @@ interface fredSeries {
3472
4651
  * back as a caller-fixable error naming the problem rather than as an empty result.
3473
4652
  */
3474
4653
  getSeriesInfo(seriesId: string): Promise<fredSeries>;
4654
+
4655
+ /**
4656
+ * Reads the actual numbers for a FRED series — the dated observations themselves, oldest
4657
+ * first, with a missing period returned as `value: null` rather than as a `NaN` or a silently
4658
+ * dropped row. Called bare (`getSeriesObservations("GDPC1")`) it returns the series' full
4659
+ * history; `from`/`to` (ISO yyyy-mm-dd) narrow the window. It also runs FRED's own transforms
4660
+ * server-side so a caller never has to recompute one: `units` converts the level to a change
4661
+ * (`pc1` percent change from a year ago — the usual way to read inflation off CPIAUCSL — plus
4662
+ * `pch`, `chg`, `log` and the rest of FRED's ten codes), and `frequency` with
4663
+ * `aggregationMethod` collapses a series to a coarser period (`{ frequency: "a",
4664
+ * aggregationMethod: "avg" }` turns the monthly unemployment rate into annual averages). The
4665
+ * result carries the transform FRED reports having applied and the vintage it served, so a
4666
+ * caller can tell what they actually got. This is the function to call once
4667
+ * `searchSeries`/`getSeriesInfo` has identified the right series id — e.g. A191RL1Q225SBEA for
4668
+ * the US real GDP growth rate.
4669
+ */
4670
+ getSeriesObservations(args: string | { seriesId: string; from?: string; to?: string; units?: string; frequency?: string; aggregationMethod?: string }): Promise<fredObservations>;
4671
+
4672
+ /**
4673
+ * Browses FRED's category tree the way fred.stlouisfed.org/categories does — the category
4674
+ * itself (id/name/parent), its immediate child categories, and the series filed directly under
4675
+ * it (the same shape getSeriesInfo returns per series, so a caller can read
4676
+ * units/frequency/lastUpdated off a browsed result with no second call). Called bare it starts
4677
+ * at the root (id 0). FRED organizes its ~800,000 series into a real hierarchy, so this is how
4678
+ * a caller explores 'what's available in this area' before knowing a series id to look up
4679
+ * directly. An unknown category id comes back as a caller-fixable error.
4680
+ */
4681
+ browseCategory(categoryId?: number): Promise<fredCategory>;
3475
4682
  }
3476
4683
  }
3477
4684
 
@@ -3912,6 +5119,15 @@ interface graingerRow {
3912
5119
  id: string;
3913
5120
  }
3914
5121
 
5122
+ interface graingerSearchRow {
5123
+ itemNumber: string;
5124
+ name: string;
5125
+ url: string;
5126
+ brand: string | null;
5127
+ price: { amount: number; currency: string; perUnit: string } | null;
5128
+ thumbnail: string | null;
5129
+ }
5130
+
3915
5131
  interface graingerBranchRow {
3916
5132
  branchNumber: string;
3917
5133
  name: string;
@@ -3922,12 +5138,55 @@ interface graingerBranchRow {
3922
5138
  hours: { day: string; hours: string }[];
3923
5139
  }
3924
5140
 
5141
+ interface graingerProductRow {
5142
+ itemNumber: string;
5143
+ manufacturerModel: string | null;
5144
+ name: string;
5145
+ description: string | null;
5146
+ brand: string | null;
5147
+ url: string;
5148
+ images: string[];
5149
+ price: { amount: number; currency: string; perUnit: string } | null;
5150
+ specs: { name: string; value: string }[];
5151
+ availabilitySummary: string | null;
5152
+ }
5153
+
5154
+ interface graingerStockRow {
5155
+ itemNumber: string;
5156
+ zip: string;
5157
+ quantity: number;
5158
+ shipping: { message: string | null; fulfillmentCode: string | null; availKey: string | null } | null;
5159
+ pickup: {
5160
+ message: string | null;
5161
+ fulfillmentCode: string | null;
5162
+ availKey: string | null;
5163
+ branch: {
5164
+ branchCode: string;
5165
+ city: string | null;
5166
+ address: { street: string | null; city: string | null; state: string | null; zip: string | null; country: string | null } | null;
5167
+ url: string | null;
5168
+ } | null;
5169
+ } | null;
5170
+ }
5171
+
3925
5172
  /**
3926
- * Grainger's industrial MRO catalog, product detail, and branch/stock availability —
3927
- * findBranch is live (nationwide branch directory, address/phone/hours); catalog, product
3928
- * detail and stock checks are still stubs.
5173
+ * Grainger's industrial MRO catalog, product detail, and branch/stock availability — search
5174
+ * (keyword/category catalog search returning name, item number, brand, price and thumbnail),
5175
+ * findBranch (nationwide branch directory), getProduct (price, pack size, spec table,
5176
+ * availability by item number or URL) and checkStock (shipping-to-zip and
5177
+ * pickup-at-nearest-branch fulfillment estimates) are all live.
3929
5178
  */
3930
5179
  interface Unit {
5180
+ /**
5181
+ * Searches Grainger's industrial MRO catalog by keyword, returning matching products — item
5182
+ * number, name, brand, list price and thumbnail. Takes `query` (free text, e.g. "antistatic
5183
+ * gloves"). A SPECIFIC query resolves to Grainger's own matching leaf category and returns its
5184
+ * real products; a broad query (e.g. "gloves" alone) can resolve to a category-of-categories
5185
+ * browse page one or more levels above any actual product and throws rather than returning an
5186
+ * empty array — narrow the query if that happens.
5187
+ */
5188
+ search(args: object): Promise<graingerSearchRow[]>;
5189
+
3931
5190
  /**
3932
5191
  * Finds Grainger's own U.S. branches near a ZIP, city or state — address, phone, hours and
3933
5192
  * curbside-pickup availability, off the site's own nationwide directory. `zip` matches by its
@@ -3937,6 +5196,99 @@ interface graingerBranchRow {
3937
5196
  * truncating.
3938
5197
  */
3939
5198
  findBranch(args: object): Promise<graingerBranchRow[]>;
5199
+
5200
+ /**
5201
+ * Reads one Grainger product page in full — price and pack size/unit of measure, the full spec
5202
+ * table, the manufacturer's own part number, and a shipping/pickup availability summary. Takes
5203
+ * `itemNumber` (Grainger's own catalog id, e.g. "26K909" — resolves directly, no descriptive
5204
+ * slug needed) or `url` (a full grainger.com product URL). Throws if the item number doesn't
5205
+ * exist (a clean 404) rather than returning an empty row.
5206
+ */
5207
+ getProduct(args: object): Promise<graingerProductRow>;
5208
+
5209
+ /**
5210
+ * Checks real fulfillment availability for one item (`itemNumber` or `url`, same as
5211
+ * `getProduct`) at a caller-supplied `zip` (required, 5-digit US) — both shipping-to-that-zip
5212
+ * and pickup-at-the-nearest-branch-to-that-zip, in one call. Returns the site's own message
5213
+ * text (an arrival/ready-by estimate, never a literal stock count — the site doesn't publish
5214
+ * one) plus its opaque status codes for each mode, and the ACTUAL branch that answered the
5215
+ * pickup half (nearest-to-point, not necessarily one the caller could have named). Optional
5216
+ * `quantity` (default 1) is forwarded to the site.
5217
+ */
5218
+ checkStock(args: object): Promise<graingerStockRow>;
5219
+ }
5220
+ }
5221
+
5222
+ declare namespace BowmarkProvider_hauslabs {
5223
+ // ── Haus Labs by Lady Gaga — the unit's own declarations, verbatim ──
5224
+ interface HauslabsVariant {
5225
+ id: string;
5226
+ title: string;
5227
+ price: string;
5228
+ compareAtPrice: string | null;
5229
+ sku: string | null;
5230
+ available: boolean;
5231
+ options: string[];
5232
+ }
5233
+ interface HauslabsProduct {
5234
+ handle: string;
5235
+ title: string;
5236
+ vendor: string;
5237
+ productType: string;
5238
+ url: string;
5239
+ descriptionHtml: string | null;
5240
+ optionNames: string[];
5241
+ variants: HauslabsVariant[];
5242
+ priceRange: { min: string; max: string } | null;
5243
+ inStock: boolean;
5244
+ tags: string[];
5245
+ images: string[];
5246
+ }
5247
+ interface HauslabsShadeMatch {
5248
+ quiz: { family: string; depth: string; undertone: string; hasAddOne: boolean };
5249
+ variant: {
5250
+ number: number;
5251
+ family: string;
5252
+ sku: string | null;
5253
+ price: string;
5254
+ available: boolean;
5255
+ };
5256
+ product: HauslabsProduct;
5257
+ warnings: string[];
5258
+ }
5259
+
5260
+ /**
5261
+ * Haus Labs by Lady Gaga product catalogue — every clean-beauty SKU, its variants, its prices
5262
+ * and what is in stock — read off the live Shopify Plus storefront. The Foundation Shade
5263
+ * Finder is the broadcast wedge: a multi-step quiz ChatGPT cannot operate, mapped locally to
5264
+ * one specific priced shade with the buy-page handoff.
5265
+ */
5266
+ interface Unit {
5267
+ /**
5268
+ * Reads the live Haus Labs catalogue as the storefront publishes it — every product, its
5269
+ * handle, title, vendor, description, tags, images and the per-variant price the storefront is
5270
+ * quoting right now. Optional productType narrows to FACE / LIPS / EYES / SETS / etc. before
5271
+ * the limit. Returns [] on a transport failure (warnings would be on an object envelope; this
5272
+ * is a list). The catalog page is the line and the parse is the unit of work.
5273
+ */
5274
+ listHauslabsProducts(opts?: { limit?: number; productType?: string }): Promise<HauslabsProduct[]>;
5275
+
5276
+ /**
5277
+ * Reads one product by its handle — every variant, its exact price, the image the storefront
5278
+ * is showing and whether that specific variant is purchasable right now. Takes the handle
5279
+ * listHauslabsProducts returns. THROWS on an unknown handle (the store answers a real 404).
5280
+ */
5281
+ getHauslabsProduct(handle: string): Promise<HauslabsProduct>;
5282
+
5283
+ /**
5284
+ * Resolves a buyer's Foundation Lab quiz answers to ONE specific shade: the variant title, the
5285
+ * SKU, the real price, the availability, the buy-page URL. Mirrors the quiz's `shadeLogic`
5286
+ * decision tree natively against Cartful Solutions' published `pd.json` (keyless, browserless)
5287
+ * and resolves the matching variant through /products/<handle>.js for live price and stock.
5288
+ * The quiz is a 5-step Shopify section ChatGPT cannot operate on the buyer's behalf; this
5289
+ * function returns the single shade the quiz's terminal page renders for the same inputs.
5290
+ */
5291
+ runFoundationShadeFinder(input: { family: 'Deep' | 'Medium Deep' | 'Medium' | 'Light Medium' | 'Light' | 'Fair'; depth: 'deeper' | 'medium' | 'lighter'; undertone: 'warm' | 'cool' | 'neutral' | 'rosy' | 'golden'; hasAddOne?: boolean }): Promise<HauslabsShadeMatch>;
3940
5292
  }
3941
5293
  }
3942
5294
 
@@ -4734,6 +6086,72 @@ interface HellofreshRecipeSearchPage {
4734
6086
  }
4735
6087
  }
4736
6088
 
6089
+ declare namespace BowmarkProvider_hellotend {
6090
+ // ── Tend Dental — the unit's own declarations, verbatim ──
6091
+ interface HellotendMarket {
6092
+ slug: string; // e.g. "new-york-city"
6093
+ name: string; // e.g. "New York City"
6094
+ location: { lat: number; lon: number } | null;
6095
+ bookingEnabled: boolean;
6096
+ }
6097
+ interface HellotendStudio {
6098
+ slug: string; // e.g. "hells-kitchen" — what listServices takes
6099
+ name: string;
6100
+ market: string; // e.g. "new-york-city"
6101
+ address: string | null;
6102
+ location: { lat: number; lon: number } | null;
6103
+ openingDate: string | null;
6104
+ serviceCodes: string[]; // ["CLNCHK","WHTNG",...] — the codes this studio accepts
6105
+ bookingEnabled: boolean;
6106
+ familyBookingEnabled: boolean;
6107
+ }
6108
+ interface HellotendService {
6109
+ code: string | null; // e.g. "CLNCHK" — null on category-level entries
6110
+ name: string; // e.g. "Exam"
6111
+ longName: string | null; // e.g. "Dental Exam"
6112
+ description: string | null;
6113
+ bookingDescription: string | null;
6114
+ duration: string | null; // e.g. "70 minutes or less"
6115
+ }
6116
+
6117
+ /**
6118
+ * Reads Tend Dental's public booking chain — every market, every studio, every service a
6119
+ * studio offers — straight from hellotend.com's own Next.js data route, no key, no browser.
6120
+ */
6121
+ interface Unit {
6122
+ /**
6123
+ * Lists every market Tend serves — the 6 metros the booking chain currently offers (NYC,
6124
+ * Washington DC, Atlanta, Boston, Chicago, Nashville), with each market's slug, lat/lon and
6125
+ * booking-enabled flag. Takes nothing. The slug it returns is what listStudios and
6126
+ * listServices take. THROWS rather than returning [] when the data route answers without its
6127
+ * payload or names no markets — Tend operates 6 metros and zero is never an honest answer.
6128
+ */
6129
+ listMarkets(): Promise<HellotendMarket[]>;
6130
+
6131
+ /**
6132
+ * Lists every Tend dental studio — 33+ across all markets, with name, slug, market, address,
6133
+ * lat/lon, opening date, the service codes that studio accepts, and whether it offers
6134
+ * family-booking. The market arg is OPTIONAL: omit it to get the full set across all markets,
6135
+ * pass a market slug to filter. THROWS rather than returning [] when the data route answers
6136
+ * without its payload or names no studios; surfaces an unknown market slug as a caller-fixable
6137
+ * error listing the real ones.
6138
+ */
6139
+ listStudios(market?: string): Promise<HellotendStudio[]>;
6140
+
6141
+ /**
6142
+ * Lists the service codes a specific Tend studio offers (Dental Exam CLNCHK, Clear Aligners
6143
+ * INVISALN, Emergency EMGNCY, Sleep Apnea Consult SLPCONS, Cosmetic, Procedures) with each
6144
+ * service's display name, code, duration and short description. The CODE is what a real Tend
6145
+ * booking needs to advance to the time-picker page. The first four carry a code; the last two
6146
+ * (Cosmetic, Procedures) are category-level landing entries that route to sub-flows and are
6147
+ * returned with a null code rather than dropped. THROWS rather than returning [] when the data
6148
+ * route answers without its payload or names no services; surfaces an unknown studio as a
6149
+ * caller-fixable error listing the real ones in that market.
6150
+ */
6151
+ listServices(market: string, studio: string): Promise<HellotendService[]>;
6152
+ }
6153
+ }
6154
+
4737
6155
  declare namespace BowmarkProvider_hilton {
4738
6156
  // ── Hilton — the unit's own declarations, verbatim ──
4739
6157
  interface hiltonRoomOffer {
@@ -5979,6 +7397,99 @@ interface InteriorDefineCartHandoff {
5979
7397
  }
5980
7398
  }
5981
7399
 
7400
+ declare namespace BowmarkProvider_joybird {
7401
+ // ── Joybird — the unit's own declarations, verbatim ──
7402
+ interface JoybirdConfigurator {
7403
+ slug: string;
7404
+ name: string;
7405
+ sku: string;
7406
+ type: string;
7407
+ family: string;
7408
+ url: string;
7409
+ finalPrice: number;
7410
+ originalPrice: number;
7411
+ discountPercent: number;
7412
+ }
7413
+ interface JoybirdOptionValue {
7414
+ sku: string;
7415
+ value: string;
7416
+ cover: string | null;
7417
+ color: string | null;
7418
+ family: string;
7419
+ tier: number;
7420
+ petFriendly: boolean;
7421
+ performanceFabric: boolean;
7422
+ sustainableFabric: boolean;
7423
+ popular: boolean;
7424
+ }
7425
+ interface JoybirdOption {
7426
+ id: number;
7427
+ name: string;
7428
+ type: string | null;
7429
+ values: JoybirdOptionValue[];
7430
+ }
7431
+ interface JoybirdCatalog {
7432
+ slug: string;
7433
+ name: string;
7434
+ sku: string;
7435
+ type: string;
7436
+ family: string;
7437
+ url: string;
7438
+ dimensions: string;
7439
+ finalPrice: number;
7440
+ originalPrice: number;
7441
+ discountPercent: number;
7442
+ promotionStart: string | null;
7443
+ promotionEnd: string | null;
7444
+ options: JoybirdOption[];
7445
+ }
7446
+ interface JoybirdPriceLine {
7447
+ optionId: number;
7448
+ optionName: string;
7449
+ optionSku: string;
7450
+ valueSku: string;
7451
+ valueName: string;
7452
+ }
7453
+ interface JoybirdPriceResult {
7454
+ slug: string;
7455
+ sku: string;
7456
+ finalPrice: number;
7457
+ originalPrice: number;
7458
+ discountPercent: number;
7459
+ lines: JoybirdPriceLine[];
7460
+ }
7461
+
7462
+ /**
7463
+ * Reads Joybird's real sofa/sectional configurator — every configurable product, every fabric
7464
+ * and wood stain, and the live configured price Joybird's own page shows.
7465
+ */
7466
+ interface Unit {
7467
+ /**
7468
+ * Lists every configurable product Joybird sells — sofas, sectionals, chairs, ottomans, beds,
7469
+ * organised by collection — with its slug, name, current displayed price, list price and
7470
+ * active discount. Takes nothing. The slug it returns is what getConfigurator and
7471
+ * priceConfigurator take.
7472
+ */
7473
+ listConfigurators(): Promise<JoybirdConfigurator[]>;
7474
+
7475
+ /**
7476
+ * Reads one product's full configurator — its dimensions, current price, active promotion
7477
+ * window, and every option slot the product exposes (Fabric, Wood Stain, Orientation, ...)
7478
+ * with the site's full swatch list for each. The slot ids and swatch SKUs it returns are what
7479
+ * priceConfigurator takes.
7480
+ */
7481
+ getConfigurator(slug: string): Promise<JoybirdCatalog>;
7482
+
7483
+ /**
7484
+ * Prices an exact configuration for one product given the caller's swatch picks (one swatch
7485
+ * SKU per slot id; any slot left out uses its first available swatch as a documented default).
7486
+ * Returns the real live total Joybird's own page shows, plus a per-slot breakdown of what was
7487
+ * picked.
7488
+ */
7489
+ priceConfigurator(slug: string, selections: Record<string, string>): Promise<JoybirdPriceResult>;
7490
+ }
7491
+ }
7492
+
5982
7493
  declare namespace BowmarkProvider_kayak {
5983
7494
  // ── Kayak — the unit's own declarations, verbatim ──
5984
7495
  interface KayakQuery {
@@ -6134,6 +7645,17 @@ interface LabcorpTestSummary {
6134
7645
  currency: string; // "USD"
6135
7646
  }
6136
7647
 
7648
+ interface LabcorpTestDetail extends LabcorpTestSummary {
7649
+ sampleType: string; // "Blood & Urine", "Nasal Swab"
7650
+ collectionMethod: string; // "In person at a Labcorp location"
7651
+ turnaroundTime: string; // "1-2 days from when your sample arrives at our lab"
7652
+ ageRange: string; // "18-100", "" if absent
7653
+ metaDescription: string;
7654
+ metaTitle: string;
7655
+ shortDescriptionHtml: string;
7656
+ descriptionHtml: string;
7657
+ }
7658
+
6137
7659
  /** Lab test pricing, PSC location lookup and appointment availability from Labcorp. */
6138
7660
  interface Unit {
6139
7661
  /**
@@ -6142,6 +7664,14 @@ interface LabcorpTestSummary {
6142
7664
  * No doctor's visit required to order.
6143
7665
  */
6144
7666
  search(query: string): Promise<LabcorpTestSummary[]>;
7667
+
7668
+ /**
7669
+ * Returns the full OnDemand test detail for one sku — price, descriptions, sample type,
7670
+ * collection method, turnaround time and acceptable age band. Combines the catalog row
7671
+ * (GraphQL) with the specimen/turnaround facts the site renders on the PDP HTML. Pass the sku
7672
+ * returned by `search`.
7673
+ */
7674
+ getTest(sku: string): Promise<LabcorpTestDetail>;
6145
7675
  }
6146
7676
  }
6147
7677
 
@@ -6628,6 +8158,80 @@ interface LululemonVariant {
6628
8158
  available: boolean;
6629
8159
  price: number | null;
6630
8160
  salePrice: number | null;
8161
+ /** Why this SKU's price is, or is not, a markdown. Derived from price and
8162
+ * salePrice, so it can never disagree with them. */
8163
+ sale: SaleEvidence;
8164
+ }
8165
+ interface SaleEvidence {
8166
+ /** True only with retailer evidence. NEVER from a low price or a title. */
8167
+ onSale: boolean;
8168
+ currentPrice: number | null;
8169
+ /** The list price, when the markdown is against one. */
8170
+ originalPrice: number | null;
8171
+ /** ISO 4217, or null. ALWAYS null here: this feed publishes bare numbers with
8172
+ * no currency code anywhere in the payload. */
8173
+ currency: string | null;
8174
+ promotionMessage: string | null;
8175
+ evidenceType: "compare_at_price" | "sale_price" | "retailer_sale_badge" | "published_promotion" | "none";
8176
+ /** The retailer text or field the classification rests on, verbatim. */
8177
+ evidenceText: string | null;
8178
+ }
8179
+ interface ProductImage {
8180
+ /** Absolute HTTPS url. */
8181
+ url: string;
8182
+ altText: string | null;
8183
+ /** The colourway's own colour — sound because lululemon publishes its image
8184
+ * list PER COLOURWAY, so every picture in it is that colour by construction. */
8185
+ color: string | null;
8186
+ colorId: string | null;
8187
+ /** Always [] here: this feed links a picture to a COLOUR, never to a size. */
8188
+ variantIds: string[];
8189
+ }
8190
+ /** The retailer's own labels. On this door that is audience and nothing else —
8191
+ * the HPDP feed publishes no description, tags, fabric, collection or category.
8192
+ * Every other field is null or [], honestly. */
8193
+ interface PublishedProductAttributes {
8194
+ audience: string | null;
8195
+ garmentType: "sports_bra" | "tank" | "crop_top" | "leggings" | "shorts" | "other" | null;
8196
+ categories: string[];
8197
+ collections: string[];
8198
+ fabrics: string[];
8199
+ materials: string[];
8200
+ color: string | null;
8201
+ colorFamily: string | null;
8202
+ pattern: string | null;
8203
+ styleTags: string[];
8204
+ neckline: string | null;
8205
+ strapWidth: string | null;
8206
+ backDesign: string | null;
8207
+ sleeveLength: string | null;
8208
+ rise: string | null;
8209
+ waistband: string | null;
8210
+ inseam: string | null;
8211
+ legShape: string | null;
8212
+ fit: string | null;
8213
+ coverage: string | null;
8214
+ }
8215
+ /** Shared colour and family — what makes two pieces PLAUSIBLY coordinate. None
8216
+ * of it establishes a set. */
8217
+ interface CoordinationMetadata {
8218
+ collectionNames: string[];
8219
+ fabricNames: string[];
8220
+ colorName: string | null;
8221
+ colorId: string | null;
8222
+ colorFamily: string | null;
8223
+ productFamily: string | null;
8224
+ }
8225
+ /** An EXPLICIT retailer-published relationship. ALWAYS [] on this door: the feed's
8226
+ * only product-to-product relation is the ALGORITHMIC similarity rail, which is
8227
+ * getSimilarProducts. Reading that as a set would turn "the recommender put these
8228
+ * near each other" into "lululemon sells these together". */
8229
+ interface RetailerSetEvidence {
8230
+ evidenceType: "official_set" | "shop_the_set" | "complete_the_look" | "matching_piece";
8231
+ evidenceText: string | null;
8232
+ sourceUrl: string | null;
8233
+ setId: string | null;
8234
+ relatedProducts: Array<{ productId: string | null; handle: string | null; title: string | null; url: string | null }>;
6631
8235
  }
6632
8236
  interface LululemonOptionGroup {
6633
8237
  /** The machine name. "size" on every lululemon product measured. */
@@ -6649,6 +8253,13 @@ interface LululemonColorway {
6649
8253
  url: string;
6650
8254
  swatchImage: string | null;
6651
8255
  images: string[];
8256
+ /** The SAME pictures as images, carrying this colourway's colour and colorId.
8257
+ * images stays a bare string[] for existing callers; this is the additive half. */
8258
+ imageAssets: ProductImage[];
8259
+ sale: SaleEvidence;
8260
+ coordination: CoordinationMetadata;
8261
+ /** ISO 4217, or null. Always null — see SaleEvidence.currency. */
8262
+ currency: string | null;
6652
8263
  inStock: boolean;
6653
8264
  optionGroups: LululemonOptionGroup[];
6654
8265
  /** What can be BOUGHT in this colour right now — not the full size run. */
@@ -6676,6 +8287,37 @@ interface LululemonProduct {
6676
8287
  /** Other lengths of the same style. Empty on every product measured — on this
6677
8288
  * site an inseam is its OWN product, not an option. */
6678
8289
  sizeTypes: LululemonSizeType[];
8290
+ attributes: PublishedProductAttributes;
8291
+ coordination: CoordinationMetadata;
8292
+ retailerSetEvidence: RetailerSetEvidence[];
8293
+ }
8294
+ /** One published product-detail block from the page, verbatim. */
8295
+ interface LululemonFeature {
8296
+ heading: string;
8297
+ body: string;
8298
+ }
8299
+ /** What lululemon's OWN product page publishes about a garment, which the
8300
+ * third-party pricing door does not carry at all. */
8301
+ interface LululemonProductAttributes {
8302
+ productId: string;
8303
+ url: string;
8304
+ title: string;
8305
+ /** The site's own ProductGroup category, e.g. "Leggings". */
8306
+ category: string | null;
8307
+ description: string | null;
8308
+ /** Trademarked fabric names off the detail accordion, e.g. ["Nulu"]. */
8309
+ fabrics: string[];
8310
+ fit: string | null;
8311
+ /** "High-Rise" / "Mid-Rise" / "Low-Rise", as the title spells it. */
8312
+ rise: string | null;
8313
+ /** Every detail block, unmapped and in page order. */
8314
+ features: LululemonFeature[];
8315
+ /** The site's own aggregate — the honest one. The pricing door reports 0
8316
+ * reviews on products whose live page shows 22,748. */
8317
+ ratingValue: number | null;
8318
+ reviewCount: number | null;
8319
+ /** What could not be reached. Non-empty means the page refused. */
8320
+ warnings: string[];
6679
8321
  }
6680
8322
  interface LululemonRow {
6681
8323
  id: string;
@@ -6731,6 +8373,19 @@ interface LululemonSimilarProducts {
6731
8373
  */
6732
8374
  getProduct(query: { productId: string }): Promise<LululemonProduct>;
6733
8375
 
8376
+ /**
8377
+ * Reads what lululemon's OWN product page publishes about a garment and the third-party
8378
+ * pricing door does not carry at all: the category the site files it under, the collection
8379
+ * description, the trademarked fabric it is cut from, the fit and the rise, its real review
8380
+ * aggregate, and every product-detail block verbatim. This is the expensive door on this
8381
+ * provider — a headed Google Chrome, ~10-20x the latency of `getProduct` — so call it when the
8382
+ * ATTRIBUTES are the answer and `getProduct` when the price, colourways and sizes are. It
8383
+ * never throws on a refused page: a page that will not render comes back with every field
8384
+ * empty and a `warnings` entry naming it, so an empty `fabrics` is distinguishable from an
8385
+ * unread one.
8386
+ */
8387
+ getProductAttributes(query: { productId: string }): Promise<LululemonProductAttributes>;
8388
+
6734
8389
  /**
6735
8390
  * Returns the products lululemon's own product pages recommend alongside one product — the
6736
8391
  * 'You may also like' rail — as priced rows in the store's own ranked order, de-duplicated to
@@ -6743,6 +8398,82 @@ interface LululemonSimilarProducts {
6743
8398
  }
6744
8399
  }
6745
8400
 
8401
+ declare namespace BowmarkProvider_maidenhome {
8402
+ // ── Maiden Home — the unit's own declarations, verbatim ──
8403
+ // Maiden Home's OWN shapes — not a capability contract.
8404
+
8405
+ interface MaidenHomeVariant {
8406
+ productHandle: string;
8407
+ productTitle: string;
8408
+ productType: string; // e.g. "Sofa", "Modular Component", "Dining Table"
8409
+ size: string; // e.g. "85\" Width", or a non-numeric value like "Right-Facing Chaise"
8410
+ woodFinish: string; // e.g. "Driftwood Ash"
8411
+ sku: string;
8412
+ price: number;
8413
+ priceFormatted: string;
8414
+ available: boolean;
8415
+ url: string; // the product page, preselecting this exact variant
8416
+ }
8417
+
8418
+ interface MaidenHomeConfiguratorProduct {
8419
+ handle: string;
8420
+ title: string;
8421
+ productType: string;
8422
+ url: string;
8423
+ sizeOptions: string[];
8424
+ woodFinishOptions: string[];
8425
+ priceRange: { min: number; max: number };
8426
+ variants: MaidenHomeVariant[];
8427
+ }
8428
+
8429
+ interface MaidenHomeVariantResolution {
8430
+ productQuery: string;
8431
+ size: string;
8432
+ woodFinish: string;
8433
+ matched: boolean;
8434
+ variant: MaidenHomeVariant | null;
8435
+ candidates: MaidenHomeVariant[]; // populated when not narrowed to exactly one real variant
8436
+ message: string;
8437
+ }
8438
+
8439
+ /**
8440
+ * Maiden Home's Size x Wood Finish product configurator (sofas, sectionals/modular components,
8441
+ * tables) — list every configurable product, read one product's complete priced variant grid,
8442
+ * and resolve a free-text product + size + wood finish to the exact live price and SKU, off
8443
+ * the storefront's own live catalog rather than a researched estimate or a hedged price range.
8444
+ */
8445
+ interface Unit {
8446
+ /**
8447
+ * Lists every Maiden Home product configurable by Size x Wood Finish (sofas,
8448
+ * sectionals/modular components, tables) from the storefront's own live catalog — every size
8449
+ * and wood-finish option, its live price range and variant count. `query` (optional) narrows
8450
+ * the list by a fuzzy match on the product title or product type, e.g. "chelsea" or "dining
8451
+ * table".
8452
+ */
8453
+ searchConfigurations(query?: string): Promise<MaidenHomeConfiguratorProduct[]>;
8454
+
8455
+ /**
8456
+ * Reads one configurator product's complete Size x Wood Finish variant grid — a handle, e.g.
8457
+ * "the-chelsea-sofa-heritage-belgian-linen-lake" — every size x finish combination, each with
8458
+ * its own exact live price, SKU and availability. THROWS on an unrecognized handle, naming
8459
+ * searchConfigurations() as the way to find current ones.
8460
+ */
8461
+ getProduct(handle: string): Promise<MaidenHomeConfiguratorProduct>;
8462
+
8463
+ /**
8464
+ * Resolves a free-text product (e.g. "Chelsea Sofa Heritage Belgian Linen Lake"), size (e.g.
8465
+ * "85\"") and wood finish (e.g. "Driftwood Ash") to the exact priced variant and its product
8466
+ * URL, mirroring the on-page configurator's own selection flow. `matched: true` with a
8467
+ * populated `variant` means exactly one real variant narrowed to; otherwise `candidates` lists
8468
+ * every real variant the product query DID match, so a caller can narrow with an exact
8469
+ * size/finish rather than guessing again. Never throws for an ambiguous or zero match — an
8470
+ * unmatched product name is the one case this DOES treat as a caller error (throws, naming
8471
+ * searchConfigurations()).
8472
+ */
8473
+ resolveVariant(productQuery: string, size: string, woodFinish: string): Promise<MaidenHomeVariantResolution>;
8474
+ }
8475
+ }
8476
+
6746
8477
  declare namespace BowmarkProvider_mailchimp {
6747
8478
  // ── Mailchimp — the unit's own declarations, verbatim ──
6748
8479
  interface mailchimpPlanTier {
@@ -7441,6 +9172,96 @@ interface medicareMedigapSearch {
7441
9172
  planTypes: medicareMedigapPlanType[];
7442
9173
  }
7443
9174
 
9175
+ interface medicarePlanDetail {
9176
+ /** CMS's contract-plan-segment triple joined by '-', e.g. "S5884-103-0". */
9177
+ id: string;
9178
+ name: string;
9179
+ nameSpanish: string | null;
9180
+ organization: string;
9181
+ contractId: string;
9182
+ planId: string;
9183
+ segmentId: string;
9184
+ year: number;
9185
+ /** CMS's own category string: "Medicare Advantage" / "Medicare Advantage with
9186
+ * Prescription Drug Coverage" / "Medicare Prescription Drug Plan" /
9187
+ * "Special Needs Plan". */
9188
+ category: string;
9189
+ planType: "PLAN_TYPE_PDP" | "PLAN_TYPE_MA" | "PLAN_TYPE_MAPD" | "PLAN_TYPE_SNP";
9190
+ carrierUrl: string | null;
9191
+ contractYear: string;
9192
+ partcPremium: number;
9193
+ partdPremium: number;
9194
+ partbPremiumReduction: number;
9195
+ /** Annual drug deductible in dollars; 0 means none. PDP only. */
9196
+ drugPlanDeductible: number | null;
9197
+ /** Annual in-network OOP maximum, verbatim. Empty when not published. */
9198
+ maximumOopc: string;
9199
+ /** Per-visit cost strings, verbatim. Empty when CMS publishes no figure —
9200
+ * "$0" (a real benefit) and "" (not published) are deliberately distinct. */
9201
+ primaryDoctorVisitCost: string;
9202
+ specialistDoctorVisitCost: string;
9203
+ emergencyCareCost: string;
9204
+ /** MA/MAPD only — null on PDP, which has no primary/specialist visits. */
9205
+ primaryDoctorCostSharing: string | null;
9206
+ specialistDoctorCostSharing: string | null;
9207
+ /** 1-5 in half steps, or null when CMS publishes none (with starRatingNote
9208
+ * naming the reason — e.g. "too new to be rated"). */
9209
+ starRating: number | null;
9210
+ starRatingNote: string | null;
9211
+ lowPerforming: boolean;
9212
+ highPerforming: boolean;
9213
+ /** All false on a PDP — supplemental benefits live on the Part C side. */
9214
+ supplementalBenefits: {
9215
+ silverSneakers: boolean;
9216
+ transportation: boolean;
9217
+ telehealth: boolean;
9218
+ otcDrugs: boolean;
9219
+ homeSafetyDevices: boolean;
9220
+ inHomeSupport: boolean;
9221
+ supportForCaregivers: boolean;
9222
+ healthEducation: boolean;
9223
+ counselingServices: boolean;
9224
+ emergencyResponseDevice: boolean;
9225
+ worldwideEmergency: boolean;
9226
+ };
9227
+ providerCoverage: {
9228
+ /** False on plans with no network (e.g. PFFS); providers is then reliably empty. */
9229
+ hasProviderCoverageData: boolean;
9230
+ providerCount: number;
9231
+ };
9232
+ /** Extra Help / Low-Income Subsidy dollar amounts at each LIS band. */
9233
+ lis: {
9234
+ level100: number;
9235
+ level75: number;
9236
+ level50: number;
9237
+ level25: number;
9238
+ };
9239
+ snpType: string;
9240
+ dsnpIntegrationLevel: string;
9241
+ /** When CMS marks the plan as terminated for the search year. */
9242
+ terminatedWithoutCrosswalk: string | null;
9243
+ /** Empty when the plan is published in full; the SPA hides fields CMS marks
9244
+ * for redaction and the same fields arrive here. */
9245
+ redactions: string[];
9246
+ }
9247
+
9248
+ interface medicareGetPlanQuery {
9249
+ /** "pdp" | "ma" | "mapd" | "snp" — the caller's MUST match the row they
9250
+ * have in hand. The same (contractId, planId, segmentId) triple does NOT
9251
+ * exist across plan types by design. */
9252
+ planType: "pdp" | "ma" | "mapd" | "snp";
9253
+ /** CMS's contract id (e.g. "S5884" for Part D, "H1234" for Part C). */
9254
+ contractId: string;
9255
+ planId: string;
9256
+ segmentId: string;
9257
+ /** Defaults to the current calendar year — CMS renumbers every January. */
9258
+ year?: number;
9259
+ /** 5-digit US ZIP. Required because the API is keyed on (fips, zip). */
9260
+ zip: string;
9261
+ /** Needed only for the rare ZIP that crosses a state line. */
9262
+ county?: string;
9263
+ }
9264
+
7444
9265
  /**
7445
9266
  * The US government's own Medicare site — Medicare Advantage, Part D and Medigap plan search
7446
9267
  * with real drug-cost estimates, the Care Compare directory of doctors, hospitals, nursing
@@ -7547,7 +9368,27 @@ interface medicareMedigapSearch {
7547
9368
  * coordinates — so `radiusFullyScanned` and `matchesInSearchedZips` carry the same
7548
9369
  * walked-radius honesty split `findDoctors` uses, for the identical reason.
7549
9370
  */
7550
- findHospitals(query: medicareHospitalQuery): Promise<medicareHospitalSearch>;
9371
+ findHospitals(query: medicareHospitalQuery): Promise<medicareHospitalSearch>;
9372
+
9373
+ /**
9374
+ * The full detail of one Part D / MA / MAPD / SNP plan, identified by its CMS
9375
+ * contract-plan-segment triple (e.g. `S5884-103-0` for Part D, `Hxxxx-yyyy-0` for Part C).
9376
+ * Returns the per-visit and per-event cost strings verbatim ('$0', '$20 copay', '20%', or
9377
+ * empty when CMS publishes none), the annual in-network OOP maximum, the supplemental benefits
9378
+ * (dental, fitness, telehealth, OTC drugs, transportation, worldwide emergency — PDPs set them
9379
+ * all to false because the supplemental benefit half is a Part C thing), the CMS star rating
9380
+ * with the explicit reason when none is published (e.g. 'too new to be rated' rather than
9381
+ * rendering a null as a middling rating), the Extra Help / LIS dollar amounts at each band,
9382
+ * the provider-coverage summary, and the carrier's own CMS-published page. `planType` must be
9383
+ * the same discriminator `searchDrugPlans` / a future health-plan search used to find the
9384
+ * triple — the same `(contractId, planId, segmentId)` does NOT exist across plan types by
9385
+ * design, so the wrong one throws. `zip` is required because the API is keyed on (fips, zip),
9386
+ * not on the plan id alone — without it there is no region to ask about. `year` defaults to
9387
+ * the current calendar year. NOTE: the per-visit cost strings are verbatim and the difference
9388
+ * between '$0' (a real zero-cost benefit) and '' (not published) is load-bearing — never
9389
+ * coerce an empty string to 0.
9390
+ */
9391
+ getPlan(arg0: medicareGetPlanQuery): Promise<medicarePlanDetail>;
7551
9392
  }
7552
9393
  }
7553
9394
 
@@ -8472,6 +10313,114 @@ interface ottoSearchQuery {
8472
10313
  }
8473
10314
  }
8474
10315
 
10316
+ declare namespace BowmarkProvider_paypal {
10317
+ // ── PayPal — the unit's own declarations, verbatim ──
10318
+ interface PaypalEstimateFeeArgs {
10319
+ amount: number; // > 0, in `currency`
10320
+ currency: string; // ISO 4217, e.g. "USD"
10321
+ crossBorder: boolean; // sender and recipient in different countries
10322
+ fundingSource: "balance" | "bank" | "card" | "amexSend";
10323
+ }
10324
+ interface PaypalFeeCitation {
10325
+ documentId: string; // the CMS fee-table id this figure came from, e.g. "FEETB20"
10326
+ feeDataKey: string; // the exact published value used, e.g. "2.90%"
10327
+ internalName: string;
10328
+ }
10329
+ interface PaypalFeeEstimate {
10330
+ amount: number;
10331
+ currency: string;
10332
+ crossBorder: boolean;
10333
+ fundingSource: "balance" | "bank" | "card" | "amexSend";
10334
+ fee: number;
10335
+ net: number; // amount - fee
10336
+ citations: PaypalFeeCitation[];
10337
+ }
10338
+ interface PaypalGetFeesArgs {
10339
+ audience?: "consumer"; // defaults to "consumer"; merchant is a separate, unverified page
10340
+ country?: string; // ISO 3166-1 alpha-2, defaults to "us"; only "us" is verified end-to-end
10341
+ }
10342
+ interface PaypalFeeToken {
10343
+ feeDataKey: string; // the exact published value, e.g. "2.90%" or "0.30 USD"
10344
+ internalName: string;
10345
+ percent: number | null; // 0.029 when "2.90%", else null
10346
+ amount: { amount: number; currency: string } | null; // when "0.30 USD", else null
10347
+ }
10348
+ interface PaypalFeeRow {
10349
+ labels: string[]; // plain-text label cells, in cell order
10350
+ tokens: PaypalFeeToken[]; // every published fee token on the row, across all columns
10351
+ cells: string[]; // plain-text rendering of each cell, in cell order
10352
+ noFee: boolean; // true iff the row carries no fee token (PayPal's "No fee" rows)
10353
+ citations: PaypalFeeCitation[];
10354
+ }
10355
+ interface PaypalFeeTable {
10356
+ documentId: string; // the CMS fee-table id, e.g. "FEETB20"
10357
+ caption: string; // PayPal's own caption, e.g. "Sending domestic personal transactions"
10358
+ rows: PaypalFeeRow[];
10359
+ }
10360
+ interface PaypalFeeSchedule {
10361
+ audience: "consumer";
10362
+ country: string; // lowercased to match PayPal's URL path, e.g. "us"
10363
+ sourceUrl: string;
10364
+ tables: PaypalFeeTable[];
10365
+ }
10366
+ type PaypalConversionKind = "goodsOrServices" | "personal" | "payouts" | "other";
10367
+ interface PaypalCurrencyConversionCitation {
10368
+ documentId: string; // the CMS table id this figure came from, e.g. "FEETB26"
10369
+ feeDataKey: string; // the exact published value used, e.g. "4.00%"
10370
+ internalName: string;
10371
+ }
10372
+ interface PaypalGetCurrencyConversionQuoteArgs {
10373
+ kind?: PaypalConversionKind; // "goodsOrServices" | "personal" | "payouts" | "other"
10374
+ audience?: "consumer"; // defaults to "consumer"; merchant is a separate, unverified page
10375
+ country?: string; // ISO 3166-1 alpha-2, defaults to "us"; only "us" is verified end-to-end
10376
+ }
10377
+ interface PaypalCurrencyConversionQuote {
10378
+ kind: PaypalConversionKind; // which PayPal-conversion context the spread applies to
10379
+ paypalSpread: number; // 0.04 for goodsOrServices/personal/payouts; 0.03 for "other"
10380
+ citations: { paypal: PaypalCurrencyConversionCitation };
10381
+ }
10382
+
10383
+ /**
10384
+ * PayPal's public, signed-out surfaces: the published consumer and merchant fee schedules, the
10385
+ * fee on one concrete personal (friends-and-family) transaction, the spread PayPal adds on a
10386
+ * currency conversion, Pay Later instalment plans, PayPal.Me handle lookup, Help Center search
10387
+ * and articles, the binding policy documents, PayPal Shopping cashback offers, crypto prices,
10388
+ * and invoice payer-view reads. Three functions callable today — estimateFee, getFees,
10389
+ * getCurrencyConversionQuote.
10390
+ */
10391
+ interface Unit {
10392
+ /**
10393
+ * Computes what PayPal charges to send a PERSONAL (friends-and-family) payment — domestic or
10394
+ * cross-border, by funding source — off PayPal's own published fee schedule, e.g.
10395
+ * estimateFee({ amount: 100, currency: "USD", crossBorder: false, fundingSource: "card" }) ->
10396
+ * { fee: 3.2, net: 96.8, citations: [...] }. Does not (yet) cover goods-and-services/merchant
10397
+ * transactions, a separate page nobody has walked.
10398
+ */
10399
+ estimateFee(args: PaypalEstimateFeeArgs): Promise<PaypalFeeEstimate>;
10400
+
10401
+ /**
10402
+ * Reads PayPal's published fee schedule for one audience / country pair and returns every fee
10403
+ * table on the page — every row, every published feeDataKey, with documentId-level citations —
10404
+ * so a caller can inspect the schedule itself rather than asking about one amount. Currently
10405
+ * consumer / us only; merchant is on a separate unverified page and other countries have not
10406
+ * been fetched.
10407
+ */
10408
+ getFees(args: PaypalGetFeesArgs): Promise<PaypalFeeSchedule>;
10409
+
10410
+ /**
10411
+ * Reads PayPal's published currency-conversion spread — the half of its fee it DOES disclose —
10412
+ * off the same fees page (FEETB26, 4.00% for goodsOrServices/personal/payouts, 3.00% for
10413
+ * "other"), e.g. getCurrencyConversionQuote({ kind: "goodsOrServices" }) -> { kind:
10414
+ * "goodsOrServices", paypalSpread: 0.04, citations: { paypal: { documentId: "FEETB26",
10415
+ * feeDataKey: "4.00%", internalName: "..." } } }. PayPal does NOT publish the wholesale base
10416
+ * rate, so this function returns only the spread; combining it with a base rate from another
10417
+ * provider (e.g. bowmark.providers.oanda.convertCurrency) is the capability tier's job, not a
10418
+ * single provider's. consumer / us only today.
10419
+ */
10420
+ getCurrencyConversionQuote(args: PaypalGetCurrencyConversionQuoteArgs): Promise<PaypalCurrencyConversionQuote>;
10421
+ }
10422
+ }
10423
+
8475
10424
  declare namespace BowmarkProvider_pirateship {
8476
10425
  // ── Pirate Ship — the unit's own declarations, verbatim ──
8477
10426
  interface PirateshipDimensions {
@@ -8652,17 +10601,100 @@ interface PizzahutMenuItemWeight {
8652
10601
  priceCents: number; // what THIS option costs on THIS variant — varies by size
8653
10602
  }
8654
10603
 
10604
+ // ── getMenu ───────────────────────────────────────────────────────────────
10605
+ interface PizzahutMenuArgs {
10606
+ storeNumber: string;
10607
+ }
10608
+
10609
+ interface PizzahutMenuVariant {
10610
+ variantCode: string;
10611
+ name: string | null;
10612
+ priceCents: number;
10613
+ attributes: string[]; // e.g. ["Original Pan® Pizza", "Personal Pan"]
10614
+ }
10615
+
10616
+ interface PizzahutMenuListItem {
10617
+ productCode: string;
10618
+ name: string | null;
10619
+ description: string | null;
10620
+ categoryCode: string;
10621
+ categoryName: string;
10622
+ currency: string;
10623
+ variants: PizzahutMenuVariant[];
10624
+ }
10625
+
10626
+ interface PizzahutMenuCategory {
10627
+ categoryCode: string;
10628
+ categoryName: string;
10629
+ items: PizzahutMenuListItem[];
10630
+ }
10631
+
10632
+ interface PizzahutMenu {
10633
+ storeNumber: string;
10634
+ currency: string;
10635
+ categories: PizzahutMenuCategory[];
10636
+ }
10637
+
10638
+ // ── getDeals ──────────────────────────────────────────────────────────────
10639
+ // Mirrors the public types declared at the top of this file (PizzahutDeals,
10640
+ // PizzahutDeal, PizzahutDealImage, PizzahutDealScope) — copied here so the
10641
+ // rendered get_library blurb and the catalog signature are types the
10642
+ // gateway can resolve. The exported shapes are the source of truth.
10643
+ type PizzahutDealScopeForRender = "all" | { storeNumbers: string[] };
10644
+
10645
+ interface PizzahutDealImageForRender {
10646
+ url: string;
10647
+ title: string | null;
10648
+ }
10649
+
10650
+ interface PizzahutDealForRender {
10651
+ position: number | null;
10652
+ code: string;
10653
+ name: string;
10654
+ description: string | null;
10655
+ legalText: string | null;
10656
+ appImage: PizzahutDealImageForRender | null;
10657
+ webImage: PizzahutDealImageForRender | null;
10658
+ }
10659
+
10660
+ interface PizzahutDealsForRender {
10661
+ storeNumber: string;
10662
+ deals: PizzahutDealForRender[];
10663
+ sources: { name: string; scope: PizzahutDealScopeForRender }[];
10664
+ }
10665
+
8655
10666
  /**
8656
10667
  * Pizza Hut's US ordering site. `findStores` returns the stores serving any US address or ZIP,
8657
10668
  * nearest first, with each one's number, hours, distance, phone and the terms of the carryout
8658
- * and delivery it offers. `getMenuItem` reads one item's full store-level configuration by
8659
- * name every size/crust, and every optional topping/sauce/cheese slot with what each choice
8660
- * costs on THAT variant. `priceOrder` then prices a basket at one of those stores WITHOUT
8661
- * placing it line items, subtotal, sales tax, delivery fee and the real total Pizza Hut
8662
- * would charge, for carryout or to a delivery address, anonymously. Browsing the full menu
8663
- * list and reading the current deals are still stubs.
10669
+ * and delivery it offers. `getMenu` reads a store's whole menu every category, every item,
10670
+ * and every variant's price at THAT store. `getMenuItem` reads one item's full store-level
10671
+ * configuration by name every size/crust, and every optional topping/sauce/cheese slot with
10672
+ * what each choice costs on THAT variant. `getDeals` reads the deals and bundle offers Pizza
10673
+ * Hut is running AT ONE STORE right now, filtered to what is actually redeemable there.
10674
+ * `priceOrder` then prices a basket at one of those stores WITHOUT placing it — line items,
10675
+ * subtotal, sales tax, delivery fee and the real total Pizza Hut would charge, for carryout or
10676
+ * to a delivery address, anonymously.
8664
10677
  */
8665
10678
  interface Unit {
10679
+ /**
10680
+ * Reads a store's whole menu — every category (pizza, wings, pasta, sides, desserts, drinks,
10681
+ * dips, melts, …), every item in each, and each item's variants with their price AT THAT
10682
+ * STORE, all in cents. `storeNumber` comes from `findStores` and is required because Pizza
10683
+ * Hut's prices are store-level — measured 2026-08-07, the same Pepperoni Pizza was $5.50 /
10684
+ * $20.08 at store 026196 (North Hollywood CA) and $6.69 / $12.99 at store 027278 (Plano TX),
10685
+ * all 11 variants differing between the two, so omitting the store would silently return
10686
+ * whatever default the site happens to serve. One GraphQL read returns the whole menu in a
10687
+ * single ~200 KB response (measured 2026-08-07 on store 026196: 20 categories, 138 items, 731
10688
+ * variants, 731/731 with prices), so no fan-out is needed. Bundle items and bare-variant
10689
+ * category items are out of scope — they are not configurable products — same exclusion as
10690
+ * `flattenProductCatalog`. A variant is the priced configuration (size + crust already in
10691
+ * `variantCode`), so a `variantCode` read here plus a `slotCode` / `modifierCode` /
10692
+ * `modifierWeightCode` triple from `getMenuItem` is everything `priceOrder` needs to price a
10693
+ * configured basket. Wholly anonymous: no account, no session, no identity of any kind, same
10694
+ * guest-token read `priceOrder` and `getMenuItem` use.
10695
+ */
10696
+ getMenu(args: { storeNumber: string }): Promise<PizzahutMenu>;
10697
+
8666
10698
  /**
8667
10699
  * Finds the Pizza Hut stores that serve a US location — each store's number, street address,
8668
10700
  * phone, opening hours, straight-line distance, online status, and the terms of every
@@ -8730,6 +10762,91 @@ interface PizzahutMenuItemWeight {
8730
10762
  * identifying.
8731
10763
  */
8732
10764
  getMenuItem(args: { storeNumber: string; item: string; category?: string }): Promise<PizzahutMenuItem>;
10765
+
10766
+ /**
10767
+ * Reads the deals, coupons and bundle offers Pizza Hut is running AT ONE STORE right now —
10768
+ * every deal that applies there, its bundle code, display name, description and legal text, in
10769
+ * the order the site puts them on the deals page. `storeNumber` comes from `findStores` and is
10770
+ * REQUIRED: Pizza Hut runs national deals AND franchise-local ones, and a deal listed but not
10771
+ * available at the caller's store is the honest-vs-misleading line — the function filters by
10772
+ * `MenuDealPageSortOverride.storesList` (a comma-separated list of stores, or the literal
10773
+ * "ALL") so a caller gets only what is actually redeemable where they asked. The store's deals
10774
+ * page lives on Contentful (NOT the Yum storefront GraphQL the rest of the provider hits): the
10775
+ * deals page's own `__NEXT_DATA__.runtimeConfig` publishes `CONTENTFUL_SPACE_ID` +
10776
+ * `CONTENTFUL_ACCESS_TOKEN` + `CONTENTFUL_ENVIRONMENT` + `CONTENTFUL_BASE_URL`, and this reads
10777
+ * them out of the page rather than asking the caller for them. The bootstrap throws on a
10778
+ * missing payload the way `parsePhdConfig` does — a 200 without the runtimeConfig is the
10779
+ * Canadian site, and serving a caller the wrong country’s deals is worse than no answer. The
10780
+ * list is sorted by `dealPagePosition` (1-based, lower = higher up); positions the site leaves
10781
+ * null fall back to a stable code-order tiebreak rather than being treated as "first". Wholly
10782
+ * anonymous, one Contentful read per call.
10783
+ */
10784
+ getDeals(args: { storeNumber: string }): Promise<PizzahutDealsForRender>;
10785
+ }
10786
+ }
10787
+
10788
+ declare namespace BowmarkProvider_premierbuildings {
10789
+ // ── Premier Portable Buildings — the unit's own declarations, verbatim ──
10790
+ interface PremierbuildingsStyle {
10791
+ key: string;
10792
+ label: string;
10793
+ sidingOptions: string[];
10794
+ sizes: { sizeKey: string; width: number; length: number }[];
10795
+ }
10796
+ interface PremierbuildingsPrice {
10797
+ styleKey: string;
10798
+ model: string;
10799
+ sizeKey: string;
10800
+ width: number;
10801
+ length: number;
10802
+ sidingKey: string;
10803
+ zip: string;
10804
+ region: string;
10805
+ basePrice: number;
10806
+ sidingSurcharge: number;
10807
+ total: number;
10808
+ currency: "USD";
10809
+ }
10810
+ interface PremierbuildingsDealer {
10811
+ key: string;
10812
+ name: string;
10813
+ city: string;
10814
+ state: string;
10815
+ zip: string;
10816
+ phoneNumber: string;
10817
+ dealerURL: string;
10818
+ }
10819
+
10820
+ /**
10821
+ * Reads Premier Portable Buildings' own ShedView 3D configurator pricing catalogue — building
10822
+ * styles, real available sizes, and region-exact siding surcharges — plus its real dealer
10823
+ * directory.
10824
+ */
10825
+ interface Unit {
10826
+ /**
10827
+ * 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.
10830
+ */
10831
+ listBuildingStyles(): Promise<PremierbuildingsStyle[]>;
10832
+
10833
+ /**
10834
+ * Prices one real Premier building configuration exactly the way ShedView itself does: the
10835
+ * base price for `styleKey` + `sizeKey` in the pricing region `zip` falls under, plus the
10836
+ * EXACT siding surcharge Premier's own rules add for `sidingKey` at that width and region (0
10837
+ * for the default "urethane-siding"; a real dollar amount, never a guess, for an alternative
10838
+ * like "metal" — the surcharge genuinely varies by both region and building width).
10839
+ * `sidingKey` defaults to "urethane-siding" (Premier's standard siding) when omitted.
10840
+ */
10841
+ priceBuilding(styleKey: string, sizeKey: string, sidingKey: string | undefined, zip: string): Promise<PremierbuildingsPrice>;
10842
+
10843
+ /**
10844
+ * Looks up Premier's real dealer locations in one US state or Canadian province (accepts
10845
+ * either a full name like "Tennessee" or an abbreviation like "TN") — name, city, phone, and
10846
+ * the dealer's own ShedView URL, straight from Premier's live dealer directory, for handing a
10847
+ * priced configuration off to order.
10848
+ */
10849
+ findDealers(state: string): Promise<PremierbuildingsDealer[]>;
8733
10850
  }
8734
10851
  }
8735
10852
 
@@ -9975,6 +12092,38 @@ interface SearsProduct {
9975
12092
  description: string | null;
9976
12093
  specifications: SearsProductSpecification[];
9977
12094
  }
12095
+ interface SearsShippingAvailability {
12096
+ available: boolean;
12097
+ availableQuantity: number | null;
12098
+ ffmType: string | null;
12099
+ shipModes: string[];
12100
+ dcUnitId: string | null;
12101
+ promiseDate: string | null;
12102
+ autoUpgrade: boolean;
12103
+ freeShipping: boolean;
12104
+ freeEligible: boolean;
12105
+ freeQualified: boolean;
12106
+ }
12107
+ interface SearsStockStore {
12108
+ unitId: string | null;
12109
+ storeName: string | null;
12110
+ storeBrand: string | null;
12111
+ storeAddress: string | null;
12112
+ promiseDate: string | null;
12113
+ ffmType: string | null;
12114
+ }
12115
+ interface SearsPickupAvailability {
12116
+ available: boolean;
12117
+ stores: SearsStockStore[];
12118
+ message: string | null;
12119
+ }
12120
+ interface SearsStock {
12121
+ productId: string;
12122
+ zipCode: string;
12123
+ quantity: number;
12124
+ shipping: SearsShippingAvailability | null;
12125
+ pickup: SearsPickupAvailability;
12126
+ }
9978
12127
 
9979
12128
  /** Sears' own storefront — product search, product detail, fulfillment/stock and store locator. */
9980
12129
  interface Unit {
@@ -9998,6 +12147,67 @@ interface SearsProduct {
9998
12147
  * default (New York, 10101). THROWS on an id the site does not recognise.
9999
12148
  */
10000
12149
  getProduct(idOrUrl: string, opts?: { zipCode?: string }): Promise<SearsProduct>;
12150
+
12151
+ /**
12152
+ * Answers whether a Sears product is buyable right now — for shipping/delivery AND for
12153
+ * in-store/curbside pickup — the way the product page's own fulfillment panel does, in one
12154
+ * call. `shipping` carries the site's own available quantity, ship modes and promise date.
12155
+ * `pickup.stores` is the stores the site found able to fulfil it near `zipCode` — routinely
12156
+ * empty (Sears' physical footprint has shrunk sharply), which is a real, common answer, not an
12157
+ * error; `pickup.message` carries the site's own explanation when it is. `zipCode` narrows the
12158
+ * search the way the site's own zip cookie does; omit it for the site's own default (New York,
12159
+ * 10101). Takes the product id or URL from `search`/`getProduct` — same as `getProduct`.
12160
+ */
12161
+ checkStock(idOrUrl: string, opts?: { zipCode?: string; quantity?: number }): Promise<SearsStock>;
12162
+ }
12163
+ }
12164
+
12165
+ declare namespace BowmarkProvider_seegarsfence {
12166
+ // ── Seegars Fence Company — the unit's own declarations, verbatim ──
12167
+ interface SeegarsBranch {
12168
+ id: number;
12169
+ name: string;
12170
+ address1: string;
12171
+ city: string;
12172
+ state: string;
12173
+ zip: string;
12174
+ salesEmail: string;
12175
+ salesPhone: string;
12176
+ webSite: string;
12177
+ outsideServiceAreaText: string;
12178
+ serviceArea: string;
12179
+ }
12180
+
12181
+ interface SeegarsGeocodedAddress {
12182
+ address1: string;
12183
+ city: string;
12184
+ state: string;
12185
+ zip: string;
12186
+ displayName: string;
12187
+ latitude: number;
12188
+ longitude: number;
12189
+ }
12190
+
12191
+ interface CheckServiceAreaResult {
12192
+ address: SeegarsGeocodedAddress;
12193
+ inServiceArea: boolean;
12194
+ branch: SeegarsBranch;
12195
+ }
12196
+
12197
+ /**
12198
+ * Fence/gate installer (Carolinas). checkServiceArea is live — geocodes an address and reports
12199
+ * whether it's inside Seegars' service area, plus the branch that would handle it.
12200
+ * estimateFencePrice (the actual priced estimate) is a stub — see its notImplemented reason.
12201
+ */
12202
+ interface Unit {
12203
+ /**
12204
+ * Geocodes a free-text address (`address`, e.g. "301 Fayetteville St, Raleigh, NC 27601")
12205
+ * against Seegars Fence's own address-lookup API, then checks it against the branch's
12206
+ * published service-area polygon — the same check the site's own Fence Price Estimator Tool
12207
+ * performs before it will show any pricing. Returns the normalized address, whether it falls
12208
+ * inside the service area, and the branch (name, phone, email, address) that would handle it.
12209
+ */
12210
+ checkServiceArea(args: object): Promise<CheckServiceAreaResult>;
10001
12211
  }
10002
12212
  }
10003
12213
 
@@ -10555,40 +12765,286 @@ interface StatefarmBusinessCoverage {
10555
12765
  * different things, so "State Farm will not cover you" can never be mistaken for "we could not
10556
12766
  * read the page".
10557
12767
  */
10558
- getRentersQuote(query: StatefarmRentersQuoteQuery | string): Promise<StatefarmRentersQuote>;
12768
+ getRentersQuote(query: StatefarmRentersQuoteQuery | string): Promise<StatefarmRentersQuote>;
12769
+
12770
+ /**
12771
+ * Prices a State Farm Business Owners Policy — commercial property and liability bundled — for
12772
+ * one small business, and returns the carrier's own rated numbers: the assumed monthly
12773
+ * instalment, the full 12-month premium, the deductible the price assumes, every named
12774
+ * discount that moved it, and all ~60 coverages in the bundle with which are actually switched
12775
+ * on. Measured 2026-08-01: an accounting LLC in Springfield IL is $52.92/mo and $635 for the
12776
+ * term on a $1,000 deductible with 38 of 60 coverages selected, while an attorneys'
12777
+ * corporation in Austin TX is $57.66/mo and $691.92 with 37 of 59 — the coverage counts differ
12778
+ * because State Farm rates a BOP off state forms, so the SAME business is a different policy
12779
+ * in a different state. This is the commercial line, not a personal one, so it asks for facts
12780
+ * no personal-lines quote does: the trade classification, whether the premises are tenanted or
12781
+ * owner-occupied, floor area, year built, gross annual receipts, headcount and the business
12782
+ * personal property to insure. None of them is defaulted, because a defaulted square footage
12783
+ * returns a real premium for a business that does not exist. It is a RATE LOOKUP that State
12784
+ * Farm will not perform anonymously: the engine refuses to price until it has the owner's
12785
+ * name, date of birth, email and phone, so `identity` is a required argument carrying the
12786
+ * CALLER's own details, passed at call time and never held. The four underwriting answers are
12787
+ * required too and are deliberately not defaulted — State Farm refuses an online quote
12788
+ * outright to a business with a loss in the past five years or an existing State Farm business
12789
+ * policy, so answering those on the caller's behalf would hand back a price the carrier would
12790
+ * not have given them. What comes back is a price, not an offer, and State Farm's own words
12791
+ * for that are returned verbatim as `disclaimer`. Where State Farm declines to quote online it
12792
+ * says WHY rather than returning nothing: `StatefarmBusinessNotQuotable` carries the carrier's
12793
+ * own reason code and a severity, and the two mean opposite things — a SOFT kickout (an
12794
+ * unsupported trade, an owner-occupied building, a religious or government organisation) means
12795
+ * an agent writes that policy, while a HARD one (11 states, a prior loss, an existing policy)
12796
+ * means there is no online quote to be had at all. Commercial auto and workers' compensation
12797
+ * are NOT this function: State Farm's own application router sends commercial auto to a
12798
+ * no-quote page and publishes no online application for workers' comp, contractors or
12799
+ * farm-and-ranch.
12800
+ */
12801
+ getBusinessQuote(query: StatefarmBusinessQuoteQuery): Promise<StatefarmBusinessQuote>;
12802
+ }
12803
+ }
12804
+
12805
+ declare namespace BowmarkProvider_stickergiant {
12806
+ // ── StickerGiant — the unit's own declarations, verbatim ──
12807
+ // StickerGiant's OWN shape — not a capability contract.
12808
+
12809
+ interface StickergiantListArgs {
12810
+ format?: string; // optional material code filter, e.g. "WHP"
12811
+ }
12812
+
12813
+ interface StickergiantProduct {
12814
+ url: string; // The configurator's own entry URL — durable key
12815
+ name: string; // "Individual Stickers (Die Cut) - White"
12816
+ sku: string; // The site's own material code, e.g. "WHP"
12817
+ priceUsd: string; // "$37.90" — per-100 stickers starting price
12818
+ priceValue: number; // Same number unformatted
12819
+ priceCurrency: string; // "USD"
12820
+ availability: string; // Schema.org URL, e.g. "https://schema.org/InStock"
12821
+ imageUrl: string;
12822
+ }
12823
+
12824
+ interface StickergiantBuild {
12825
+ widthInches: number; // required, from SITE_SIZES
12826
+ heightInches: number; // required, from SITE_SIZES
12827
+ lamination: "OGL" | "MAL"; // required — Outdoor Gloss / Matte
12828
+ quantity?: number; // optional — omit for the full 15-tier ladder back
12829
+ }
12830
+
12831
+ interface StickergiantQuantityPrice {
12832
+ quantity: number;
12833
+ price: number; // the pricing engine's own total (not the rendered 'Total')
12834
+ pricePerUnit: number;
12835
+ }
12836
+
12837
+ interface StickergiantPriceResult {
12838
+ selections: { // echoes back what the engine actually priced
12839
+ widthInches: number;
12840
+ heightInches: number;
12841
+ lamination: "OGL" | "MAL";
12842
+ product: string; // "DCU" — the only product the API honors
12843
+ material: string; // "WHP" — the only material the API honors
12844
+ };
12845
+ selectedQuantity?: StickergiantQuantityPrice; // when caller passed quantity
12846
+ quantityPrices: StickergiantQuantityPrice[]; // always: the full 15-tier ladder
12847
+ }
12848
+
12849
+ /**
12850
+ * StickerGiant's sticker configurator and its published catalog — every sticker SKU on
12851
+ * /custom-stickers with its real starting price, material code and configurator entry URL.
12852
+ */
12853
+ interface Unit {
12854
+ /**
12855
+ * Lists every sticker SKU the /custom-stickers page publishes — name, the configurator's
12856
+ * material URL, the site's own material code (sku), the per-100-stickers starting price the
12857
+ * page carries in its schema.org Product block, the price currency, availability, and the
12858
+ * page's hero image. Optional { format } restricts to one material code (e.g. 'WHP' for Die
12859
+ * Cut White). THROWS rather than returning [] when the page carries no schema.org Product
12860
+ * blocks or when the format filter names an unknown code — both are honest failure modes and
12861
+ * an empty array would read as 'StickerGiant sells no stickers', which is the
12862
+ * confident-wrong-answer failure this provider exists to avoid.
12863
+ */
12864
+ listStickerProducts(args?: StickergiantListArgs): Promise<StickergiantProduct[]>;
12865
+
12866
+ /**
12867
+ * Prices one exact custom-sticker build against Sticker Giant's own live pricing backend (POST
12868
+ * prod.pricing-backend.service.stickergiant.com/item) and returns the full 15-tier quantity
12869
+ * ladder — each tier's price and price-per-unit. With a `quantity` passed, the response also
12870
+ * carries a `selectedQuantity` with the priced value for that exact qty. The returned `price`
12871
+ * is the pricing engine's own canonical number (not the rendered 'Total' on the page, which
12872
+ * carries a small UI markup). THROWS on a missing lamination or out-of-range width/height —
12873
+ * both are caller-fixable.
12874
+ */
12875
+ priceCustomSticker(build: StickergiantBuild): Promise<StickergiantPriceResult>;
12876
+ }
12877
+ }
12878
+
12879
+ declare namespace BowmarkProvider_sunhomesaunas {
12880
+ // ── Sun Home Saunas — the unit's own declarations, verbatim ──
12881
+ // Sun Home Saunas' OWN shapes — not a capability contract.
12882
+
12883
+ interface SunHomeSaunasQuizOption {
12884
+ id: string;
12885
+ label: string;
12886
+ }
12887
+
12888
+ interface SunHomeSaunasQuizQuestion {
12889
+ id: string; // pass back as answers[].questionId
12890
+ title: string;
12891
+ type: string; // the site's own node type, e.g. "SIMPLE_MULTI"
12892
+ options: SunHomeSaunasQuizOption[]; // option.id -> answers[].optionIds
12893
+ }
12894
+
12895
+ interface SunHomeSaunasMatch {
12896
+ handle: string; // the key addSaunaToCart takes
12897
+ title: string;
12898
+ price: number; // dollars — real live Shopify price
12899
+ matchScore: number; // e.g. 5
12900
+ matchOutOf: number; // e.g. 5 -> the site's own "5/5 match"
12901
+ }
12902
+
12903
+ interface SunHomeSaunasCartResult {
12904
+ handle: string;
12905
+ title: string;
12906
+ variantId: number;
12907
+ linePrice: number; // dollars, for the quantity added
12908
+ quantity: number;
12909
+ cartItemCount: number; // the live cart's total items AFTER this add
12910
+ cartTotal: number; // dollars — the live cart's total price after this add
12911
+ }
12912
+
12913
+ /**
12914
+ * Sun Home Saunas' real Perfect Product Finder quiz — the site's own 5-question buyer quiz,
12915
+ * its real server-computed ranked product matches with live prices, and a real Shopify cart
12916
+ * write for the winning match — no login, no dealer routing.
12917
+ */
12918
+ interface Unit {
12919
+ /**
12920
+ * Reads Sun Home Saunas' real, live Perfect Product Finder quiz straight off its quiz vendor's
12921
+ * own API — the current 5 questions and every real option, with the real ids
12922
+ * getPersonalizedSaunaMatches() needs to answer them.
12923
+ */
12924
+ getSaunaFinderQuestions(): Promise<SunHomeSaunasQuizQuestion[]>;
12925
+
12926
+ /**
12927
+ * Submits real answers (from getSaunaFinderQuestions()) through the same quiz session flow the
12928
+ * site's own UI uses, and returns the site's own SERVER-COMPUTED ranked product matches with
12929
+ * real live prices and a real match score — the exact personalized result a real buyer would
12930
+ * see, never a guess from general knowledge.
12931
+ */
12932
+ getPersonalizedSaunaMatches(answers: {questionId: string, optionIds: string[]}[]): Promise<SunHomeSaunasMatch[]>;
12933
+
12934
+ /**
12935
+ * Adds one real matched sauna (a handle from getPersonalizedSaunaMatches()) to a real Shopify
12936
+ * cart at Sun Home Saunas' own real live price, and reads the cart back to confirm the write
12937
+ * landed. THROWS if the product is currently out of stock.
12938
+ */
12939
+ addSaunaToCart(handle: string, quantity?: number): Promise<SunHomeSaunasCartResult>;
12940
+ }
12941
+ }
12942
+
12943
+ declare namespace BowmarkProvider_target {
12944
+ // ── Target — the unit's own declarations, verbatim ──
12945
+ interface targetRow {
12946
+ id: string;
12947
+ }
12948
+
12949
+ interface TargetStoreHoursInterval {
12950
+ begin_time: string;
12951
+ end_date: string;
12952
+ end_time: string;
12953
+ }
12954
+
12955
+ interface TargetStoreHoursDay {
12956
+ is_open: boolean;
12957
+ date: string;
12958
+ day_name: string;
12959
+ hours: TargetStoreHoursInterval[];
12960
+ }
12961
+
12962
+ interface TargetStoreGeoSpec {
12963
+ iso_time_zone_code: string;
12964
+ time_zone_code: string;
12965
+ time_zone_utc_offset_name: string;
12966
+ }
12967
+
12968
+ interface TargetStore {
12969
+ id: string;
12970
+ slug: string;
12971
+ name: string;
12972
+ address: string;
12973
+ phone: string | null;
12974
+ geoSpec: TargetStoreGeoSpec | null;
12975
+ weeklyHours: TargetStoreHoursDay[];
12976
+ }
12977
+
12978
+ interface TargetStoreSearch {
12979
+ query: string;
12980
+ stores: TargetStore[];
12981
+ warnings: string[];
12982
+ }
12983
+
12984
+ /**
12985
+ * Big-box general merchandise — search, product detail, store stock and store lookup on
12986
+ * target.com.
12987
+ */
12988
+ interface Unit {
12989
+ /**
12990
+ * Searches the store-locator for nearby Targets by ZIP, partial ZIP, city, or street+city, and
12991
+ * returns each store's id, slug, name, address, phone, time-zone and 14-day weekly hours.
12992
+ */
12993
+ findStore(args: { query: string }): Promise<TargetStoreSearch>;
12994
+ }
12995
+ }
12996
+
12997
+ declare namespace BowmarkProvider_teladoc {
12998
+ // ── Teladoc Health — the unit's own declarations, verbatim ──
12999
+ interface teladocRow {
13000
+ id: string;
13001
+ }
13002
+
13003
+ interface teladocPricingRow {
13004
+ service: string;
13005
+ priceUsd: number;
13006
+ unit: "visit" | "review" | null;
13007
+ href: string | null;
13008
+ }
13009
+
13010
+ interface teladocPricing {
13011
+ source: string;
13012
+ disclaimer: string;
13013
+ services: teladocPricingRow[];
13014
+ }
13015
+
13016
+ interface teladocInsuranceCoverage {
13017
+ source: string;
13018
+ headline: string;
13019
+ headlinePriceUsd: number;
13020
+ services: string[];
13021
+ disclaimer: string;
13022
+ }
13023
+
13024
+ /**
13025
+ * Virtual-care company: searches its public Health Library and self-pay visit pricing. Booking
13026
+ * a visit requires a member login and is out of scope.
13027
+ */
13028
+ interface Unit {
13029
+ /**
13030
+ * Returns Teladoc's published self-pay (no-insurance) visit pricing — the per-visit dollar
13031
+ * amount for each service line (24/7 Urgent Care, Nutrition, Dermatology, Mental Health), the
13032
+ * unit (visit vs review), the page's own eligibility disclaimer, and the source URL. THROWS
13033
+ * when the no-insurance tile renders without a price list (a real re-skin, not a zero-priced
13034
+ * answer).
13035
+ */
13036
+ getPricing(): Promise<teladocPricing>;
10559
13037
 
10560
13038
  /**
10561
- * Prices a State Farm Business Owners Policy commercial property and liability bundled — for
10562
- * one small business, and returns the carrier's own rated numbers: the assumed monthly
10563
- * instalment, the full 12-month premium, the deductible the price assumes, every named
10564
- * discount that moved it, and all ~60 coverages in the bundle with which are actually switched
10565
- * on. Measured 2026-08-01: an accounting LLC in Springfield IL is $52.92/mo and $635 for the
10566
- * term on a $1,000 deductible with 38 of 60 coverages selected, while an attorneys'
10567
- * corporation in Austin TX is $57.66/mo and $691.92 with 37 of 59 — the coverage counts differ
10568
- * because State Farm rates a BOP off state forms, so the SAME business is a different policy
10569
- * in a different state. This is the commercial line, not a personal one, so it asks for facts
10570
- * no personal-lines quote does: the trade classification, whether the premises are tenanted or
10571
- * owner-occupied, floor area, year built, gross annual receipts, headcount and the business
10572
- * personal property to insure. None of them is defaulted, because a defaulted square footage
10573
- * returns a real premium for a business that does not exist. It is a RATE LOOKUP that State
10574
- * Farm will not perform anonymously: the engine refuses to price until it has the owner's
10575
- * name, date of birth, email and phone, so `identity` is a required argument carrying the
10576
- * CALLER's own details, passed at call time and never held. The four underwriting answers are
10577
- * required too and are deliberately not defaulted — State Farm refuses an online quote
10578
- * outright to a business with a loss in the past five years or an existing State Farm business
10579
- * policy, so answering those on the caller's behalf would hand back a price the carrier would
10580
- * not have given them. What comes back is a price, not an offer, and State Farm's own words
10581
- * for that are returned verbatim as `disclaimer`. Where State Farm declines to quote online it
10582
- * says WHY rather than returning nothing: `StatefarmBusinessNotQuotable` carries the carrier's
10583
- * own reason code and a severity, and the two mean opposite things — a SOFT kickout (an
10584
- * unsupported trade, an owner-occupied building, a religious or government organisation) means
10585
- * an agent writes that policy, while a HARD one (11 states, a prior loss, an existing policy)
10586
- * means there is no online quote to be had at all. Commercial auto and workers' compensation
10587
- * are NOT this function: State Farm's own application router sends commercial auto to a
10588
- * no-quote page and publishes no online application for workers' comp, contractors or
10589
- * farm-and-ranch.
13039
+ * Returns the with-insurance side of /start/no-insurancethe page's own headline figure (a
13040
+ * literal '$0*' on the live page, since the per-plan price lives behind member.teladoc.com and
13041
+ * is out of scope), the services the page promises are 'Included in your coverage*' (Primary
13042
+ * Care, 24/7 Care, Mental Health, And more!), and the same eligibility disclaimer as
13043
+ * `getPricing`. THROWS when the with-insurance tile renders without its service list, so a
13044
+ * re-skin that drops the second tile or rewrites it in a way this parser cannot read surfaces
13045
+ * as an error rather than an empty answer.
10590
13046
  */
10591
- getBusinessQuote(query: StatefarmBusinessQuoteQuery): Promise<StatefarmBusinessQuote>;
13047
+ getInsurancePricing(): Promise<teladocInsuranceCoverage>;
10592
13048
  }
10593
13049
  }
10594
13050
 
@@ -10684,6 +13140,82 @@ interface TentreeCart {
10684
13140
  }
10685
13141
  }
10686
13142
 
13143
+ declare namespace BowmarkProvider_therabody {
13144
+ // ── Therabody — the unit's own declarations, verbatim ──
13145
+ interface TherabodyVariant {
13146
+ /** Shopify's numeric variant id as a string. The future addToCart entry. */
13147
+ id: string;
13148
+ /** The variant's own label, e.g. "Default Title". */
13149
+ title: string;
13150
+ /** Decimal string exactly as the store publishes it, e.g. "54998" (cents). */
13151
+ price: string;
13152
+ /** Same scale as price. Null when the product is not on sale. */
13153
+ compareAtPrice: string | null;
13154
+ /** The store's own SKU. Null on a product without one. */
13155
+ sku: string | null;
13156
+ /** Whether the variant is purchasable right now. */
13157
+ available: boolean;
13158
+ options: string[];
13159
+ }
13160
+ interface TherabodyProduct {
13161
+ /** The handle is the only stable identifier across the catalogue. */
13162
+ handle: string;
13163
+ title: string;
13164
+ vendor: string;
13165
+ productType: string;
13166
+ url: string;
13167
+ descriptionHtml: string | null;
13168
+ optionNames: string[];
13169
+ variants: TherabodyVariant[];
13170
+ /**
13171
+ * The store's own price scale per endpoint — see TherabodyVariant.price for
13172
+ * why the two strings may differ. Range keeps the same scale as the input.
13173
+ */
13174
+ priceRange: { min: string; max: string } | null;
13175
+ /** True if ANY variant is purchasable. The "is it in stock?" answer. */
13176
+ inStock: boolean;
13177
+ tags: string[];
13178
+ /** Therabody's own images, in the order the storefront publishes them. */
13179
+ images: string[];
13180
+ }
13181
+ interface TherabodyRecommendation {
13182
+ /** The matching products, in-stock first, then by handle. */
13183
+ products: TherabodyProduct[];
13184
+ /** What the filter DROPPED, in the same register the rest of the library uses. */
13185
+ warnings: string[];
13186
+ }
13187
+
13188
+ /**
13189
+ * Therabody (Theragun) product catalogue — every device, its variants, its prices and what is
13190
+ * in stock — read off the live Shopify storefront.
13191
+ */
13192
+ interface Unit {
13193
+ /**
13194
+ * Reads the live Therabody catalogue as Therabody publishes it — every product, its handle,
13195
+ * title, vendor, description, tags, images and the per-variant price the storefront is quoting
13196
+ * right now. Returns [] on a transport failure (warnings would be on an object envelope; this
13197
+ * is a list). The catalog page is the line and the parse is the unit of work.
13198
+ */
13199
+ listTheragunProducts(opts?: { limit?: number }): Promise<TherabodyProduct[]>;
13200
+
13201
+ /**
13202
+ * Reads one product by its handle — every variant, its exact price, the image the storefront
13203
+ * is showing and whether that specific variant is purchasable right now. Takes the handle
13204
+ * listTheragunProducts returns. THROWS on an unknown handle (the store answers a real 404).
13205
+ */
13206
+ getTheragunProduct(handle: string): Promise<TherabodyProduct>;
13207
+
13208
+ /**
13209
+ * Filters the live catalogue by what a shopper actually needs — device family, audience, and
13210
+ * the features named (percussion, recovery, hot/cold, breath). Returns the matching products
13211
+ * with their real prices, ranked by in-stock first. The storefront does not publish a query or
13212
+ * filter endpoint, so the function is local filtering on the catalogue listTheragunProducts
13213
+ * already returns — the divide is what the function does with the data, not how it gets there.
13214
+ */
13215
+ recommendTheragun(criteria: { audience?: string; features?: string[]; inStockOnly?: boolean }): Promise<TherabodyRecommendation>;
13216
+ }
13217
+ }
13218
+
10687
13219
  declare namespace BowmarkProvider_thezebra {
10688
13220
  // ── The Zebra — the unit's own declarations, verbatim ──
10689
13221
  interface thezebraStateRatesQuery {
@@ -10948,6 +13480,47 @@ interface thezebraRentersQuotes {
10948
13480
  url: string
10949
13481
  }
10950
13482
 
13483
+ interface thezebraAutoDriver {
13484
+ firstName: string
13485
+ lastName: string
13486
+ dob: string // ISO YYYY-MM-DD — carriers rate on the DATE, not on an age
13487
+ email: string
13488
+ }
13489
+
13490
+ interface thezebraAutoVehicle {
13491
+ year: number // 4-digit; a model year The Zebra does not rate THROWS
13492
+ make: string // "Toyota", "Tesla"
13493
+ model: string // "Camry", "Model 3" — a TRIM is not a page
13494
+ }
13495
+
13496
+ interface thezebraAutoQuotesQuery {
13497
+ driver: thezebraAutoDriver
13498
+ vehicle: thezebraAutoVehicle
13499
+ state: string // 2-letter postal code
13500
+ zip: string // 5 digits
13501
+ county: string // the county the ZIP sits in — the gateway validates server-side
13502
+ }
13503
+
13504
+ interface thezebraAutoQuote {
13505
+ carrier: string // e.g. "Progressive"
13506
+ carrierSlug: string // the site's own slug, e.g. "progressive"
13507
+ monthlyPremium: number // USD per MONTH; the card's period is asserted
13508
+ sixMonthPremium: number | null // USD per 6-month policy, where the card publishes one
13509
+ totalPremium: number | null // USD for the whole term, never derived
13510
+ policyLengthMonths: number | null
13511
+ deductible: number | null
13512
+ coverages: string[] // every coverage the card lists, verbatim
13513
+ }
13514
+
13515
+ interface thezebraAutoQuotes {
13516
+ quotes: thezebraAutoQuote[] // cheapest monthly premium first; [] is a real answer
13517
+ // The carriers ADVERTISED beside the quotes — paid placements with no price.
13518
+ // Returned under their own name so they can never be read as offers.
13519
+ advertisedCarriers: string[]
13520
+ warnings: string[] // names every dropped source / what the gateway refused
13521
+ url: string
13522
+ }
13523
+
10951
13524
  /**
10952
13525
  * US insurance comparison marketplace — side-by-side auto, home and renters rates from 100+
10953
13526
  * carriers, plus published rate research by state, city, vehicle, carrier and driver history.
@@ -11121,6 +13694,68 @@ interface thezebraRentersQuotes {
11121
13694
  * homeowners funnel reaches the same results page and publishes no premium anywhere on it.
11122
13695
  */
11123
13696
  getRentersQuotes(query: thezebraRentersQuotesQuery): Promise<thezebraRentersQuotes>;
13697
+
13698
+ /**
13699
+ * Returns REAL auto insurance quotes for one driver and one vehicle at a US ZIP — each
13700
+ * carrier's own monthly and six-month premium, deductible, and the coverage it priced, as The
13701
+ * Zebra's auto quote funnel prices them. This is a priced offer for the person asking, NOT the
13702
+ * published averages `getStateRates` and its siblings return. Pass `driver` (`firstName`,
13703
+ * `lastName`, `dob` ISO YYYY-MM-DD, `email`), one `vehicle` (`year`, `make`, `model` — a model
13704
+ * The Zebra does not rate THROWS naming the URL it tried), the 2-letter `state`, a 5-digit
13705
+ * `zip`, and `county` (the county the ZIP sits in — The Zebra validates it server-side and a
13706
+ * missing or wrong county is bounced). **The write binds, the read does not — yet**: the
13707
+ * GraphQL gateway at `graphql-gateway.production.thezebra.com` accepts the auto seed
13708
+ * (`LegacyStartInput.start.currentlyInsured` is the only field Apollo currently exposes on
13709
+ * that input), but the results route STILL bounces the session to the homepage with the four
13710
+ * fields this function sends. The function throws on the bounce with a message naming the gap;
13711
+ * the second required field on `LegacyStartInput` is the next attempt's work, and the rejected
13712
+ * probes — `helpToday`, `userPurchaseTimeframe`, `hadActiveInsurance`, `residenceOwnership`,
13713
+ * `presumedAnswers`, `policyLinkInfo`, `startDate`, `desiredCoverage` — are documented in
13714
+ * `agents/capability-engineer/instances/vertical-insurance/tools/zebra-auto-quotes/shape-summary.json`
13715
+ * (and the e5 clone) so they don't have to be re-derived. **`advertisedCarriers` is not a
13716
+ * quote list and must never be read as one**: the results page would carry paid carrier
13717
+ * placements alongside real offers, separated by `data-cy="results-card_ad_<carrier>"` (ad)
13718
+ * versus `data-cy="results-card_q2b_<carrier>"` (real offer), and the advertised names are
13719
+ * returned in their own field with no price attached. Every premium is USD and
13720
+ * `monthlyPremium` is per MONTH — the card's own period is checked rather than assumed, and a
13721
+ * card printing any other term THROWS instead of relabelling a figure. `totalPremium` is the
13722
+ * site's own whole-term number and is never divided out of the monthly one.
13723
+ */
13724
+ getAutoQuotes(query: thezebraAutoQuotesQuery): Promise<thezebraAutoQuotes>;
13725
+ }
13726
+ }
13727
+
13728
+ declare namespace BowmarkProvider_topviewtix {
13729
+ // ── TopView Sightseeing — the unit's own declarations, verbatim ──
13730
+ interface topviewtixPackageDetails {
13731
+ id: number;
13732
+ slug: string;
13733
+ name: string;
13734
+ description: string;
13735
+ url: string;
13736
+ adultsPrice: number | null;
13737
+ kidsPrice: number | null;
13738
+ isAdultOnly: boolean;
13739
+ availableDates: string[];
13740
+ blockedDates: string[];
13741
+ soldOutDates: string[];
13742
+ availableUntil: string | null;
13743
+ }
13744
+
13745
+ /**
13746
+ * TopView's NYC hop-on-hop-off bus, Statue of Liberty cruise and bike/walking tour packages —
13747
+ * getPackageDetails reads one package's live price and its own real-time booking calendar
13748
+ * (available/blocked/sold-out dates) off topviewtix.com/new-york/<slug>.
13749
+ */
13750
+ interface Unit {
13751
+ /**
13752
+ * Reads one TopView tour package in full — name, description, adult/kid price, and the site's
13753
+ * OWN live booking calendar (which dates are open, blocked, or sold out, and how far out the
13754
+ * calendar reaches). Takes `slug`, the package's own URL slug off
13755
+ * topviewtix.com/new-york/<slug> (e.g. "hop-on-hop-off-pass"). Throws if the slug doesn't
13756
+ * resolve to a real package (a clean 404) rather than returning an empty row.
13757
+ */
13758
+ getPackageDetails(args: object): Promise<topviewtixPackageDetails>;
11124
13759
  }
11125
13760
  }
11126
13761
 
@@ -11271,6 +13906,46 @@ interface UlrichPriceResult {
11271
13906
  }
11272
13907
  }
11273
13908
 
13909
+ declare namespace BowmarkProvider_viewrail {
13910
+ // ── Viewrail — the unit's own declarations, verbatim ──
13911
+ interface ViewrailMaterial {
13912
+ slug: string;
13913
+ title: string;
13914
+ metal: boolean;
13915
+ defaultFinish: string | null;
13916
+ finishes: string[];
13917
+ }
13918
+
13919
+ interface ViewrailMountingStyle {
13920
+ slug: string;
13921
+ title: string;
13922
+ availableMaterials: string[];
13923
+ }
13924
+
13925
+ /**
13926
+ * Cable railing / floating-stair manufacturer — the material and mounting-style catalog behind
13927
+ * Victor, Viewrail's own draw-and-quote design app (victor.viewrail.com). listMaterials and
13928
+ * listMountingStyles are live; the rest of Victor's option set (infill, posts, handrails,
13929
+ * newels) are stubs.
13930
+ */
13931
+ interface Unit {
13932
+ /**
13933
+ * Lists the metal and metal-look composite families Victor's cable railing configurator offers
13934
+ * (304/316/2205 stainless steel, aluminum, wood-grain aluminum, …), each with whether it's a
13935
+ * true metal, its default finish, and every finish slug it supports — off Victor's own
13936
+ * materials-config API.
13937
+ */
13938
+ listMaterials(): Promise<ViewrailMaterial[]>;
13939
+
13940
+ /**
13941
+ * Lists Victor's post-mounting styles (Surface Mount, Side Mount, SLIM Side Mount, Bump Out
13942
+ * Side Mount, Core Drill, …) and which material families each is available in — the first
13943
+ * choice Victor's own design flow asks a user to make before drawing a run.
13944
+ */
13945
+ listMountingStyles(): Promise<ViewrailMountingStyle[]>;
13946
+ }
13947
+ }
13948
+
11274
13949
  declare namespace BowmarkProvider_visible {
11275
13950
  // ── Visible — the unit's own declarations, verbatim ──
11276
13951
  interface VisibleDealOffer {
@@ -11375,15 +14050,91 @@ interface VisibleGetPhoneResult {
11375
14050
  flashSale: VisiblePhoneFlashSale | null;
11376
14051
  }
11377
14052
 
14053
+ interface VisibleCoveragePoint {
14054
+ matchedAddress: string | null;
14055
+ city: string | null;
14056
+ state: string | null;
14057
+ zip: string | null;
14058
+ latitude: number;
14059
+ longitude: number;
14060
+ }
14061
+
14062
+ interface VisibleCheckCoverageResult {
14063
+ input: string;
14064
+ point: VisibleCoveragePoint;
14065
+ tier: "5gUltraWideband" | "5gNationwide" | "4gLte" | "none";
14066
+ fiveGUltraWideband: boolean;
14067
+ fiveGNationwide: boolean;
14068
+ fourGLte: boolean;
14069
+ /** The site's own one-word verdict, forwarded verbatim. Measured to disagree
14070
+ * with the tier flags on a real point — trust the flags over this. */
14071
+ summary: string;
14072
+ }
14073
+
14074
+ interface VisibleSearchPhone {
14075
+ slug: string;
14076
+ name: string;
14077
+ make: string;
14078
+ deviceOs: string | null;
14079
+ listPrice: number | null;
14080
+ price: number | null;
14081
+ monthlyPrice: number | null;
14082
+ financingTermMonths: number | null;
14083
+ inStock: boolean;
14084
+ preOwned: boolean;
14085
+ fiveG: boolean;
14086
+ eSIMCompatible: boolean;
14087
+ comingSoon: boolean;
14088
+ tradeInEligible: boolean;
14089
+ visiblePaybackEligible: boolean | null;
14090
+ imageUrl: string | null;
14091
+ source: string;
14092
+ flashSale: VisiblePhoneFlashSale | null;
14093
+ }
14094
+
14095
+ interface VisibleSearchPhonesResult {
14096
+ source: string;
14097
+ totalCatalogueCount: number;
14098
+ filteredCount: number;
14099
+ page: number;
14100
+ pageSize: number;
14101
+ hasMore: boolean;
14102
+ availableMakes: string[];
14103
+ results: VisibleSearchPhone[];
14104
+ }
14105
+ interface VisiblePlanFeature {
14106
+ label: string | null;
14107
+ items: string[];
14108
+ }
14109
+ interface VisiblePlan {
14110
+ name: string;
14111
+ monthlyPrice: number;
14112
+ regularPrice: number | null;
14113
+ promoCode: string | null;
14114
+ promoText: string | null;
14115
+ taxesAndFeesIncluded: boolean | null;
14116
+ badge: string | null;
14117
+ ctaCode: string | null;
14118
+ ctaUrl: string | null;
14119
+ features: VisiblePlanFeature[];
14120
+ }
14121
+ interface VisibleGetPlansResult {
14122
+ source: string;
14123
+ plans: VisiblePlan[];
14124
+ }
14125
+
11378
14126
  /**
11379
14127
  * Visible (Verizon's prepaid brand): the promotions running right now — the offer grid with
11380
14128
  * its promo codes and fine print, plus the standing referral, trade-in, payback, Stack'em and
11381
- * Fios home-internet bundle programmes — and one phone in full from its catalogue slug or URL,
14129
+ * Fios home-internet bundle programmes — one phone in full from its catalogue slug or URL,
11382
14130
  * every storage/colour SKU with its own price, monthly financing terms and live stock,
11383
- * alongside the specs, images, device-protection plans and eSIM/5G support. Also declared, not
11384
- * yet built: plan pricing, network coverage by address, bring-your-own-device compatibility,
11385
- * phone SEARCH across the catalogue, per-device trade-in values, international rates, the
11386
- * wearable catalogue and the support estate.
14131
+ * alongside the specs, images, device-protection plans and eSIM/5G support Verizon's real
14132
+ * network coverage at a caller-supplied US address or ZIP, broken down by 5G Ultra Wideband /
14133
+ * 5G Nationwide / 4G LTE rather than a single yes/no — and the three-tier line-up as the plans
14134
+ * page renders it, with each tier's headline price, the running promo and the code that
14135
+ * unlocks it, the marketing badge and the four labelled feature sections. Also declared, not
14136
+ * yet built: bring-your-own-device compatibility, per-device trade-in values, international
14137
+ * rates, the wearable catalogue and the support estate.
11387
14138
  */
11388
14139
  interface Unit {
11389
14140
  /**
@@ -11409,6 +14160,48 @@ interface VisibleGetPhoneResult {
11409
14160
  * that ended months ago.
11410
14161
  */
11411
14162
  getPhone(slugOrUrl: string, options?: { preOwned?: boolean }): Promise<VisibleGetPhoneResult>;
14163
+
14164
+ /**
14165
+ * Returns the phones Visible currently sells, with the headline facts a purchase turns on —
14166
+ * name, make, OS, list price, current price, financed monthly payment and term, in-stock
14167
+ * status, pre-owned vs new, 5G support, eSIM compatibility, trade-in / Payback eligibility,
14168
+ * and the catalogue image. Optional filters narrow by make (Apple, Samsung, Google, Motorola,
14169
+ * TCL), by a `priceMax` the buyer's actually-going-to-pay price (NOT the strikethrough on a
14170
+ * stale flash-sale banner), by 5G support, and by in-stock availability. Pagination is
14171
+ * explicit and client-side over the catalogue's bounded 42-row response — the endpoint does
14172
+ * NOT paginate server-side; every tried pagination parameter is ignored. Joins naturally with
14173
+ * `getPhone`, which takes the same `slug` as its input — `searchPhones` answers "what does
14174
+ * Visible sell?", `getPhone` answers "what does this specific device cost across storage and
14175
+ * colour?".
14176
+ */
14177
+ searchPhones(options?: { make?: string; priceMax?: number; supports5G?: boolean; inStock?: boolean; page?: number; pageSize?: number }): Promise<VisibleSearchPhonesResult>;
14178
+
14179
+ /**
14180
+ * Returns Verizon's real network coverage — the tier that actually determines usable speed (5G
14181
+ * Ultra Wideband, 5G Nationwide, or 4G LTE) — at a caller-supplied US street address or
14182
+ * 5-digit ZIP, straight from the same point-level lookup Verizon's own coverage map (embedded
14183
+ * in visible.com/plans/coverage) queries. Geocodes the input first — a full address via the US
14184
+ * Census Bureau's public geocoder, a bare ZIP via a ZIP-centroid lookup — then reads the tiers
14185
+ * at that exact point, never a national or per-ZIP summary standing in for an address-level
14186
+ * answer. Also returns the site's own one-word verdict ("Best"/"Good"/"Moderate"/"No
14187
+ * Coverage") as `summary`, measured to sometimes DISAGREE with the tier flags — the flags are
14188
+ * the ones to trust.
14189
+ */
14190
+ checkCoverage(addressOrZip: string): Promise<VisibleCheckCoverageResult>;
14191
+
14192
+ /**
14193
+ * Returns the three tiers Visible sells today (Visible, Visible+, Visible+ Pro) as the plans
14194
+ * page renders them — each tier's headline monthly price, the regular price the running promo
14195
+ * unlocks (e.g. $19/mo with code SAVE6 unlocking $25/mo), the promo code itself, the "Taxes &
14196
+ * fees included" guarantee, the marketing badge ("Most popular" / "Best value" / "Ultimate
14197
+ * experience"), the CTA button code that pre-fills /shop/plan-selected, and four labelled
14198
+ * feature sections (Network, Mobile Hotspot, International, The Extras) with every bullet the
14199
+ * page shows. Reads the LIVE page only, never the site's own /docs/visible_plans.md, which is
14200
+ * dated 2025-11-12 and answers the same prompt with two stale tiers and no code. Three tiers
14201
+ * is hard — a future fourth tier changes the answer visibly rather than reading as a
14202
+ * half-broken response.
14203
+ */
14204
+ getPlans(): Promise<VisibleGetPlansResult>;
11412
14205
  }
11413
14206
  }
11414
14207
 
@@ -11536,6 +14329,27 @@ interface wellfoundCompanyRow {
11536
14329
  highlightedRoles: { id: string; title: string; url: string; locations: string[] }[];
11537
14330
  }
11538
14331
 
14332
+ interface wellfoundCompanyDetail {
14333
+ id: string;
14334
+ name: string;
14335
+ slug: string;
14336
+ url: string;
14337
+ highConcept: string | null;
14338
+ productDescription: string | null;
14339
+ companySize: string | null;
14340
+ employeesMin: number | null;
14341
+ employeesMax: number | null;
14342
+ markets: string[];
14343
+ stage: string | null;
14344
+ activelyHiring: boolean;
14345
+ badges: { id: string; label: string; tooltip: string | null }[];
14346
+ locations: { slug: string; displayName: string }[];
14347
+ remotePolicy: "remote" | null;
14348
+ companyUrl: string | null;
14349
+ totalRaisedAmount: number | null;
14350
+ logoUrl: string | null;
14351
+ }
14352
+
11539
14353
  /**
11540
14354
  * Wellfound (formerly AngelList Talent) — startup job search with salary and equity bands,
11541
14355
  * startup profiles and their open roles.
@@ -11584,6 +14398,95 @@ interface ShopifyVariant {
11584
14398
  /** The store's own per-variant stock flag. */
11585
14399
  available: boolean;
11586
14400
  options: string[];
14401
+ /** The same values keyed by the option's own NAME — { Color: "Black", Size: "S" }.
14402
+ * Read THIS to filter by size; options[1] is only the size on a store that
14403
+ * happens to order it second. {} when the two lists cannot be reconciled. */
14404
+ selectedOptions: Record<string, string>;
14405
+ /** The image the STORE linked to this variant. Usually NULL — most storefronts
14406
+ * publish no image-to-variant link at all, and null says so rather than
14407
+ * handing back the first product picture. */
14408
+ image: ProductImage | null;
14409
+ /** Why this price is, or is not, a markdown. */
14410
+ sale: SaleEvidence;
14411
+ }
14412
+ interface ProductImage {
14413
+ /** Absolute HTTPS url, at the largest rendition the CDN serves. */
14414
+ url: string;
14415
+ /** The retailer's own alt text, or null. */
14416
+ altText: string | null;
14417
+ /** The retailer's colour name for this picture. Set when the store links it,
14418
+ * or when the whole product is ONE colourway (which is how both yoga
14419
+ * retailers publish: one colour per product). Null otherwise. */
14420
+ color: string | null;
14421
+ colorId: string | null;
14422
+ /** Variant ids the STORE linked. [] means it published no link — NOT that the
14423
+ * image belongs to every variant. */
14424
+ variantIds: string[];
14425
+ }
14426
+ interface SaleEvidence {
14427
+ /** True only with retailer evidence. NEVER set from a low price or from the
14428
+ * word "sale" in a title. */
14429
+ onSale: boolean;
14430
+ currentPrice: string | null;
14431
+ /** The published "was" price. Strictly greater than currentPrice when
14432
+ * evidenceType is "compare_at_price". Null when nothing published one. */
14433
+ originalPrice: string | null;
14434
+ /** ISO 4217, or null. Null on the REST catalogue door, which publishes no
14435
+ * currency — reported honestly rather than assumed to be USD. */
14436
+ currency: string | null;
14437
+ promotionMessage: string | null;
14438
+ /** How it was decided. "compare_at_price" is a struck-through price;
14439
+ * "retailer_sale_badge" is a published sale tag; "none" is not on sale. */
14440
+ evidenceType: "compare_at_price" | "sale_price" | "retailer_sale_badge" | "published_promotion" | "none";
14441
+ /** The retailer text or field the classification rests on, verbatim. */
14442
+ evidenceText: string | null;
14443
+ }
14444
+ /** The retailer's own labels, read off its published tags, category and options.
14445
+ * NEVER inferred from the title or from an image. Null or [] when unpublished,
14446
+ * which is common and is an honest answer. */
14447
+ interface PublishedProductAttributes {
14448
+ audience: string | null;
14449
+ garmentType: "sports_bra" | "tank" | "crop_top" | "leggings" | "shorts" | "other" | null;
14450
+ categories: string[];
14451
+ collections: string[];
14452
+ fabrics: string[];
14453
+ materials: string[];
14454
+ color: string | null;
14455
+ colorFamily: string | null;
14456
+ pattern: string | null;
14457
+ styleTags: string[];
14458
+ neckline: string | null;
14459
+ strapWidth: string | null;
14460
+ backDesign: string | null;
14461
+ sleeveLength: string | null;
14462
+ rise: string | null;
14463
+ waistband: string | null;
14464
+ inseam: string | null;
14465
+ legShape: string | null;
14466
+ fit: string | null;
14467
+ coverage: string | null;
14468
+ }
14469
+ /** Shared colour, fabric, collection and style family — what makes two garments
14470
+ * PLAUSIBLY coordinate. None of it establishes a set. */
14471
+ interface CoordinationMetadata {
14472
+ collectionNames: string[];
14473
+ fabricNames: string[];
14474
+ colorName: string | null;
14475
+ colorId: string | null;
14476
+ colorFamily: string | null;
14477
+ /** The store's own grouping key for one style across its colourways. Two
14478
+ * products sharing it are the same garment in two colours. */
14479
+ productFamily: string | null;
14480
+ }
14481
+ /** 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. */
14484
+ interface RetailerSetEvidence {
14485
+ evidenceType: "official_set" | "shop_the_set" | "complete_the_look" | "matching_piece";
14486
+ evidenceText: string | null;
14487
+ sourceUrl: string | null;
14488
+ setId: string | null;
14489
+ relatedProducts: Array<{ productId: string | null; handle: string | null; title: string | null; url: string | null }>;
11587
14490
  }
11588
14491
  interface ShopifyProduct {
11589
14492
  handle: string;
@@ -11597,6 +14500,14 @@ interface ShopifyProduct {
11597
14500
  inStock: boolean;
11598
14501
  tags: string[];
11599
14502
  descriptionHtml: string | null;
14503
+ /** The same copy with its markup removed. */
14504
+ descriptionText: string | null;
14505
+ currency: string | null;
14506
+ /** Every image the door published, deduplicated, in the store's own order. */
14507
+ images: ProductImage[];
14508
+ attributes: PublishedProductAttributes;
14509
+ coordination: CoordinationMetadata;
14510
+ retailerSetEvidence: RetailerSetEvidence[];
11600
14511
  }
11601
14512
  interface ShopifyCartLine {
11602
14513
  /** Shopify's own line key, which its cart-change endpoints address a line by. */
@@ -11610,6 +14521,30 @@ interface ShopifyCartLine {
11610
14521
  lineTotal: string;
11611
14522
  url: string;
11612
14523
  }
14524
+ /** One collection the store publishes — its own merchandised grouping, and the
14525
+ * ONE place either yoga retailer states a set. Membership in a collection the
14526
+ * retailer NAMED "Matching Sets" is a published fact and is admissible as set
14527
+ * evidence; two products being adjacent inside it is NOT, because a position in
14528
+ * a list is not a statement. */
14529
+ interface ShopifyCollection {
14530
+ handle: string;
14531
+ title: string;
14532
+ url: string;
14533
+ descriptionHtml: string | null;
14534
+ /** True when the retailer's OWN title or handle names this a set, a matching
14535
+ * piece or a look. Never inferred from what is inside it. */
14536
+ setLike: boolean;
14537
+ productCount: number | null;
14538
+ updatedAt: string | null;
14539
+ }
14540
+ interface ShopifyCollectionProducts {
14541
+ handle: string;
14542
+ url: string;
14543
+ /** In the RETAILER's own order. Curated collections are merchandised
14544
+ * top-then-bottom; reading a pairing out of that order is the caller's
14545
+ * inference, never this provider's claim. [] is an ordinary answer. */
14546
+ products: ShopifyProduct[];
14547
+ }
11613
14548
  interface ShopifyCart {
11614
14549
  /** The store's own cart token — a bearer credential, so treat it like one. */
11615
14550
  token: string;
@@ -11641,6 +14576,20 @@ interface ShopifyCart {
11641
14576
  */
11642
14577
  getProduct(handle: string): Promise<ShopifyProduct>;
11643
14578
 
14579
+ /**
14580
+ * Lists the store's own merchandised collections. THIS is where a retailer states a SET: a
14581
+ * collection the store itself named "Matching Sets" or "Activewear Sets" carries setLike:
14582
+ * true, and membership in one is published evidence that two garments are sold together.
14583
+ */
14584
+ listCollections(opts?: { limit?: number }): Promise<ShopifyCollection[]>;
14585
+
14586
+ /**
14587
+ * Reads one collection's products in the retailer's own merchandised order, as full product
14588
+ * rows. An empty list is an ordinary answer — several named 'look' collections publish no
14589
+ * products through this door.
14590
+ */
14591
+ getCollection(handle: string, opts?: { limit?: number }): Promise<ShopifyCollectionProducts>;
14592
+
11644
14593
  /**
11645
14594
  * Puts variants into THIS run's own cart on the store and returns the cart the store reports
11646
14595
  * back. A real write: the cart exists on the store from the first call and belongs to this
@@ -11672,6 +14621,95 @@ interface ShopifyVariant {
11672
14621
  /** The store's own per-variant stock flag. */
11673
14622
  available: boolean;
11674
14623
  options: string[];
14624
+ /** The same values keyed by the option's own NAME — { Color: "Black", Size: "S" }.
14625
+ * Read THIS to filter by size; options[1] is only the size on a store that
14626
+ * happens to order it second. {} when the two lists cannot be reconciled. */
14627
+ selectedOptions: Record<string, string>;
14628
+ /** The image the STORE linked to this variant. Usually NULL — most storefronts
14629
+ * publish no image-to-variant link at all, and null says so rather than
14630
+ * handing back the first product picture. */
14631
+ image: ProductImage | null;
14632
+ /** Why this price is, or is not, a markdown. */
14633
+ sale: SaleEvidence;
14634
+ }
14635
+ interface ProductImage {
14636
+ /** Absolute HTTPS url, at the largest rendition the CDN serves. */
14637
+ url: string;
14638
+ /** The retailer's own alt text, or null. */
14639
+ altText: string | null;
14640
+ /** The retailer's colour name for this picture. Set when the store links it,
14641
+ * or when the whole product is ONE colourway (which is how both yoga
14642
+ * retailers publish: one colour per product). Null otherwise. */
14643
+ color: string | null;
14644
+ colorId: string | null;
14645
+ /** Variant ids the STORE linked. [] means it published no link — NOT that the
14646
+ * image belongs to every variant. */
14647
+ variantIds: string[];
14648
+ }
14649
+ interface SaleEvidence {
14650
+ /** True only with retailer evidence. NEVER set from a low price or from the
14651
+ * word "sale" in a title. */
14652
+ onSale: boolean;
14653
+ currentPrice: string | null;
14654
+ /** The published "was" price. Strictly greater than currentPrice when
14655
+ * evidenceType is "compare_at_price". Null when nothing published one. */
14656
+ originalPrice: string | null;
14657
+ /** ISO 4217, or null. Null on the REST catalogue door, which publishes no
14658
+ * currency — reported honestly rather than assumed to be USD. */
14659
+ currency: string | null;
14660
+ promotionMessage: string | null;
14661
+ /** How it was decided. "compare_at_price" is a struck-through price;
14662
+ * "retailer_sale_badge" is a published sale tag; "none" is not on sale. */
14663
+ evidenceType: "compare_at_price" | "sale_price" | "retailer_sale_badge" | "published_promotion" | "none";
14664
+ /** The retailer text or field the classification rests on, verbatim. */
14665
+ evidenceText: string | null;
14666
+ }
14667
+ /** The retailer's own labels, read off its published tags, category and options.
14668
+ * NEVER inferred from the title or from an image. Null or [] when unpublished,
14669
+ * which is common and is an honest answer. */
14670
+ interface PublishedProductAttributes {
14671
+ audience: string | null;
14672
+ garmentType: "sports_bra" | "tank" | "crop_top" | "leggings" | "shorts" | "other" | null;
14673
+ categories: string[];
14674
+ collections: string[];
14675
+ fabrics: string[];
14676
+ materials: string[];
14677
+ color: string | null;
14678
+ colorFamily: string | null;
14679
+ pattern: string | null;
14680
+ styleTags: string[];
14681
+ neckline: string | null;
14682
+ strapWidth: string | null;
14683
+ backDesign: string | null;
14684
+ sleeveLength: string | null;
14685
+ rise: string | null;
14686
+ waistband: string | null;
14687
+ inseam: string | null;
14688
+ legShape: string | null;
14689
+ fit: string | null;
14690
+ coverage: string | null;
14691
+ }
14692
+ /** Shared colour, fabric, collection and style family — what makes two garments
14693
+ * PLAUSIBLY coordinate. None of it establishes a set. */
14694
+ interface CoordinationMetadata {
14695
+ collectionNames: string[];
14696
+ fabricNames: string[];
14697
+ colorName: string | null;
14698
+ colorId: string | null;
14699
+ colorFamily: string | null;
14700
+ /** The store's own grouping key for one style across its colourways. Two
14701
+ * products sharing it are the same garment in two colours. */
14702
+ productFamily: string | null;
14703
+ }
14704
+ /** 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. */
14707
+ interface RetailerSetEvidence {
14708
+ evidenceType: "official_set" | "shop_the_set" | "complete_the_look" | "matching_piece";
14709
+ evidenceText: string | null;
14710
+ sourceUrl: string | null;
14711
+ setId: string | null;
14712
+ relatedProducts: Array<{ productId: string | null; handle: string | null; title: string | null; url: string | null }>;
11675
14713
  }
11676
14714
  interface ShopifyProduct {
11677
14715
  handle: string;
@@ -11685,6 +14723,14 @@ interface ShopifyProduct {
11685
14723
  inStock: boolean;
11686
14724
  tags: string[];
11687
14725
  descriptionHtml: string | null;
14726
+ /** The same copy with its markup removed. */
14727
+ descriptionText: string | null;
14728
+ currency: string | null;
14729
+ /** Every image the door published, deduplicated, in the store's own order. */
14730
+ images: ProductImage[];
14731
+ attributes: PublishedProductAttributes;
14732
+ coordination: CoordinationMetadata;
14733
+ retailerSetEvidence: RetailerSetEvidence[];
11688
14734
  }
11689
14735
  interface ShopifyCartLine {
11690
14736
  /** Shopify's own line key, which its cart-change endpoints address a line by. */
@@ -11698,6 +14744,30 @@ interface ShopifyCartLine {
11698
14744
  lineTotal: string;
11699
14745
  url: string;
11700
14746
  }
14747
+ /** One collection the store publishes — its own merchandised grouping, and the
14748
+ * ONE place either yoga retailer states a set. Membership in a collection the
14749
+ * retailer NAMED "Matching Sets" is a published fact and is admissible as set
14750
+ * evidence; two products being adjacent inside it is NOT, because a position in
14751
+ * a list is not a statement. */
14752
+ interface ShopifyCollection {
14753
+ handle: string;
14754
+ title: string;
14755
+ url: string;
14756
+ descriptionHtml: string | null;
14757
+ /** True when the retailer's OWN title or handle names this a set, a matching
14758
+ * piece or a look. Never inferred from what is inside it. */
14759
+ setLike: boolean;
14760
+ productCount: number | null;
14761
+ updatedAt: string | null;
14762
+ }
14763
+ interface ShopifyCollectionProducts {
14764
+ handle: string;
14765
+ url: string;
14766
+ /** In the RETAILER's own order. Curated collections are merchandised
14767
+ * top-then-bottom; reading a pairing out of that order is the caller's
14768
+ * inference, never this provider's claim. [] is an ordinary answer. */
14769
+ products: ShopifyProduct[];
14770
+ }
11701
14771
  interface ShopifyCart {
11702
14772
  /** The store's own cart token — a bearer credential, so treat it like one. */
11703
14773
  token: string;
@@ -11728,6 +14798,20 @@ interface ShopifyCart {
11728
14798
  * specific size or colour is purchasable right now.
11729
14799
  */
11730
14800
  getProduct(handle: string): Promise<ShopifyProduct>;
14801
+
14802
+ /**
14803
+ * Lists the store's own merchandised collections. THIS is where a retailer states a SET: a
14804
+ * collection the store itself named "Matching Sets" or "Activewear Sets" carries setLike:
14805
+ * true, and membership in one is published evidence that two garments are sold together.
14806
+ */
14807
+ listCollections(opts?: { limit?: number }): Promise<ShopifyCollection[]>;
14808
+
14809
+ /**
14810
+ * Reads one collection's products in the retailer's own merchandised order, as full product
14811
+ * rows. An empty list is an ordinary answer — several named 'look' collections publish no
14812
+ * products through this door.
14813
+ */
14814
+ getCollection(handle: string, opts?: { limit?: number }): Promise<ShopifyCollectionProducts>;
11731
14815
  }
11732
14816
  }
11733
14817
 
@@ -11740,23 +14824,30 @@ interface BowmarkProviders {
11740
14824
  aa: BowmarkProvider_aa.Unit;
11741
14825
  abercrombie: BowmarkProvider_abercrombie.Unit;
11742
14826
  ashleyfurniture: BowmarkProvider_ashleyfurniture.Unit;
14827
+ avis: BowmarkProvider_avis.Unit;
11743
14828
  azure: BowmarkProvider_azure.Unit;
11744
14829
  barletta: BowmarkProvider_barletta.Unit;
11745
14830
  bhphoto: BowmarkProvider_bhphoto.Unit;
11746
14831
  blenderseyewear: BowmarkProvider_blenderseyewear.Unit;
14832
+ bluehaven: BowmarkProvider_bluehaven.Unit;
11747
14833
  bmwusa: BowmarkProvider_bmwusa.Unit;
14834
+ bykoket: BowmarkProvider_bykoket.Unit;
11748
14835
  cancer: BowmarkProvider_cancer.Unit;
14836
+ caraway: BowmarkProvider_caraway.Unit;
11749
14837
  cars: BowmarkProvider_cars.Unit;
11750
14838
  cheapflights: BowmarkProvider_cheapflights.Unit;
11751
14839
  chriscraft: BowmarkProvider_chriscraft.Unit;
11752
14840
  classpass: BowmarkProvider_classpass.Unit;
11753
14841
  cloudflare: BowmarkProvider_cloudflare.Unit;
14842
+ cyberpowerpc: BowmarkProvider_cyberpowerpc.Unit;
11754
14843
  decked: BowmarkProvider_decked.Unit;
14844
+ dice: BowmarkProvider_dice.Unit;
11755
14845
  dickssportinggoods: BowmarkProvider_dickssportinggoods.Unit;
11756
14846
  dillards: BowmarkProvider_dillards.Unit;
11757
14847
  discounttire: BowmarkProvider_discounttire.Unit;
11758
14848
  erieinsurance: BowmarkProvider_erieinsurance.Unit;
11759
14849
  extraspace: BowmarkProvider_extraspace.Unit;
14850
+ firstdibs: BowmarkProvider_firstdibs.Unit;
11760
14851
  flightradar24: BowmarkProvider_flightradar24.Unit;
11761
14852
  ford: BowmarkProvider_ford.Unit;
11762
14853
  framebridge: BowmarkProvider_framebridge.Unit;
@@ -11764,13 +14855,16 @@ interface BowmarkProviders {
11764
14855
  geico: BowmarkProvider_geico.Unit;
11765
14856
  google_flights: BowmarkProvider_google_flights.Unit;
11766
14857
  grainger: BowmarkProvider_grainger.Unit;
14858
+ hauslabs: BowmarkProvider_hauslabs.Unit;
11767
14859
  healthcare_gov: BowmarkProvider_healthcare_gov.Unit;
11768
14860
  hellofresh: BowmarkProvider_hellofresh.Unit;
14861
+ hellotend: BowmarkProvider_hellotend.Unit;
11769
14862
  hilton: BowmarkProvider_hilton.Unit;
11770
14863
  hunter: BowmarkProvider_hunter.Unit;
11771
14864
  ibuypower: BowmarkProvider_ibuypower.Unit;
11772
14865
  insurify: BowmarkProvider_insurify.Unit;
11773
14866
  interiordefine: BowmarkProvider_interiordefine.Unit;
14867
+ joybird: BowmarkProvider_joybird.Unit;
11774
14868
  kayak: BowmarkProvider_kayak.Unit;
11775
14869
  labcorp: BowmarkProvider_labcorp.Unit;
11776
14870
  linkedin: BowmarkProvider_linkedin.Unit;
@@ -11778,6 +14872,7 @@ interface BowmarkProviders {
11778
14872
  lonelyplanet: BowmarkProvider_lonelyplanet.Unit;
11779
14873
  lufthansa: BowmarkProvider_lufthansa.Unit;
11780
14874
  lululemon: BowmarkProvider_lululemon.Unit;
14875
+ maidenhome: BowmarkProvider_maidenhome.Unit;
11781
14876
  mailchimp: BowmarkProvider_mailchimp.Unit;
11782
14877
  marriott: BowmarkProvider_marriott.Unit;
11783
14878
  mcdonalds: BowmarkProvider_mcdonalds.Unit;
@@ -11792,22 +14887,32 @@ interface BowmarkProviders {
11792
14887
  newegg: BowmarkProvider_newegg.Unit;
11793
14888
  oanda: BowmarkProvider_oanda.Unit;
11794
14889
  otto: BowmarkProvider_otto.Unit;
14890
+ paypal: BowmarkProvider_paypal.Unit;
11795
14891
  pirateship: BowmarkProvider_pirateship.Unit;
11796
14892
  pizzahut: BowmarkProvider_pizzahut.Unit;
14893
+ premierbuildings: BowmarkProvider_premierbuildings.Unit;
11797
14894
  progressive: BowmarkProvider_progressive.Unit;
11798
14895
  prose: BowmarkProvider_prose.Unit;
11799
14896
  reddit: BowmarkProvider_reddit.Unit;
11800
14897
  ritani: BowmarkProvider_ritani.Unit;
11801
14898
  samsclub: BowmarkProvider_samsclub.Unit;
11802
14899
  sears: BowmarkProvider_sears.Unit;
14900
+ seegarsfence: BowmarkProvider_seegarsfence.Unit;
11803
14901
  selectblinds: BowmarkProvider_selectblinds.Unit;
11804
14902
  semihandmade: BowmarkProvider_semihandmade.Unit;
11805
14903
  soundcloud: BowmarkProvider_soundcloud.Unit;
11806
14904
  statefarm: BowmarkProvider_statefarm.Unit;
14905
+ stickergiant: BowmarkProvider_stickergiant.Unit;
14906
+ sunhomesaunas: BowmarkProvider_sunhomesaunas.Unit;
14907
+ target: BowmarkProvider_target.Unit;
14908
+ teladoc: BowmarkProvider_teladoc.Unit;
11807
14909
  tentree: BowmarkProvider_tentree.Unit;
14910
+ therabody: BowmarkProvider_therabody.Unit;
11808
14911
  thezebra: BowmarkProvider_thezebra.Unit;
14912
+ topviewtix: BowmarkProvider_topviewtix.Unit;
11809
14913
  trektravel: BowmarkProvider_trektravel.Unit;
11810
14914
  ulrichlifestyle: BowmarkProvider_ulrichlifestyle.Unit;
14915
+ viewrail: BowmarkProvider_viewrail.Unit;
11811
14916
  visible: BowmarkProvider_visible.Unit;
11812
14917
  walmart: BowmarkProvider_walmart.Unit;
11813
14918
  wellfound: BowmarkProvider_wellfound.Unit;
@@ -17278,6 +20383,7 @@ interface BowmarkProviders {
17278
20383
  avedaisland: BowmarkFamily_shopify_store.Unit;
17279
20384
  avenatheme: BowmarkFamily_shopify_store.Unit;
17280
20385
  avenidabresil: BowmarkFamily_shopify_store.Unit;
20386
+ aventon: BowmarkFamily_shopify_store.Unit;
17281
20387
  aventsbyaugust: BowmarkFamily_shopify_store.Unit;
17282
20388
  aventureextension: BowmarkFamily_shopify_store.Unit;
17283
20389
  avenues3: BowmarkFamily_shopify_store.Unit;