@bowmark/web 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: 80346d8cf36c785e2b7fe0a77a87e5a51fa97ceb04ea11c951c71a9f7f75ad8e
9
- // 8 capabilities, 71 providers, 214 typed functions, 20 refused.
10
- // 51,711 family members, sharing 2 interface(s) — declared once and pointed at, never repeated per member.
8
+ // Manifest version: 75ed32aa210bc375ea259fb61276ab65363d6b123ba60e63283bdfa36a58a3d5
9
+ // 8 capabilities, 87 providers, 294 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
@@ -232,6 +232,71 @@ type BookingOptionsResult = {
232
232
  // sellers are not in here. Empty means nothing dropped.
233
233
  }
234
234
 
235
+ // Give EITHER flightNumber OR both origin and destination, plus date and airline.
236
+ type FlightStatusQuery = {
237
+ airline: string // IATA carrier code, e.g. "AA" — routes to the airline
238
+ // that flies it; there is no default to guess
239
+ date: string // the flight's ORIGIN date, ISO "2026-08-04"
240
+ flightNumber?: string // "100", "2005", or "AA2005"
241
+ origin?: string // IATA code — with destination, returns every NONSTOP
242
+ destination?: string // that airline flies on the route that day
243
+ }
244
+
245
+ // One leg's status, at one end of the flight.
246
+ type FlightStatusAirport = {
247
+ airportCode: string
248
+ cityName: string | null
249
+ gate: string | null // null is UNKNOWN, not "no gate" — normal for a flight
250
+ // weeks out
251
+ terminal: string | null
252
+ state: string | null
253
+ country: string | null
254
+ baggageClaim: string | null // arrival end only
255
+ scheduledTime: string | null // ISO 8601 WITH the airport's own UTC offset
256
+ estimatedTime: string | null
257
+ actualTime: string | null // what happened, once it has; null before the event
258
+ scheduledBoardingTime: string | null // departure end only
259
+ estimatedBoardingTime: string | null
260
+ }
261
+
262
+ type FlightStatusLeg = {
263
+ flightNumber: string
264
+ airlineCode: string
265
+ flightStatus: string | null // the airline's own wording, verbatim
266
+ flightStatusKey: string | null // a stable key behind the wording — branch on
267
+ // this, not the display string
268
+ flightStatusColor: string | null // the airline's own severity colour, where
269
+ // it publishes one (GREEN, ORANGE, RED, ...)
270
+ canceled: boolean
271
+ diverted: boolean
272
+ inFlight: boolean
273
+ landed: boolean
274
+ departure: FlightStatusAirport
275
+ arrival: FlightStatusAirport
276
+ equipment: {
277
+ tailNumber: string | null
278
+ equipmentCode: string | null
279
+ iataName: string | null
280
+ displayName: string | null // e.g. "Airbus A321neo"
281
+ }
282
+ disruptionMessage: string | null // the airline's own passenger-facing prose
283
+ codeShare: boolean
284
+ operatedBy: string | null
285
+ marketingCarrier: string | null
286
+ wifiAvailable: boolean | null
287
+ powerPortAvailable: boolean | null
288
+ }
289
+
290
+ type FlightStatusResult = {
291
+ date: string // echoed back, "YYYY-MM-DD"
292
+ flightNumber: string | null // null in route mode
293
+ origin: string | null
294
+ destination: string | null
295
+ flights: FlightStatusLeg[] // EMPTY IS AN ANSWER: no such flight that day
296
+ warnings: string[] // always present, same contract as every other
297
+ // function on this capability
298
+ }
299
+
235
300
  /**
236
301
  * Search flights with one call and get back normalized, price-sorted results (the same
237
302
  * physical flight appears once). Each result carries the site it came from (`site`) and every
@@ -270,6 +335,24 @@ type BookingOptionsResult = {
270
335
  * on, whose sellers are not included.
271
336
  */
272
337
  getBookingOptions(flight: FlightResult, options?: CallOptions): Promise<BookingOptionsResult>;
338
+
339
+ /**
340
+ * A flight's live status, checked directly with the airline that flies it. Pass `airline` (an
341
+ * IATA carrier code, e.g. "AA") plus `date` (the flight's ORIGIN date, ISO "2026-08-04") and
342
+ * EITHER `flightNumber` OR both `origin` and `destination` (IATA airport codes) to get every
343
+ * nonstop that airline flies on that route that day. Each returned leg carries the airline's
344
+ * own status wording and a stable status key to branch on, the
345
+ * canceled/diverted/inFlight/landed booleans, scheduled/estimated/actual times at both ends as
346
+ * ISO strings with each airport's own UTC offset, gate, terminal and baggage claim, the
347
+ * aircraft, codeshare and operating carrier, and the airline's passenger-facing disruption
348
+ * message. THROWS for an `airline` no provider behind this capability implements, naming which
349
+ * ones can answer — there is no default carrier to guess, unlike `search`, which has no
350
+ * caller-supplied identity to route on in the first place. An empty `flights` array is a real
351
+ * answer: that airline flies no such flight that day, not a failure. `warnings` is always
352
+ * present, same contract as every other function here, though today it can only ever report a
353
+ * clamped `timeoutMs` — a single-carrier route has no fan-out to go thin.
354
+ */
355
+ getFlightStatus(query: FlightStatusQuery, options?: CallOptions): Promise<FlightStatusResult>;
273
356
  }
274
357
  }
275
358
 
@@ -446,6 +529,29 @@ type CarrierLicensing = {
446
529
  warnings: string[] // always present; a timeoutMs clamp notice today
447
530
  }
448
531
 
532
+ // listReferralCarriers: whose paper a referral/marketplace program's quote
533
+ // actually places — a fact the quote row itself never states.
534
+ type ReferralCarrierQuery = {
535
+ line?: string // narrow to one property line, e.g. "homeowners" — NOT a closed
536
+ // enum; an unmatched value throws, naming the lines the
537
+ // directory actually publishes. Omit for the whole directory.
538
+ }
539
+ type ReferralCarrier = {
540
+ source: string // which referral program this came from
541
+ name: string // as the directory writes it
542
+ lines: string[] // every property line this carrier is listed under
543
+ url: string | null // the directory's own link for this carrier
544
+ ownedBySource: boolean | null // true only for the referral program's OWN
545
+ // paper; null when the directory linked
546
+ // nothing for this row, so it said nothing
547
+ // to derive an answer from
548
+ }
549
+ type ReferralCarrierListResult = {
550
+ carriers: ReferralCarrier[] // alphabetical by name
551
+ warnings: string[] // always present; names a source that timed
552
+ // out or failed
553
+ }
554
+
449
555
  type CallOptions = {
450
556
  timeoutMs?: number // per-provider budget in ms, default 30000, clamped to 1000-55000.
451
557
  // A provider slower than this is DROPPED from the results and
@@ -516,6 +622,25 @@ type CallOptions = {
516
622
  * result to hand back. `options.timeoutMs` sets the budget (default 30000).
517
623
  */
518
624
  getLicensing(naicCode: string, options?: CallOptions): Promise<CarrierLicensing>;
625
+
626
+ /**
627
+ * Lists the carriers a referral/marketplace program actually places business with — the fact a
628
+ * quote row never states on its face. Reads Progressive's own published directory of outside
629
+ * property carriers (homeowners, renters, condo, dwelling-fire, manufactured-home) today. Call
630
+ * with no argument for the whole directory (16 carriers currently) or `{ line: "homeowners" }`
631
+ * to narrow to one line — `line` is NOT a closed enum; an unrecognized value THROWS naming the
632
+ * lines the directory actually publishes, because inventing a fixed list here would silently
633
+ * drop a line the site adds later. Each row carries every line that carrier is listed under
634
+ * (`lines`) and `ownedBySource` — true ONLY when the row is the referral program's own paper,
635
+ * derived from the directory's own linking rather than from name matching, and null when the
636
+ * directory linked nothing for that row. NEVER returns an empty list from a source that
637
+ * answered: this is a published directory with no legitimate empty case, so a missing section
638
+ * or a changed page throws at the provider rather than under-reporting who underwrites the
639
+ * policy. `warnings` is always present and names a source that timed out or failed — with one
640
+ * source today, read it before trusting a short list is the whole directory.
641
+ * `options.timeoutMs` sets the per-source budget (default 30000).
642
+ */
643
+ listReferralCarriers(query?: ReferralCarrierQuery, options?: CallOptions): Promise<ReferralCarrierListResult>;
519
644
  }
520
645
  }
521
646
 
@@ -789,18 +914,179 @@ interface aaFlightStatusResult {
789
914
  flights: aaFlight[];
790
915
  }
791
916
 
917
+ interface aaReservation {
918
+ recordLocator: string;
919
+ status: string | null;
920
+ bookingTime: string | null;
921
+ passengers: aaReservationPassenger[];
922
+ itinerary: aaReservationSlice[];
923
+ }
924
+
925
+ interface aaReservationPassenger {
926
+ firstName: string | null;
927
+ lastName: string | null;
928
+ passengerID: string | null;
929
+ paxType: string | null;
930
+ loyaltyNumber: string | null;
931
+ ticketNumbers: string[];
932
+ }
933
+
934
+ interface aaReservationSlice {
935
+ segments: aaReservationSegment[];
936
+ }
937
+
938
+ interface aaReservationSegment {
939
+ flightNumber: string | null;
940
+ marketingCarrierCode: string | null;
941
+ operatingCarrierCode: string | null;
942
+ cabinType: string | null;
943
+ bookingCode: string | null;
944
+ departureDateTime: string | null;
945
+ legs: aaReservationLeg[];
946
+ }
947
+
948
+ interface aaReservationLeg {
949
+ originAirportCode: string | null;
950
+ originCity: string | null;
951
+ destinationAirportCode: string | null;
952
+ destinationCity: string | null;
953
+ }
954
+
955
+ interface aaRetrieveBookingArgs {
956
+ /** Exactly six letters — American's own record-locator format. */
957
+ recordLocator: string;
958
+ /** The passenger's last name, exactly as it appears on the reservation. */
959
+ lastName: string;
960
+ }
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
+
792
1038
  /**
793
1039
  * American Airlines' own site — its published fares and award availability, flight status,
794
- * reservation lookup, seat maps, baggage allowance and fee schedules. Flight status is live
795
- * 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.
796
1043
  */
797
1044
  interface Unit {
798
- // NO TYPED SURFACE — every function this unit declares is refused above.
799
- // The unit is real and callable at runtime; nothing here can say so in types.
800
1045
  // UNTYPED, DELIBERATELY OMITTED — `getFlightStatus({ date, flightNumber, origin, destination })` declares no types for
801
1046
  // its argument, so there is no honest signature to emit.
802
1047
  // It is CALLABLE at runtime; `bowmark.providers.aa.getFlightStatus` is a compile error here on purpose.
803
1048
  // A `(...args: unknown[])` stand-in would compile and tell you nothing.
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
+
1074
+ /**
1075
+ * Reads an existing American Airlines reservation by its six-letter record locator (PNR) and
1076
+ * the passenger's last name — nothing is signed into, and both are the caller's own details,
1077
+ * passed at call time. Returns the record locator, American's own status string, when the
1078
+ * booking was made, every passenger (name, passenger id, fare type, loyalty number, ticket
1079
+ * numbers), and the itinerary as slices of flown segments (flight number, marketing and
1080
+ * operating carrier codes, cabin, booking class, departure time, and each leg's
1081
+ * origin/destination airport and city). Throws when the locator and last name do not both
1082
+ * match a real reservation — American validates the pair together, so a real locator paired
1083
+ * with the wrong last name answers exactly like one that does not exist at all; there is no
1084
+ * way to tell those two cases apart from the outside. HONEST LIMIT: the not-found path is
1085
+ * live-verified; the success shape above is reconstructed from American's own client code and
1086
+ * has not been observed on the wire, since no consenting real booking was available to test it
1087
+ * — see `retrieve-booking.ts` for what that means for field accuracy.
1088
+ */
1089
+ retrieveBooking(arg0: aaRetrieveBookingArgs): Promise<aaReservation>;
804
1090
  }
805
1091
  }
806
1092
 
@@ -902,6 +1188,54 @@ interface abercrombieSearchQuery {
902
1188
  maxItems?: number;
903
1189
  }
904
1190
 
1191
+ interface abercrombieStoreStock {
1192
+ store: abercrombieStore;
1193
+ inventoryStatus: string;
1194
+ availableQuantity: number;
1195
+ inStock: boolean;
1196
+ availableFrom: string | null;
1197
+ availableFromLabel: string | null;
1198
+ }
1199
+
1200
+ interface abercrombieStock {
1201
+ productId: string;
1202
+ sku: string;
1203
+ productName: string | null;
1204
+ color: string | null;
1205
+ url: string;
1206
+ sizeLabel: string;
1207
+ sizePrimary: string | null;
1208
+ sizeSecondary: string | null;
1209
+ primaryDimension: string | null;
1210
+ secondaryDimension: string | null;
1211
+ inStockOnline: boolean;
1212
+ onlineQuantity: number;
1213
+ onlineStatus: string;
1214
+ preorderEligible: boolean;
1215
+ price: number | null;
1216
+ listPrice: number | null;
1217
+ onSale: boolean;
1218
+ currency: string;
1219
+ findInStoreEligible: boolean;
1220
+ pickupEligible: boolean;
1221
+ stores: abercrombieStoreStock[] | null;
1222
+ }
1223
+
1224
+ interface abercrombieStockQuery {
1225
+ url?: string;
1226
+ id?: string;
1227
+ size?: string;
1228
+ sizePrimary?: string;
1229
+ sizeSecondary?: string;
1230
+ sku?: string;
1231
+ zip?: string;
1232
+ city?: string;
1233
+ state?: string;
1234
+ radiusMiles?: number;
1235
+ maxStores?: number;
1236
+ brand?: "adult" | "kids" | "both";
1237
+ }
1238
+
905
1239
  /**
906
1240
  * Abercrombie & Fitch's own storefront — product search, product detail, size/store stock,
907
1241
  * store locator, current deals and gift card balance.
@@ -943,6 +1277,29 @@ interface abercrombieSearchQuery {
943
1277
  */
944
1278
  findStores(query: abercrombieStoreQuery): Promise<abercrombieStore[]>;
945
1279
 
1280
+ /**
1281
+ * Answers whether ONE size of ONE colourway is buyable RIGHT NOW — online, and at the stores
1282
+ * near a place you name. Identify the product with `url` or `id`, then the size with either
1283
+ * `size` (the site's own label, e.g. "32 X Regular" or "M"), or `sizePrimary`+`sizeSecondary`,
1284
+ * or a `sku` you already hold. Add `zip` OR `city`+`state` to also get per-store stock; omit
1285
+ * all three and `stores` comes back `null` — "you did not ask", which is deliberately distinct
1286
+ * from `[]`, "asked, and no store nearby carries it". Returns the resolved `sku`, the size and
1287
+ * its dimension names, the online answer (`inStockOnline`, a real `onlineQuantity` — the site
1288
+ * publishes counts like 305, not a flag — the site's own `onlineStatus` word,
1289
+ * `preorderEligible`, price/listPrice/onSale), whether the colourway is eligible for the
1290
+ * site's find-in-store and pick-up-in-store journeys at all, and one row per nearby store
1291
+ * carrying that store's full record plus its `inventoryStatus`, `availableQuantity`, `inStock`
1292
+ * and the date it expects the item. **`inStock` is the strict question and is NOT `status !==
1293
+ * "Unavailable"`**: the site's commonest store answer is `Backorderable` with quantity 0,
1294
+ * which means "we will order it for you", not "it is on the shelf" — so `inStock` is true only
1295
+ * for `Available` WITH a quantity above zero. **An ambiguous size THROWS rather than
1296
+ * guessing**: "26" names three lengths on a jean, and answering for one of them would be a
1297
+ * wrong answer on a 200. A `sku` is looked up across the whole style and answers for the
1298
+ * colourway it really belongs to, not the one in the url. This is the per-SIZE, per-STORE
1299
+ * question; `getProduct` answers the different one of what sizes and colours a style comes in.
1300
+ */
1301
+ checkStock(query: abercrombieStockQuery): Promise<abercrombieStock>;
1302
+
946
1303
  /**
947
1304
  * Searches or browses Abercrombie's live catalog the way the site's own search bar and
948
1305
  * category navigation do. Pass EITHER `query` (free text, e.g. "wide leg jeans") OR `category`
@@ -1081,6 +1438,79 @@ interface AshleyFurnitureStore {
1081
1438
  }
1082
1439
  }
1083
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
+
1084
1514
  declare namespace BowmarkProvider_azure {
1085
1515
  // ── Microsoft Azure — the unit's own declarations, verbatim ──
1086
1516
  interface AzurePriceRow {
@@ -1428,6 +1858,57 @@ interface BlendersEyewearPriceResult {
1428
1858
  }
1429
1859
  }
1430
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
+
1431
1912
  declare namespace BowmarkProvider_bmwusa {
1432
1913
  // ── BMW USA — the unit's own declarations, verbatim ──
1433
1914
  interface BmwusaBuiltVehicleOption {
@@ -1484,6 +1965,84 @@ interface BmwusaCpoSearchOptions {
1484
1965
  maxOdometer?: number;
1485
1966
  }
1486
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
+
1487
2046
  /**
1488
2047
  * BMW US car shopping: the Build Your Own configurator and its option pricing, live VIN-level
1489
2048
  * new and Certified Pre-Owned dealer inventory near a ZIP, the model lineup with trims and
@@ -1510,6 +2069,236 @@ interface BmwusaCpoSearchOptions {
1510
2069
  * buckets, not raw numbers, so this filters honestly rather than guessing bucket boundaries).
1511
2070
  */
1512
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_cancer {
2107
+ // ── National Cancer Institute (cancer.gov) — the unit's own declarations, verbatim ──
2108
+ type cancerCenterDesignation =
2109
+ | "Comprehensive Cancer Center"
2110
+ | "Clinical Cancer Center"
2111
+ | "Basic Laboratory Cancer Center";
2112
+
2113
+ interface cancerCenterRow {
2114
+ name: string;
2115
+ /** The center's own detail page on cancer.gov. */
2116
+ url: string;
2117
+ /** NCI's own state grouping — the authoritative field to filter on. */
2118
+ state: string;
2119
+ /** The "City, State" line the page publishes, verbatim. */
2120
+ location: string;
2121
+ /** A second location aside the page publishes for a few centers, e.g.
2122
+ * "(in addition to facilities in Florida and Minnesota)" — present on a
2123
+ * center that operates comprehensive facilities in more than one state and
2124
+ * is cross-listed under each. */
2125
+ locationNote?: string;
2126
+ /** The parent university or health system, when distinct from the center's
2127
+ * own name. Absent for freestanding centers (their own name IS the
2128
+ * institution). */
2129
+ hostInstitution?: string;
2130
+ designation: cancerCenterDesignation;
2131
+ }
2132
+
2133
+ interface cancerCentersResult {
2134
+ /** Every center when no `state` filter is given; only the matching ones
2135
+ * otherwise. */
2136
+ total: number;
2137
+ centers: cancerCenterRow[];
2138
+ }
2139
+
2140
+ type cancerInfoAudience = "patient" | "healthProfessional";
2141
+
2142
+ interface cancerInfoSection {
2143
+ /** The PDQ document's own heading, verbatim, e.g. "Stage Information for
2144
+ * Breast Cancer". */
2145
+ heading: string;
2146
+ /** The section's own text, whitespace-normalized. */
2147
+ text: string;
2148
+ }
2149
+
2150
+ interface cancerInfoSummaryResult {
2151
+ topic: string;
2152
+ audience: cancerInfoAudience;
2153
+ /** The PDQ document's own title, verbatim. */
2154
+ title: string;
2155
+ /** The summary's own page on cancer.gov. */
2156
+ url: string;
2157
+ /** ISO 8601 — the PDQ Editorial Board's own "Updated" date for this exact
2158
+ * document. PDQ is a living, continuously revised document; there is no
2159
+ * honest way to use this text without it. */
2160
+ revisionDate: string;
2161
+ sections: cancerInfoSection[];
2162
+ }
2163
+
2164
+ /**
2165
+ * The US National Cancer Institute: PDQ cancer information, the clinical-trial register,
2166
+ * cancer drugs, NCI-designated cancer centers and the cancer dictionaries. Callable now: the
2167
+ * NCI-Designated Cancer Center directory (`findCancerCenters`) — every center's name,
2168
+ * designation type, location and host institution, optionally filtered by state — and
2169
+ * `getCancerInfoSummary` — NCI's own PDQ information summary for a cancer topic, patient or
2170
+ * health-professional version, with its own revision date. The other eleven declared functions
2171
+ * are still stubs.
2172
+ */
2173
+ interface Unit {
2174
+ /**
2175
+ * The NCI-Designated Cancer Centers — the institutions NCI itself certifies as meeting its
2176
+ * standards for cancer research and care — each with its name, its designation type
2177
+ * (Comprehensive, Clinical, or Basic Laboratory), its city and state, its parent university or
2178
+ * health system when it has one, and the link to its own cancer.gov detail page. `state`
2179
+ * (NCI's own state name, e.g. "California", "Hawai'i", "District of Columbia", matched
2180
+ * case-insensitively but exactly — no fuzzy matching) filters to that state; omitted, every
2181
+ * center is returned. A center that operates comprehensive facilities in more than one state
2182
+ * (Mayo Clinic Cancer Center) is cross-listed under each, with `locationNote` naming its other
2183
+ * locations. This is the whole directory in one document — NCI does not filter it server-side
2184
+ * — so `total` and `centers.length` are always equal.
2185
+ */
2186
+ findCancerCenters(args?: { state?: string }): Promise<cancerCentersResult>;
2187
+
2188
+ /**
2189
+ * NCI's own PDQ information summary for one cancer topic — what the cancer is, its symptoms
2190
+ * and risk factors, how it is diagnosed and staged, the treatment options by stage, and the
2191
+ * prognosis — split into the site's own headed sections, each with its heading and text.
2192
+ * `topic` is cancer.gov's own `/types` path segment (e.g. "breast", "lung", "prostate").
2193
+ * `audience` (default `"patient"`) selects the patient-facing version or the more technical
2194
+ * health-professional one NCI maintains separately; both carry the same `document-dates`
2195
+ * revision block when the topic publishes one. `revisionDate` (ISO 8601) is the PDQ Editorial
2196
+ * Board's own "Updated" date for the exact document returned — PDQ is continuously revised, so
2197
+ * this is not decoration. English only: the Spanish path for the same topic uses different
2198
+ * words, not a parameter substitution on the English slug (breast's HP Spanish page is
2199
+ * `/espanol/tipos/seno/pro/tratamiento-seno-pdq`, not a `breast`/`hp` swap), and reaching it
2200
+ * needs its own resolver over the Spanish `/espanol/tipos` index — unbuilt. Two ways this
2201
+ * throws instead of guessing: `CancerInfoSummaryNotPublishedError` when the topic+audience has
2202
+ * no single consolidated document (NCI is mid-redesign — breast's patient content was migrated
2203
+ * to a task-based hub with no one document or date; its health-professional content is
2204
+ * unaffected), and `CancerInfoSummaryAmbiguousTopicError` when the topic's own index entry
2205
+ * covers more than one genuinely distinct disease, each with its own summary (lung:
2206
+ * non-small-cell and small-cell are both filed under `/types/lung`) — the error names every
2207
+ * option's own URL rather than silently answering for the wrong one.
2208
+ */
2209
+ getCancerInfoSummary(args: { topic: string; audience?: "patient" | "healthProfessional" }): Promise<cancerInfoSummaryResult>;
2210
+ }
2211
+ }
2212
+
2213
+ declare namespace BowmarkProvider_caraway {
2214
+ // ── Caraway Home — the unit's own declarations, verbatim ──
2215
+ interface CarawayVariant {
2216
+ /** Shopify's numeric variant id as a string. */
2217
+ id: string;
2218
+ /** The variant's own label, e.g. "Cream" or "Default Title". */
2219
+ title: string;
2220
+ /** String verbatim from the storefront — "50.00" (dollars) on /products.json, "44500" (cents) on /products/<h>.js. */
2221
+ price: string;
2222
+ /** Same scale as price. Null when the product is not on sale. */
2223
+ compareAtPrice: string | null;
2224
+ /** The store's own SKU. Null on a product without one. */
2225
+ sku: string | null;
2226
+ /** Whether the variant is purchasable right now. */
2227
+ available: boolean;
2228
+ options: string[];
2229
+ }
2230
+ interface CarawayProduct {
2231
+ /** The handle is the only stable identifier across the catalogue. */
2232
+ handle: string;
2233
+ title: string;
2234
+ vendor: string;
2235
+ productType: string;
2236
+ url: string;
2237
+ descriptionHtml: string | null;
2238
+ optionNames: string[];
2239
+ variants: CarawayVariant[];
2240
+ /** Same scale as variants — see CarawayVariant.price. */
2241
+ priceRange: { min: string; max: string } | null;
2242
+ /** True if ANY variant is purchasable. */
2243
+ inStock: boolean;
2244
+ tags: string[];
2245
+ /** Caraway's own images, in the order the storefront publishes them. */
2246
+ images: string[];
2247
+ }
2248
+ interface CarawayCatalogue {
2249
+ /** All matching products, in-stock first, then by handle. */
2250
+ products: CarawayProduct[];
2251
+ /** What the filter DROPPED, in the same register the rest of the library uses. */
2252
+ warnings: string[];
2253
+ }
2254
+ interface CarawayQuizArchetype {
2255
+ /** The archetype slug (e.g. new-customer, 90s-baby). */
2256
+ slug: string;
2257
+ /** Caraway's own copy for the archetype. */
2258
+ label: string;
2259
+ /** Caraway's own one-line archetype blurb. */
2260
+ description: string;
2261
+ /** The product handles the quiz route marks as Recommended. */
2262
+ recommendedHandles: string[];
2263
+ }
2264
+ interface CarawayQuizResult {
2265
+ /** The archetype the quiz terminal page lands on, with the site copy. */
2266
+ archetype: CarawayQuizArchetype;
2267
+ /** The Recommended rail, in stock first. */
2268
+ recommended: CarawayProduct[];
2269
+ /** What the resolver DROPPED, in the same register the rest of the library uses. */
2270
+ warnings: string[];
2271
+ }
2272
+
2273
+ /**
2274
+ * Caraway Home product catalogue — every ceramic cookware piece, its variants, real prices and
2275
+ * stock — read off the live Shopify storefront, plus the buyer-archetype rail the Caraway Home
2276
+ * Quiz terminal renders.
2277
+ */
2278
+ interface Unit {
2279
+ /**
2280
+ * Reads the live Caraway catalogue as Caraway publishes it — every product, its handle, title,
2281
+ * vendor, description, tags, images and the per-variant price the storefront is quoting right
2282
+ * now. Returns [] on a transport failure. The catalog page is the line and the parse is the
2283
+ * unit of work.
2284
+ */
2285
+ listCarawayProducts(opts?: { limit?: number }): Promise<CarawayProduct[]>;
2286
+
2287
+ /**
2288
+ * Reads one product by its handle — every variant, its exact price, the image the storefront
2289
+ * is showing and whether that specific variant is purchasable right now. Takes the handle
2290
+ * listCarawayProducts returns. THROWS on an unknown handle (the store answers a real 404).
2291
+ */
2292
+ getCarawayProduct(handle: string): Promise<CarawayProduct>;
2293
+
2294
+ /**
2295
+ * Routes a quiz's buyer-fit answers to a Caraway archetype and resolves the Recommended rail
2296
+ * the quiz terminal page renders. The archetype slug comes from the quiz's terminal URL
2297
+ * (new-customer, 90s-baby, etc.) and the rail is the live catalogue filtered to the products
2298
+ * Caraway marks for that buyer. THROWS on an unknown archetype — the supported set is encoded
2299
+ * inside the function and surfaced via the same module that owns the catalogue.
2300
+ */
2301
+ runCarawayQuiz(answers: { archetype: string }): Promise<CarawayQuizResult>;
1513
2302
  }
1514
2303
  }
1515
2304
 
@@ -1533,6 +2322,15 @@ interface carsListing {
1533
2322
  hotCar: boolean | null;
1534
2323
  dealer: { name: string | null; status: string | null } | null;
1535
2324
  }
2325
+ interface carsSearch {
2326
+ appliedFilters: { filter: string; value: string | null }[];
2327
+ totalListings: number;
2328
+ totalPages: number;
2329
+ page: number;
2330
+ pageSize: number;
2331
+ sort: string | null;
2332
+ listingIds: string[];
2333
+ }
1536
2334
  interface carsModelResearch {
1537
2335
  year: number;
1538
2336
  make: string;
@@ -1548,17 +2346,44 @@ interface carsModelResearch {
1548
2346
  expertReview: { headline: string; pros: string[]; cons: string[] } | null;
1549
2347
  whatsNew: string | null;
1550
2348
  }
2349
+ interface QuoteIdentity {
2350
+ firstName: string;
2351
+ lastName: string;
2352
+ dob: string;
2353
+ email: string;
2354
+ phone: string;
2355
+ }
2356
+ interface carsVehicleValue {
2357
+ offerCode: string;
2358
+ dealer: { name: string | null; zipCode: string | null } | null;
2359
+ tradeInOffer: number | null;
2360
+ privatePartyValue: number | null;
2361
+ marketLabel: string | null;
2362
+ mileageUsed: number | null;
2363
+ warnings: string[];
2364
+ }
1551
2365
 
1552
2366
  /**
1553
2367
  * Cars.com — the US new/used/certified car marketplace: for-sale inventory with dealer asking
1554
2368
  * prices, one listing's full detail, a valuation for a car you already own, and per-model
1555
- * research (trims, specs, expert and owner reviews). Two functions are built: reading a single
1556
- * listing in full by its id, and one model year's research overview.
2369
+ * research (trims, specs, expert and owner reviews). Three functions are built: searching the
2370
+ * inventory, reading one listing in full, and reading one year/make/model's research overview.
2371
+ * A fourth — the cash-offer valuation — is built too: callers pass a VIN, a ZIP, and the
2372
+ * caller-supplied identity the 2026-07-31 quote-flow ruling requires, and the function returns
2373
+ * the trade-in offer and private-party value perseus published for the assigned local dealer.
1557
2374
  */
1558
2375
  interface Unit {
1559
2376
  /**
1560
- * Reads one cars.com listing in full by its id (the uuid in a /vehicledetail/<id>/ url): VIN,
1561
- * asking price, mileage, year/make/model, stock number, CPO status, EPA highway mpg, the
2377
+ * Searches Cars.com's live for-sale inventory the way its own shopping results page does by
2378
+ * ZIP and radius, new / used / certified-pre-owned, make, model, price, mileage and returns
2379
+ * the matching listing ids (each one is a getListing argument verbatim), the total match count
2380
+ * across all pages, and the filter set the service actually applied.
2381
+ */
2382
+ 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>;
2383
+
2384
+ /**
2385
+ * Reads one cars.com listing in full by its id (the uuid in a /vehicledetail/<id>/ url): VIN,
2386
+ * asking price, mileage, year/make/model, stock number, CPO status, EPA highway mpg, the
1562
2387
  * listing's ZIP and first-listed date, the site's own price badge, and the selling dealer.
1563
2388
  */
1564
2389
  getListing(listingId: string): Promise<carsListing>;
@@ -1570,6 +2395,17 @@ interface carsModelResearch {
1570
2395
  * year — null/absent exactly where cars.com's own page shows nothing for it.
1571
2396
  */
1572
2397
  getModelResearch(args: { make: string; model: string; year: number }): Promise<carsModelResearch>;
2398
+
2399
+ /**
2400
+ * Reads Cars.com's own cash-offer valuation for a car the caller already owns: the trade-in
2401
+ * offer and the private-party value perseus computed for the dealer's assigned ZIP, with the
2402
+ * dealer and mileage the offer was scoped to. Identity is required (caller-supplied, per the
2403
+ * 2026-07-31 quote-flow ruling) so perseus has a person to assign the offer record to. The
2404
+ * function NEVER calls contactDealer, optinDealer, acceptByCode, smsPictureRequest or
2405
+ * media.create — the contact routes the 2026-08-06 standing decision names as the fence for a
2406
+ * cash-offer appraisal.
2407
+ */
2408
+ getVehicleValue(args: { vin: string; identity: QuoteIdentity; postalCode: string; mileage?: number }): Promise<carsVehicleValue>;
1573
2409
  }
1574
2410
  }
1575
2411
 
@@ -1616,6 +2452,34 @@ interface KayakBookingOption {
1616
2452
  seatsRemaining: number | null;
1617
2453
  }
1618
2454
 
2455
+ interface KayakHotelQuery {
2456
+ location: string; // IATA airport code, e.g. "SFO", or a resolvable city
2457
+ checkIn: string; // YYYY-MM-DD
2458
+ checkOut: string; // YYYY-MM-DD
2459
+ adults?: number; // default 2
2460
+ rooms?: number; // default 1
2461
+ }
2462
+
2463
+ // Cheapflights's OWN row shape for stays.
2464
+ interface KayakHotel {
2465
+ id: string;
2466
+ name: string;
2467
+ price: number | null; // per NIGHT, cheapest seller (normalized, see below)
2468
+ totalPrice: number | null; // the WHOLE stay — what rows are sorted on
2469
+ currency: string;
2470
+ seller: string; // who sells that rate ("Priceline")
2471
+ sellerCount: number | null; // how many sellers quoted this property
2472
+ stars: number | null; // property stars, 1-5
2473
+ score: number | null; // guest score out of 10
2474
+ reviewCount: number | null;
2475
+ propertyType: string; // "Hotel", "Motel", "Apartment"
2476
+ neighborhood: string | null;
2477
+ city: string | null;
2478
+ distance: string | null; // "11.7 mi", as the site renders it
2479
+ distanceFrom: string | null; // what that distance is measured from
2480
+ url: string; // deep link to the property
2481
+ }
2482
+
1619
2483
  interface KayakCarQuery {
1620
2484
  pickup: string; // IATA airport code, e.g. "SFO"
1621
2485
  dropoff?: string; // defaults to pickup
@@ -1672,6 +2536,13 @@ interface KayakCar {
1672
2536
  */
1673
2537
  getBookingOptions(flight: KayakFlight): Promise<KayakBookingOption[]>;
1674
2538
 
2539
+ /**
2540
+ * Runs the stays search on cheapflights.com and returns priced properties for a destination
2541
+ * and date range, cheapest TOTAL first. Interaction-gated: the prices only exist after the
2542
+ * site's own multi-phase supplier poll completes.
2543
+ */
2544
+ searchHotels(query: KayakHotelQuery): Promise<KayakHotel[]>;
2545
+
1675
2546
  /**
1676
2547
  * Runs the car-hire search on cheapflights.com and returns priced vehicles for a pickup
1677
2548
  * location and date range, cheapest-first. Interaction-gated: the prices only exist after the
@@ -1777,6 +2648,49 @@ interface ChriscraftPriceResult {
1777
2648
 
1778
2649
  declare namespace BowmarkProvider_classpass {
1779
2650
  // ── ClassPass — the unit's own declarations, verbatim ──
2651
+ /** Everything /v2/venues publishes about one studio — a superset of
2652
+ * ClasspassVenue, so anything holding one can hold the other. */
2653
+ interface ClasspassStudio extends ClasspassVenue {
2654
+ /** What the studio does. On THIS function it comes from the venue record's own
2655
+ * tag block, so it is correct even on a day the studio publishes no classes. */
2656
+ activities: string[];
2657
+ /** ISO-3166 alpha-2, e.g. "US", "GB". */
2658
+ country: string | null;
2659
+ /** The site's neighbourhood label ("South Charlotte"). Null where it publishes none. */
2660
+ neighborhood: string | null;
2661
+ /** The metro area the studio is sold in ("Charlotte Metro", "London Metro"). */
2662
+ metroArea: string | null;
2663
+ description: string | null;
2664
+ /** The studio's OWN site, not its ClassPass page. Null where it publishes none. */
2665
+ website: string | null;
2666
+ phone: string | null;
2667
+ instagram: string | null;
2668
+ facebook: string | null;
2669
+ twitter: string | null;
2670
+ /** Real photographs, largest first. ClassPass's generic fallback placeholders are
2671
+ * dropped — a placeholder passed off as the studio is worse than nothing. */
2672
+ photos: string[];
2673
+ logo: string | null;
2674
+ /** Only the attributes the studio asserts, e.g. ["lgbtq_friendly",
2675
+ * "wheelchair_accessible"]. A false flag means "not claimed" and is dropped. */
2676
+ inclusivity: string[];
2677
+ bookingWindow: string | null;
2678
+ whenToArrive: string | null;
2679
+ whatToBring: string | null;
2680
+ howToGetThere: string | null;
2681
+ proTip: string | null;
2682
+ cancellationPolicy: string | null;
2683
+ /** null where the site holds no policy (it sends the sentinel "UNKNOWN"). */
2684
+ lateCancellation: string | null;
2685
+ demandSignals: string[];
2686
+ /** ClassPass's own published fraction (0-1). Returned under the site's own name
2687
+ * and NOT relabelled a saving — the site does not document its basis. There is
2688
+ * no credit price on this record; per-class cost is getSchedule's `credits`. */
2689
+ averageDiscount: number | null;
2690
+ outOfNetwork: boolean;
2691
+ spots: number | null;
2692
+ }
2693
+
1780
2694
  interface ClasspassSchedule {
1781
2695
  venue: ClasspassVenue;
1782
2696
  /** Dates covered, YYYY-MM-DD in the venue's zone, ascending. A day with no
@@ -1840,14 +2754,83 @@ interface ClasspassScheduleOptions {
1840
2754
  days?: number;
1841
2755
  }
1842
2756
 
2757
+ interface ClasspassSearchQuery {
2758
+ /** Centre of the search, decimal degrees. */
2759
+ lat: number;
2760
+ lon: number;
2761
+ /** Search radius (default 1, clamped to 1-50). */
2762
+ radius: number;
2763
+ /** "mi" (default) or "km". */
2764
+ radiusUnits?: "mi" | "km";
2765
+ /** First day, YYYY-MM-DD. Defaults to TODAY (UTC date). */
2766
+ date?: string;
2767
+ /** Opaque page token from a previous result's `cursor`. */
2768
+ cursor?: string;
2769
+ }
2770
+
2771
+ interface ClasspassSearchResult {
2772
+ results: ClasspassVenue[];
2773
+ /** Opaque page token. Pass back as `query.cursor`; null when the last page is reached. */
2774
+ cursor: string | null;
2775
+ /** The origin's own session id — stable across pages of one search. */
2776
+ searchId: string;
2777
+ /** Always null: the origin does not publish a total. */
2778
+ totalHits: number | null;
2779
+ /** What this function did to the caller's query (defaults applied). */
2780
+ warnings: string[];
2781
+ }
2782
+
1843
2783
  /**
1844
2784
  * ClassPass — fitness, wellness and beauty classes across gyms, studios, spas and salons.
1845
- * `getSchedule` reads one studio's bookable timetable for a day or a week: every session with
1846
- * its start time, instructor, duration, credit price and whether it is still open. Studio and
1847
- * class search, the studio profile, per-slot availability and membership pricing are declared
1848
- * but not built yet.
2785
+ * `getStudio` reads one studio's whole profile in a single request: what it does, where it is,
2786
+ * its rating, amenities, photos, contact routes and the practical booking prose. `getSchedule`
2787
+ * reads that studio's bookable timetable for a day or a week: every session with its start
2788
+ * time, instructor, duration, credit price and whether it is still open. Studio and class
2789
+ * search, per-slot availability and membership pricing are declared but not built yet.
1849
2790
  */
1850
2791
  interface Unit {
2792
+ /**
2793
+ * ClassPass's own location search — POST lat/lon/radius and read back the venues in range,
2794
+ * with their identity, address, coordinates, IANA time zone, the activities the venue teaches,
2795
+ * amenities, ratings, distance and the practical details a person needs to decide which to
2796
+ * open. `query.lat` and `query.lon` are required (decimal degrees, finite, in range);
2797
+ * `query.radius` defaults to 1 and is clamped to 1-50; `query.radiusUnits` is `mi` (default)
2798
+ * or `km`; `query.date` is `YYYY-MM-DD` and defaults to TODAY (UTC). Pagination: the response
2799
+ * carries `cursor` (the base64 page token) and `searchId`; pass `cursor` back verbatim as
2800
+ * `query.cursor` on the next call — the body's shape is identical. One call returns up to 50
2801
+ * venues; the origin does not publish a total count, so `totalHits` is always `null` and the
2802
+ * caller pages until `cursor` is also null. Returns `warnings` whenever the function did
2803
+ * anything to the caller's query (radius defaulted, date defaulted) so a caller rendering the
2804
+ * result knows exactly what shape their input landed in. Each venue block carries `activities`
2805
+ * populated (the search response's `schedules[].venue.activities` is a comma-joined string the
2806
+ * parser splits), which `getSchedule`'s venue block does NOT have on a day the studio
2807
+ * publishes nothing — a real difference, not an inconsistency. **`query` shape today:** only
2808
+ * lat/lon/radius/radiusUnits/date/cursor are honored. The help center's rich facets (text
2809
+ * search, activity filter, time-of-day, credit-price band, neighbourhood) are DECLARED on
2810
+ * `search` but NOT WIRED — see manifest `notImplemented`.
2811
+ */
2812
+ search(query: ClasspassSearchQuery): Promise<ClasspassSearchResult>;
2813
+
2814
+ /**
2815
+ * Reads ONE ClassPass studio's whole profile in a single request — the page a person reads to
2816
+ * decide whether a result is worth booking. `studio` is a ClassPass venue id (74359), the
2817
+ * alias in its public URL ("barrys-charlotte"), or the studio URL itself; all three are
2818
+ * accepted. Returns identity and branch (a chain's locations differ only by `subtitle`), the
2819
+ * full address with coordinates, IANA time zone, neighbourhood and metro area, the studio's
2820
+ * own description, what it actually does (`activities`), amenities and the inclusivity
2821
+ * attributes it asserts, its rating and how many reviews back it, real photographs
2822
+ * (ClassPass's generic `fallback.jpg` placeholders are dropped rather than passed off as the
2823
+ * studio), its own website, phone and socials, and the practical prose a booker needs —
2824
+ * booking window, when to arrive, what to bring, how to get there, and the cancellation
2825
+ * policies. NOTE ON PRICE: this record carries NO credit figure, measured across four venues —
2826
+ * the only price-ish field ClassPass publishes here is `averageDiscount`, its own undocumented
2827
+ * fraction, returned under its own name rather than relabelled as a saving. What a class COSTS
2828
+ * is per-session and comes from `getSchedule`'s `credits`, which is both exact and free of a
2829
+ * second request. A studio that has left ClassPass throws a caller-fixable error quoting the
2830
+ * site's own reason ("Venue disabled") rather than returning a hollow profile.
2831
+ */
2832
+ getStudio(studio: number | string): Promise<ClasspassStudio>;
2833
+
1851
2834
  /**
1852
2835
  * Reads ONE ClassPass studio's bookable timetable — what a person can actually book there, and
1853
2836
  * when. `studio` is a ClassPass venue id (74359), the alias in its public URL
@@ -1965,6 +2948,76 @@ interface CloudflareSearchDomainAvailabilityResult {
1965
2948
  }
1966
2949
  }
1967
2950
 
2951
+ declare namespace BowmarkProvider_cyberpowerpc {
2952
+ // ── CyberPowerPC — the unit's own declarations, verbatim ──
2953
+ interface CyberpowerpcConfigurator {
2954
+ slug: string;
2955
+ name: string;
2956
+ url: string;
2957
+ price: string | null;
2958
+ priceValue: number | null;
2959
+ listPrice: string | null;
2960
+ listPriceValue: number | null;
2961
+ baselineSpecs: string[];
2962
+ }
2963
+ interface CyberpowerpcOption {
2964
+ id: string;
2965
+ name: string;
2966
+ sku: string | null;
2967
+ priceDifference: number;
2968
+ isDefault: boolean;
2969
+ }
2970
+ interface CyberpowerpcSection {
2971
+ code: string;
2972
+ label: string;
2973
+ category: "Core Components" | "Accessories" | "Software & Service";
2974
+ required: boolean;
2975
+ defaultOptionId: string | null;
2976
+ options: CyberpowerpcOption[];
2977
+ }
2978
+ interface CyberpowerpcCatalog {
2979
+ slug: string;
2980
+ title: string;
2981
+ basePrice: number;
2982
+ sections: CyberpowerpcSection[];
2983
+ }
2984
+ interface CyberpowerpcPriceResult {
2985
+ slug: string;
2986
+ basePrice: number;
2987
+ totalPrice: number;
2988
+ lines: { sectionCode: string; sectionLabel: string; optionId: string; optionName: string; priceDifference: number }[];
2989
+ }
2990
+
2991
+ /**
2992
+ * Reads and prices CyberPowerPC's real gaming-PC configurators — every component, every
2993
+ * option's exact price.
2994
+ */
2995
+ interface Unit {
2996
+ /**
2997
+ * Lists every base gaming-PC configurator CyberPowerPC currently sells — AMD and Intel,
2998
+ * Mainstream through Extreme — with its slug, current starting price, list price and stock
2999
+ * CPU/GPU/memory/motherboard/storage lines. Takes nothing. The slug it returns is what
3000
+ * getConfigurator and priceBuild take.
3001
+ */
3002
+ listConfigurators(): Promise<CyberpowerpcConfigurator[]>;
3003
+
3004
+ /**
3005
+ * Reads one base configurator's whole component tree — every section (CPU, GPU, memory,
3006
+ * chassis, storage, ...), every option's exact label, SKU and signed price difference versus
3007
+ * that section's default. The section codes and option ids it returns are what priceBuild
3008
+ * takes.
3009
+ */
3010
+ getConfigurator(slug: string): Promise<CyberpowerpcCatalog>;
3011
+
3012
+ /**
3013
+ * Prices an exact build for one configurator given a caller's part selections (one option id
3014
+ * per section code; any section left out uses its own default). Returns the real live total
3015
+ * the site's own configurator computes, plus a per-section breakdown of what each pick added.
3016
+ */
3017
+ priceBuild(slug: string, selections: Record<string, string>): Promise<CyberpowerpcPriceResult>;
3018
+ }
3019
+ }
3020
+
1968
3021
  declare namespace BowmarkProvider_decked {
1969
3022
  // ── DECKED — the unit's own declarations, verbatim ──
1970
3023
  // DECKED's OWN shapes — not a capability contract.
@@ -2061,6 +3114,34 @@ interface DeckedCabSideOptionResult {
2061
3114
  }
2062
3115
  }
2063
3116
 
3117
+ declare namespace BowmarkProvider_dice {
3118
+ // ── Dice — the unit's own declarations, verbatim ──
3119
+ interface DiceJobDetails {
3120
+ jobId: string;
3121
+ description: string;
3122
+ skills: string[];
3123
+ warnings: string[];
3124
+ }
3125
+ interface diceRow {
3126
+ id: string;
3127
+ }
3128
+
3129
+ /**
3130
+ * Dice — the US technology-only job board. Reaches each posting's full description and skill
3131
+ * list through Dice's own keyless MCP server at mcp.dice.com/mcp; declares tech-job search,
3132
+ * posting-detail reads, employer profiles and a company's open roles.
3133
+ */
3134
+ interface Unit {
3135
+ /**
3136
+ * Returns one Dice posting in full — the HTML description (the same document the consumer page
3137
+ * renders) and the normalized skills array — by the job id `searchJobs` returns. THROWS on a
3138
+ * missing id, on a non-existent posting (MCP returns isError), and on a transport failure, so
3139
+ * a caller can distinguish "no such job" from "empty result set".
3140
+ */
3141
+ getJob(jobId: string): Promise<DiceJobDetails>;
3142
+ }
3143
+ }
3144
+
2064
3145
  declare namespace BowmarkProvider_dickssportinggoods {
2065
3146
  // ── DICK'S Sporting Goods — the unit's own declarations, verbatim ──
2066
3147
  interface dickssportinggoodsDayHours {
@@ -2212,6 +3293,58 @@ interface dillardsRegistry {
2212
3293
  items: dillardsRegistryItem[];
2213
3294
  }
2214
3295
 
3296
+ interface dillardsGetProductQuery {
3297
+ url: string;
3298
+ }
3299
+
3300
+ interface dillardsProductVariant {
3301
+ sku: string;
3302
+ color: string;
3303
+ size: string | null;
3304
+ shipsOnline: boolean;
3305
+ }
3306
+
3307
+ interface dillardsProduct {
3308
+ id: string;
3309
+ catentryId: string;
3310
+ name: string;
3311
+ brand: string | null;
3312
+ url: string;
3313
+ description: string | null;
3314
+ image: string | null;
3315
+ images: string[];
3316
+ priceLow: number | null;
3317
+ priceHigh: number | null;
3318
+ listPrice: number | null;
3319
+ onSale: boolean;
3320
+ rating: number | null;
3321
+ reviewCount: number;
3322
+ colorCount: number;
3323
+ variants: dillardsProductVariant[];
3324
+ }
3325
+
3326
+ interface dillardsStoreRow {
3327
+ storeNumber: string;
3328
+ name: string;
3329
+ address1: string | null;
3330
+ address2: string | null;
3331
+ city: string;
3332
+ state: string;
3333
+ stateCode: string;
3334
+ zip: string;
3335
+ phone: string;
3336
+ url: string;
3337
+ latitude: number | null;
3338
+ longitude: number | null;
3339
+ }
3340
+
3341
+ interface dillardsFindStoresQuery {
3342
+ state?: string;
3343
+ city?: string;
3344
+ zip?: string;
3345
+ limit?: number;
3346
+ }
3347
+
2215
3348
  /**
2216
3349
  * Dillard's department store catalog, store-level stock, store locator and wedding/gift
2217
3350
  * registry search.
@@ -2257,6 +3390,19 @@ interface dillardsRegistry {
2257
3390
  */
2258
3391
  checkStock(query: dillardsCheckStockQuery): Promise<dillardsStockResult>;
2259
3392
 
3393
+ /**
3394
+ * Reads one product's own page — full name, brand, description, primary image plus every
3395
+ * gallery shot, current price range, pre-markdown `listPrice` and the site's own `onSale`
3396
+ * flag, star rating and review count (both null/0 when the product has no reviews yet — the
3397
+ * site omits the field entirely rather than publishing a zero), `colorCount` (distinct
3398
+ * colourways), and `variants[]`, every size/color combination the page lists with its own sku
3399
+ * and `shipsOnline` flag. Pass `url` exactly as `search` returns it in a row's own `url`.
3400
+ * **This is a summary, not a store check** — `variants[].shipsOnline` is the product's own
3401
+ * online-availability flag, independent of any physical store; whether ONE exact size/color is
3402
+ * in stock at a named store is `checkStock`'s job, not this one's.
3403
+ */
3404
+ getProduct(query: dillardsGetProductQuery): Promise<dillardsProduct>;
3405
+
2260
3406
  /**
2261
3407
  * Searches Dillard's wedding/gift registry (dillards.com/registry) — a distinctive Dillard's
2262
3408
  * feature, not a generic department-store search — and returns the matching registry's own
@@ -2279,6 +3425,23 @@ interface dillardsRegistry {
2279
3425
  * through to its item page rather than handing back an unusable list.
2280
3426
  */
2281
3427
  searchRegistry(query: dillardsRegistrySearchQuery): Promise<dillardsRegistry[]>;
3428
+
3429
+ /**
3430
+ * Finds nearby Dillard's store locations the way the site's own /stores locator does — every
3431
+ * row carrying its `storeNumber` (the 4-digit id `checkStock` accepts as its `store`
3432
+ * argument), mall/anchor `name`, `address1`/`address2`, `city`, full `state` and 2-letter
3433
+ * `stateCode`, 5-digit `zip`, 10-digit `phone`, the per-store detail `url`, and the site's own
3434
+ * `latitude`/`longitude` (null when the row omits either). Pass AT LEAST ONE of `state` (full
3435
+ * name like "Ohio" or 2-letter code like "OH" — an unknown state THROWS, naming the 30 the
3436
+ * site publishes), `city` (exact, case-insensitive match against the site's own `city` field —
3437
+ * a name that does not match returns `[]`), or `zip` (5-digit US ZIP, exact match — the site
3438
+ * publishes one store per ZIP today, so this is "the store at this ZIP" without needing a
3439
+ * centroid lookup). Multiple filters narrow; a `state`+`city` request is a per-state page plus
3440
+ * a client-side city filter. Pass `limit` to trim. A query with no filters THROWS, naming
3441
+ * every one the site supports — an empty-argument call would otherwise hand back the full
3442
+ * 272-store list with no way to tell whether that was what the caller meant.
3443
+ */
3444
+ findStores(query: dillardsFindStoresQuery): Promise<dillardsStoreRow[]>;
2282
3445
  }
2283
3446
  }
2284
3447
 
@@ -2295,6 +3458,21 @@ type DiscounttireLocation =
2295
3458
  | { zip: string }
2296
3459
  | { latitude: number; longitude: number };
2297
3460
 
3461
+ /** One tire or wheel, as the site's own product read returns it. Price is
3462
+ * global across stores (verified at three AZ stores on the same sku on the
3463
+ * same day, 2026-08-07), so `getProduct` takes no storeCode even though
3464
+ * productByCode itself requires one. */
3465
+ interface DiscounttireProduct {
3466
+ code: string;
3467
+ name: string | null;
3468
+ brand: string | null;
3469
+ size: string | null;
3470
+ productType: string | null;
3471
+ url: string | null;
3472
+ price: { value: number | null; formatted: string | null } | null;
3473
+ source: string;
3474
+ }
3475
+
2298
3476
  interface DiscounttireStoreRef {
2299
3477
  code: string;
2300
3478
  name: string | null;
@@ -2350,14 +3528,68 @@ interface DiscounttireStock {
2350
3528
  source: string;
2351
3529
  }
2352
3530
 
3531
+ /** A tire size stamped on the sidewall — `225/45R17`. Strings, because the
3532
+ * site's schema declares every field as `String!`. */
3533
+ type TireSize = {
3534
+ diameter: string;
3535
+ width: string;
3536
+ aspectRatio: string;
3537
+ };
3538
+
3539
+ /** One tire product row from the size search. Same shape the site's own
3540
+ * `getProduct` reads back, except price + sku + name + brand, plus the
3541
+ * site's own star rating. */
3542
+ interface DiscounttireTireResult {
3543
+ code: string;
3544
+ name: string | null;
3545
+ brand: string | null;
3546
+ size: string | null;
3547
+ productType: string | null;
3548
+ url: string | null;
3549
+ price: { value: number | null; formatted: string | null } | null;
3550
+ /** `0.0`-`5.0`; null when the line has no reviews. */
3551
+ averageRating: number | null;
3552
+ }
3553
+
3554
+ /** What `searchTiresBySize` returns. */
3555
+ interface DiscounttireTireSizeSearch {
3556
+ /** The storeCode the operation was anchored to (a zip resolves to the
3557
+ * site's nearest store). */
3558
+ storeCode: string;
3559
+ pagination: {
3560
+ currentPage: number | null;
3561
+ numberOfPages: number | null;
3562
+ pageSize: number | null;
3563
+ totalNumberOfResults: number | null;
3564
+ };
3565
+ /** The site's facet names — `Brands`, `Aspect Ratio`, `Price Range`, … */
3566
+ facets: string[];
3567
+ results: DiscounttireTireResult[];
3568
+ source: string;
3569
+ }
3570
+
2353
3571
  /**
2354
3572
  * America's largest independent tire and wheel retailer — which tires and wheels actually fit
2355
3573
  * a given vehicle, what they cost, whether they are in stock near a ZIP, when a store can
2356
- * install them, and the rebates running on them. One function is built: `checkStock` answers
2357
- * whether a specific tire or wheel is gettable near a ZIP, store or coordinate, and on what
2358
- * date. The other fourteen are declared stubs.
3574
+ * install them, and the rebates running on them. Three functions are built: `getProduct` reads
3575
+ * one tire or wheel by its sku (name, brand, size, product type, price, product URL),
3576
+ * `checkStock` answers whether a specific tire or wheel is gettable near a ZIP, store or
3577
+ * coordinate, and on what date, and `searchTiresBySize` searches the tires Discount Tire sells
3578
+ * in a given size (or staggered pair) with prices, ratings and the site's pagination. The
3579
+ * other twelve are declared stubs.
2359
3580
  */
2360
3581
  interface Unit {
3582
+ /**
3583
+ * Reads one tire or wheel product by its sku — name, brand, size, product type, product URL,
3584
+ * and price (value and formatted string). Takes the numeric sku the site's product URLs end in
3585
+ * (/p/<code>), or such a URL. Price is global across stores (verified at three AZ stores on
3586
+ * the same sku on the same day, 2026-08-07), so this function takes no storeCode even though
3587
+ * the underlying `productByCode` operation requires one — the requirement is a schema
3588
+ * compliance constraint, not a per-caller choice. Throws on the site's all-null not-found row,
3589
+ * so a delisted sku surfaces as an error rather than as a row whose every field is null.
3590
+ */
3591
+ getProduct(idOrUrl: string): Promise<DiscounttireProduct>;
3592
+
2361
3593
  /**
2362
3594
  * Answers whether one specific tire or wheel is actually gettable near a place, and when — the
2363
3595
  * site's own availability sentence for the store it resolves to ("Available as soon as
@@ -2371,6 +3603,21 @@ interface DiscounttireStock {
2371
3603
  * "on the shelf right now".
2372
3604
  */
2373
3605
  checkStock(idOrUrl: string, location: { zip: string } | { storeCode: string } | { latitude: number; longitude: number }): Promise<DiscounttireStock>;
3606
+
3607
+ /**
3608
+ * Searches the tires Discount Tire sells in a given size (or staggered pair — `front` and a
3609
+ * different `rear`) and returns what is in stock near a place with prices and star ratings.
3610
+ * `front` and `rear` are stamped-on-the-sidewall sizes like `{ diameter: "17", width: "225",
3611
+ * aspectRatio: "45" }` for `225/45R17`; the site's schema refuses any unknown field on a
3612
+ * `TireSizeInput`, so the function does too. `location` is a 5-digit US zip, an exact store
3613
+ * code, or a coordinate — same three forms `checkStock` takes, same resolution path (zip is
3614
+ * geocoded to its centroid first, then the resolved store is the one the GraphQL operation is
3615
+ * anchored to). `pageNumber` and `pageSize` paginate the result set (pageSize capped at 100).
3616
+ * Returns pagination, the site's own facet list, and a list of tire rows. No
3617
+ * `vehicleAssemblyId` is needed — unlike the by-vehicle searches here, the by-size operations
3618
+ * take `vehicleInfo` as optional and the function never asks for one.
3619
+ */
3620
+ 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>;
2374
3621
  }
2375
3622
  }
2376
3623
 
@@ -2616,14 +3863,38 @@ interface ExtraspaceNearbyFacility {
2616
3863
  distanceMiles: number | null;
2617
3864
  }
2618
3865
 
3866
+ interface ExtraspaceAvailabilityResult {
3867
+ storeId: number;
3868
+ /** Normalized the way search's unitSize option is, e.g. "10x10". */
3869
+ unitSize: string;
3870
+ /** Every unit CLASS matching the requested size; empty if the facility carries none. */
3871
+ matches: ExtraspaceUnitAvailability[];
3872
+ }
3873
+
3874
+ interface ExtraspaceUnitAvailability {
3875
+ sizeDisplay: string;
3876
+ sizeClass: string;
3877
+ widthFeet: number | null;
3878
+ depthFeet: number | null;
3879
+ squareFeet: number | null;
3880
+ /** Whether the site is currently offering THIS class for rent. */
3881
+ available: boolean;
3882
+ unitsAvailable: number | null;
3883
+ streetRate: number | null;
3884
+ webRate: number | null;
3885
+ promotions: string[];
3886
+ features: string[];
3887
+ }
3888
+
2619
3889
  /**
2620
3890
  * Extra Space Storage — self-storage facility search and detail. `search` takes a US city or
2621
3891
  * ZIP and returns the nearby facilities its own locator would, nearest first, each with its
2622
3892
  * address, distance, amenities and the real monthly price of the cheapest unit in every size
2623
3893
  * it carries. `getFacility` reads one of them in full: street address, both phone lines,
2624
3894
  * office and gate-access hours, what its units offer, starting prices, rating, driving
2625
- * directions and the nearby facilities. Per-size availability and published deals are declared
2626
- * but not built yet.
3895
+ * directions and the nearby facilities. `checkAvailability` checks one specific unit size at
3896
+ * one facility and returns every unit class that matches it, each with its own live
3897
+ * availability and price. Published deals are declared but not built yet.
2627
3898
  */
2628
3899
  interface Unit {
2629
3900
  /**
@@ -2663,6 +3934,26 @@ interface ExtraspaceNearbyFacility {
2663
3934
  * caller-fixable error rather than returning an empty-looking result.
2664
3935
  */
2665
3936
  getFacility(storeId: number | string): Promise<ExtraspaceFacilityDetail>;
3937
+
3938
+ /**
3939
+ * Checks current availability and price for one unit SIZE (e.g. "10x10", "5x15" — width x
3940
+ * depth, in feet) at one Extra Space Storage facility. `storeId` is the same id
3941
+ * `search`/`getFacility` take. Returns every unit CLASS at that facility whose dimensions
3942
+ * match the requested size — a facility routinely lists more than one class of the same
3943
+ * nominal size (a live capture of facility 300125 carries four separate `10' x 10'` classes
3944
+ * with different availability), so this never collapses them to one "best" answer the way
3945
+ * `search`'s roll-up does. Each match reports whether the site is CURRENTLY offering it
3946
+ * (`available`), how many units of that class are free (`unitsAvailable`), both the
3947
+ * struck-through "street" rate and the real "web" rate, any active move-in promotion, and the
3948
+ * class's own features. An empty `matches` array means the facility does not carry that size
3949
+ * at all — a coming-soon facility with zero listed unit classes returns `matches: []` for any
3950
+ * size, with no error, exactly like a fully-open facility that simply does not offer it.
3951
+ * `unitSize` outside `width x depth` form (e.g. "12x40", which nothing in this fixture
3952
+ * carries) is not refused as invalid — it is a value the site may or may not stock, so it is
3953
+ * looked up and answered with an empty array like any other size the facility does not have;
3954
+ * only a string that cannot be PARSED as `<number>x<number>` is a caller error.
3955
+ */
3956
+ checkAvailability(storeId: number | string, unitSize: string): Promise<ExtraspaceAvailabilityResult>;
2666
3957
  }
2667
3958
  }
2668
3959
 
@@ -2832,52 +4123,254 @@ interface fordNameplateDirectory {
2832
4123
  nameplates: fordNameplate[];
2833
4124
  }
2834
4125
 
2835
- /**
2836
- * Ford US new-vehicle shopping: live VIN-level dealer inventory near a ZIP, one vehicle by
2837
- * VIN, the model/trim directory and its paint palette, the build-and-price configurator, model
2838
- * specs and MSRP, current incentives, the dealer locator, and recall lookup by VIN. Two
2839
- * functions are callable now. The dealer locator returns Ford dealers near a US ZIP with full
2840
- * address, phone, coordinates, per-day sales and service hours, Ford's own capability flags
2841
- * (EV-certified, commercial fleet, pickup-and-delivery) and links to the dealer's own site and
2842
- * inventory. The nameplate directory returns every Ford model inventory can be searched by —
2843
- * slug, display name, aliases, body style, model years and trims — and resolves a person's own
2844
- * words ("F-150", "mach e", "Super Duty") to the slug the other inventory endpoints take. The
2845
- * other seven declared functions are still stubs.
2846
- */
2847
- interface Unit {
2848
- // NO TYPED SURFACE — every function this unit declares is refused above.
2849
- // The unit is real and callable at runtime; nothing here can say so in types.
2850
- // UNTYPED, DELIBERATELY OMITTED `findDealers({ near, radiusMiles, limit })` declares no types for
2851
- // its argument, so there is no honest signature to emit.
2852
- // It is CALLABLE at runtime; `bowmark.providers.ford.findDealers` is a compile error here on purpose.
2853
- // A `(...args: unknown[])` stand-in would compile and tell you nothing.
4126
+ interface fordOfferProgram {
4127
+ id: string;
4128
+ name: string;
4129
+ /** Ford's own program type, verbatim "Cash", "APR", and whatever else
4130
+ * Ford introduces. */
4131
+ type: string;
4132
+ /** Whole USD, negative for a discount. null when this program is not a
4133
+ * flat-amount one. */
4134
+ amount: number | null;
4135
+ /** null when this program is not a financing offer. Ford sends one term or
4136
+ * several (e.g. 36/48/60/72/84-month options on the same program). */
4137
+ aprTerms: { apr: number; termMonths: number }[] | null;
4138
+ startDate: string | null;
4139
+ endDate: string | null;
4140
+ disclaimer: string | null;
4141
+ /** Ford's own machine code, e.g. "PC_STANDALONE_APR", "DEALER_CASH". */
4142
+ programType: string | null;
4143
+ /** "Retail" (public), "Private" (military/loyalty/first-responder
4144
+ * eligibility this function cannot itself verify), "Campaign", or
4145
+ * whatever else Ford uses. */
4146
+ category: string | null;
4147
+ /** True when Ford Motor Credit finances the program. */
4148
+ financeCompany: boolean;
4149
+ /** Ford's own flag for "eligibility depends on something beyond make/model/
4150
+ * ZIP" (military status, trade-in, loyalty). */
4151
+ conditional: boolean;
4152
+ }
2854
4153
 
2855
- // UNTYPED, DELIBERATELY OMITTED — `listNameplates({ match })` declares no types for
2856
- // its argument, so there is no honest signature to emit.
2857
- // It is CALLABLE at runtime; `bowmark.providers.ford.listNameplates` is a compile error here on purpose.
2858
- // A `(...args: unknown[])` stand-in would compile and tell you nothing.
2859
- }
4154
+ interface fordTrimOffers {
4155
+ trim: string;
4156
+ programs: fordOfferProgram[];
2860
4157
  }
2861
4158
 
2862
- declare namespace BowmarkProvider_framebridge {
2863
- // ── Framebridge the unit's own declarations, verbatim ──
2864
- // Framebridge's OWN shapes — not a capability contract.
4159
+ interface fordOffers {
4160
+ /** The inventory slug this was resolved from, e.g. "f150". */
4161
+ nameplate: string;
4162
+ modelYear: number;
4163
+ /** The ZIP that was searched — incentives are regional. */
4164
+ postalCode: string;
4165
+ /** Ford's own dealer-region code for that ZIP (e.g. "F48B"), when it sends
4166
+ * one. Opaque outside Ford. */
4167
+ region: string | null;
4168
+ trims: fordTrimOffers[];
4169
+ }
2865
4170
 
2866
- interface FramebridgeFrameStyle {
2867
- productId: string; // the key getConfigurator/priceConfiguration take
2868
- handle: string; // the site's own product/moulding permalink
2869
- title: string;
4171
+ interface fordVehicleImage {
2870
4172
  url: string;
2871
- priceRangeMin: number; // dollarsthe cheapest size x conveyance combo
2872
- priceRangeMax: number;
4173
+ /** "primary", "exterior" or "interior" search results carry "primary"
4174
+ * only; this endpoint returns the full set. */
4175
+ role: string;
4176
+ width: number | null;
4177
+ height: number | null;
2873
4178
  }
2874
4179
 
2875
- interface FramebridgeSizeOption {
2876
- size: string; // "XS" | "S" | "M" | "L" | "XL" | "GR" | "XG" | "MG"
2877
- conveyance: "Digital" | "Physical";
2878
- price: number; // this exact combination's own real price
2879
- variantId: string;
2880
- }
4180
+ interface fordVehiclePricing {
4181
+ msrp: number;
4182
+ /** null when Ford has no net figure for this vehicle. */
4183
+ netPriceAfterIncentives: number | null;
4184
+ currency: string;
4185
+ /** Ford's own required legal text — show it alongside any displayed price. */
4186
+ disclaimer: string;
4187
+ }
4188
+
4189
+ interface fordVehicleAvailability {
4190
+ /** "in_stock", "in_transit", or a new value Ford introduces. */
4191
+ status: string;
4192
+ asOf: string;
4193
+ }
4194
+
4195
+ interface fordVehicleDealer {
4196
+ name: string;
4197
+ city: string;
4198
+ state: string;
4199
+ distanceMiles: number;
4200
+ phone: string | null;
4201
+ address: string | null;
4202
+ websiteUrl: string | null;
4203
+ }
4204
+
4205
+ interface fordVehicleOptionPackage {
4206
+ name: string;
4207
+ /** null when Ford prices the package into the vehicle's MSRP rather than
4208
+ * itemizing it. */
4209
+ msrp: number | null;
4210
+ }
4211
+
4212
+ interface fordVehicle {
4213
+ vin: string;
4214
+ /** The slug `listNameplates` returns, e.g. "f150", "explorer". */
4215
+ nameplate: string;
4216
+ displayName: string;
4217
+ year: number;
4218
+ trim: string;
4219
+ bodyStyle: string | null;
4220
+ powertrain: string | null;
4221
+ drivetrain: string | null;
4222
+ exteriorColor: string | null;
4223
+ pricing: fordVehiclePricing;
4224
+ availability: fordVehicleAvailability;
4225
+ dealer: fordVehicleDealer;
4226
+ images: fordVehicleImage[];
4227
+ /** Canonical detail page — link every vehicle mention here. */
4228
+ vdpUrl: string;
4229
+ optionPackages: fordVehicleOptionPackage[];
4230
+ }
4231
+
4232
+ interface fordRecallRecord {
4233
+ /** Ford's own campaign identifier, e.g. "23S37", "26S48". */
4234
+ campaignNumber: string | null;
4235
+ title: string | null;
4236
+ /** Issue date as Ford stores it. */
4237
+ issueDate: string | null;
4238
+ description: string | null;
4239
+ safetyRisk: string | null;
4240
+ remedy: string | null;
4241
+ status: string | null;
4242
+ /** True when this is a Field Service Action / Customer Satisfaction Program
4243
+ * (an FSA, NOT a regulator-mandated recall). */
4244
+ isCustomerSatisfactionProgram: boolean;
4245
+ }
4246
+
4247
+ interface fordVehicleRecalls {
4248
+ vin: string;
4249
+ vehicle: {
4250
+ year: string | null;
4251
+ make: string | null;
4252
+ model: string | null;
4253
+ bodyStyle: string | null;
4254
+ fuelType: string | null;
4255
+ };
4256
+ recalls: fordRecallRecord[];
4257
+ customerSatisfactionPrograms: fordRecallRecord[];
4258
+ counts: {
4259
+ recallsCount: number;
4260
+ cspCount: number;
4261
+ totalFsaCount: number;
4262
+ };
4263
+ /** True when the page acknowledges an empty result for this VIN (no
4264
+ * recalls, no FSAs) rather than an error. Ford's own empty-state copy. */
4265
+ noRecalls: boolean;
4266
+ /** True when the upstream recall service failed to answer — the page
4267
+ * surfaces its own API-error message in that case. */
4268
+ apiError: boolean;
4269
+ warnings: string[];
4270
+ }
4271
+
4272
+ /**
4273
+ * Ford US new-vehicle shopping: live VIN-level dealer inventory near a ZIP, one vehicle by
4274
+ * VIN, the model/trim directory and its paint palette, the build-and-price configurator, model
4275
+ * specs and MSRP, current incentives, the dealer locator, and recall lookup by VIN. Five
4276
+ * functions are callable now. The dealer locator returns Ford dealers near a US ZIP with full
4277
+ * address, phone, coordinates, per-day sales and service hours, Ford's own capability flags
4278
+ * (EV-certified, commercial fleet, pickup-and-delivery) and links to the dealer's own site and
4279
+ * inventory. The nameplate directory returns every Ford model inventory can be searched by —
4280
+ * slug, display name, aliases, body style, model years and trims — and resolves a person's own
4281
+ * words ("F-150", "mach e", "Super Duty") to the slug the other inventory endpoints take.
4282
+ * `getOffers` returns Ford's live, ZIP-regional incentives for a model — cash back, APR
4283
+ * financing (with every term Ford offers, not just the headline one) and any lease programs,
4284
+ * each with its own dates, disclaimer and eligibility category, broken out per trim.
4285
+ * `getVehicle` reads one specific vehicle by VIN — full trim, pricing with Ford's required
4286
+ * disclaimer, availability, the holding dealer's contact details, the FULL image set (exterior
4287
+ * AND interior, not just the one card image a search result carries) and every option package
4288
+ * — and returns `null` rather than throwing when Ford reports the vehicle sold or removed,
4289
+ * which its own docs call a real, non-retryable answer. `getRecalls` returns the open safety
4290
+ * recalls and Customer Satisfaction Programs Ford has published against a VIN — campaign
4291
+ * number, issue date, description, safety risk and remedy for each — splitting
4292
+ * regulator-mandated recalls from Ford's own goodwill FSAs, with `null` for a well-formed VIN
4293
+ * Ford has no record of and an empty result (no recalls, no FSAs) for a known VIN with no open
4294
+ * actions. The other four declared functions are still stubs.
4295
+ */
4296
+ interface Unit {
4297
+ // UNTYPED, DELIBERATELY OMITTED — `findDealers({ near, radiusMiles, limit })` declares no types for
4298
+ // its argument, so there is no honest signature to emit.
4299
+ // It is CALLABLE at runtime; `bowmark.providers.ford.findDealers` is a compile error here on purpose.
4300
+ // A `(...args: unknown[])` stand-in would compile and tell you nothing.
4301
+
4302
+ // UNTYPED, DELIBERATELY OMITTED — `listNameplates({ match })` declares no types for
4303
+ // its argument, so there is no honest signature to emit.
4304
+ // It is CALLABLE at runtime; `bowmark.providers.ford.listNameplates` is a compile error here on purpose.
4305
+ // A `(...args: unknown[])` stand-in would compile and tell you nothing.
4306
+
4307
+ /**
4308
+ * Ford's current incentives for one model near a US ZIP — cash back, APR financing (every term
4309
+ * Ford offers on a program, e.g. 36/48/60/72/84-month options, not just the headline rate) and
4310
+ * any lease programs — broken out per trim, each with its start/end date, Ford's own
4311
+ * disclaimer text, its machine program code, and a `category` ("Retail" public vs. "Private"
4312
+ * military/loyalty/first-responder) so a caller can tell a program anyone qualifies for from
4313
+ * one that needs proof this function cannot itself check. `nameplate` is the slug
4314
+ * `listNameplates` returns ("f150", "bronco-sport"); a handful of commercial-chassis
4315
+ * nameplates the inventory API lists have no incentives page at all and are refused by name,
4316
+ * measured rather than guessed. `postalCode` is required — incentives are regional, and the
4317
+ * SAME model/year at two ZIPs 2,000 miles apart returns genuinely different programs. `year`
4318
+ * defaults to the newest model year Ford is currently running incentives on for that
4319
+ * nameplate.
4320
+ */
4321
+ getOffers(args: { nameplate: string; postalCode: string; year?: number }): Promise<fordOffers>;
4322
+
4323
+ /**
4324
+ * Reads one specific vehicle by its 17-character VIN — full trim, exterior color, complete
4325
+ * pricing with Ford's required disclaimer, live availability, the holding dealer's
4326
+ * name/address/phone/website, the FULL image set (`primary`, `exterior` AND `interior` — a
4327
+ * `searchInventory` result carries `primary` only), every option package, and the canonical
4328
+ * `vdpUrl` Ford's own docs say to link on any mention. `vin` is a required argument, matching
4329
+ * Ford's own pattern (17 characters, excluding I/O/Q) and checked locally before spending a
4330
+ * request. Returns `null` — not an error — when Ford answers `VEHICLE_NOT_FOUND`: Ford's own
4331
+ * docs call a 404 here "sold or removed... not a retryable error", so a vehicle that sold
4332
+ * between search and read is a real, unsurprising answer rather than a failure.
4333
+ */
4334
+ getVehicle(vin: string): Promise<fordVehicle | null>;
4335
+
4336
+ /**
4337
+ * Reads the open safety recalls and Customer Satisfaction Programs (FSAs) Ford has published
4338
+ * against one specific VIN, and what each one says to do — the same answer an owner or a
4339
+ * used-car buyer gets on Ford's owner-support recalls page. `vin` is required and locally
4340
+ * validated against the same 17-character pattern `getVehicle` uses (A-H, J-N, P, R-Z, 0-9).
4341
+ * Returns `null` — not an error — when the VIN is well-formed but unknown to Ford (the page
4342
+ * sets `isVinInvalid: true`); the call surfaces `noRecalls: true` for a known VIN with no open
4343
+ * actions, and the response separates regulator-mandated `recalls` from optional
4344
+ * `customerSatisfactionPrograms` (the latter are Ford's free goodwill fixes, NOT safety
4345
+ * recalls). Each record carries Ford's own campaign number, issue date, the free-form
4346
+ * description, the stated safety risk, the prescribed remedy, and the status Ford reports.
4347
+ * When Ford's recall upstream fails, the call returns a successful shape with `apiError: true`
4348
+ * and the upstream's own error message in `warnings` — a transient 5xx shouldn't kill the
4349
+ * caller. No sign-in: the page is public.
4350
+ */
4351
+ getRecalls(vin: string): Promise<fordVehicleRecalls | null>;
4352
+ }
4353
+ }
4354
+
4355
+ declare namespace BowmarkProvider_framebridge {
4356
+ // ── Framebridge — the unit's own declarations, verbatim ──
4357
+ // Framebridge's OWN shapes — not a capability contract.
4358
+
4359
+ interface FramebridgeFrameStyle {
4360
+ productId: string; // the key getConfigurator/priceConfiguration take
4361
+ handle: string; // the site's own product/moulding permalink
4362
+ title: string;
4363
+ url: string;
4364
+ priceRangeMin: number; // dollars — the cheapest size x conveyance combo
4365
+ priceRangeMax: number;
4366
+ }
4367
+
4368
+ interface FramebridgeSizeOption {
4369
+ size: string; // "XS" | "S" | "M" | "L" | "XL" | "GR" | "XG" | "MG"
4370
+ conveyance: "Digital" | "Physical";
4371
+ price: number; // this exact combination's own real price
4372
+ variantId: string;
4373
+ }
2881
4374
 
2882
4375
  interface FramebridgeMatOption {
2883
4376
  code: string; // the value priceConfiguration's mats[] takes, e.g. "WH02"
@@ -2980,9 +4473,42 @@ interface fredSeries {
2980
4473
  notes: string | null;
2981
4474
  }
2982
4475
 
4476
+ interface fredCategoryRow {
4477
+ id: number;
4478
+ name: string;
4479
+ parentId: number;
4480
+ }
4481
+
4482
+ interface fredCategory {
4483
+ id: number;
4484
+ name: string;
4485
+ parentId: number;
4486
+ children: fredCategoryRow[];
4487
+ series: fredSeries[];
4488
+ }
4489
+
4490
+ interface fredObservation {
4491
+ date: string;
4492
+ /** null where FRED holds no observation for that period — a market holiday in a
4493
+ * daily series, or the first year of a year-over-year transform. */
4494
+ value: number | null;
4495
+ }
4496
+
4497
+ interface fredObservations {
4498
+ seriesId: string;
4499
+ /** The transform FRED reports having applied: "lin" (none), "pc1", "pch", … */
4500
+ units: string;
4501
+ observationStart: string;
4502
+ observationEnd: string;
4503
+ realtimeStart: string;
4504
+ realtimeEnd: string;
4505
+ count: number;
4506
+ observations: fredObservation[];
4507
+ }
4508
+
2983
4509
  /**
2984
- * US economic data releases and their publication calendar, and the agencies FRED republishes
2985
- * data from, off the St. Louis Fed's FRED.
4510
+ * US economic data releases and their publication calendar, the agencies FRED republishes data
4511
+ * from, series metadata, and FRED's own category tree, off the St. Louis Fed's FRED.
2986
4512
  */
2987
4513
  interface Unit {
2988
4514
  /**
@@ -3016,6 +4542,34 @@ interface fredSeries {
3016
4542
  * back as a caller-fixable error naming the problem rather than as an empty result.
3017
4543
  */
3018
4544
  getSeriesInfo(seriesId: string): Promise<fredSeries>;
4545
+
4546
+ /**
4547
+ * Reads the actual numbers for a FRED series — the dated observations themselves, oldest
4548
+ * first, with a missing period returned as `value: null` rather than as a `NaN` or a silently
4549
+ * dropped row. Called bare (`getSeriesObservations("GDPC1")`) it returns the series' full
4550
+ * history; `from`/`to` (ISO yyyy-mm-dd) narrow the window. It also runs FRED's own transforms
4551
+ * server-side so a caller never has to recompute one: `units` converts the level to a change
4552
+ * (`pc1` percent change from a year ago — the usual way to read inflation off CPIAUCSL — plus
4553
+ * `pch`, `chg`, `log` and the rest of FRED's ten codes), and `frequency` with
4554
+ * `aggregationMethod` collapses a series to a coarser period (`{ frequency: "a",
4555
+ * aggregationMethod: "avg" }` turns the monthly unemployment rate into annual averages). The
4556
+ * result carries the transform FRED reports having applied and the vintage it served, so a
4557
+ * caller can tell what they actually got. This is the function to call once
4558
+ * `searchSeries`/`getSeriesInfo` has identified the right series id — e.g. A191RL1Q225SBEA for
4559
+ * the US real GDP growth rate.
4560
+ */
4561
+ getSeriesObservations(args: string | { seriesId: string; from?: string; to?: string; units?: string; frequency?: string; aggregationMethod?: string }): Promise<fredObservations>;
4562
+
4563
+ /**
4564
+ * Browses FRED's category tree the way fred.stlouisfed.org/categories does — the category
4565
+ * itself (id/name/parent), its immediate child categories, and the series filed directly under
4566
+ * it (the same shape getSeriesInfo returns per series, so a caller can read
4567
+ * units/frequency/lastUpdated off a browsed result with no second call). Called bare it starts
4568
+ * at the root (id 0). FRED organizes its ~800,000 series into a real hierarchy, so this is how
4569
+ * a caller explores 'what's available in this area' before knowing a series id to look up
4570
+ * directly. An unknown category id comes back as a caller-fixable error.
4571
+ */
4572
+ browseCategory(categoryId?: number): Promise<fredCategory>;
3019
4573
  }
3020
4574
  }
3021
4575
 
@@ -3456,6 +5010,15 @@ interface graingerRow {
3456
5010
  id: string;
3457
5011
  }
3458
5012
 
5013
+ interface graingerSearchRow {
5014
+ itemNumber: string;
5015
+ name: string;
5016
+ url: string;
5017
+ brand: string | null;
5018
+ price: { amount: number; currency: string; perUnit: string } | null;
5019
+ thumbnail: string | null;
5020
+ }
5021
+
3459
5022
  interface graingerBranchRow {
3460
5023
  branchNumber: string;
3461
5024
  name: string;
@@ -3466,12 +5029,55 @@ interface graingerBranchRow {
3466
5029
  hours: { day: string; hours: string }[];
3467
5030
  }
3468
5031
 
5032
+ interface graingerProductRow {
5033
+ itemNumber: string;
5034
+ manufacturerModel: string | null;
5035
+ name: string;
5036
+ description: string | null;
5037
+ brand: string | null;
5038
+ url: string;
5039
+ images: string[];
5040
+ price: { amount: number; currency: string; perUnit: string } | null;
5041
+ specs: { name: string; value: string }[];
5042
+ availabilitySummary: string | null;
5043
+ }
5044
+
5045
+ interface graingerStockRow {
5046
+ itemNumber: string;
5047
+ zip: string;
5048
+ quantity: number;
5049
+ shipping: { message: string | null; fulfillmentCode: string | null; availKey: string | null } | null;
5050
+ pickup: {
5051
+ message: string | null;
5052
+ fulfillmentCode: string | null;
5053
+ availKey: string | null;
5054
+ branch: {
5055
+ branchCode: string;
5056
+ city: string | null;
5057
+ address: { street: string | null; city: string | null; state: string | null; zip: string | null; country: string | null } | null;
5058
+ url: string | null;
5059
+ } | null;
5060
+ } | null;
5061
+ }
5062
+
3469
5063
  /**
3470
- * Grainger's industrial MRO catalog, product detail, and branch/stock availability —
3471
- * findBranch is live (nationwide branch directory, address/phone/hours); catalog, product
3472
- * detail and stock checks are still stubs.
5064
+ * Grainger's industrial MRO catalog, product detail, and branch/stock availability — search
5065
+ * (keyword/category catalog search returning name, item number, brand, price and thumbnail),
5066
+ * findBranch (nationwide branch directory), getProduct (price, pack size, spec table,
5067
+ * availability by item number or URL) and checkStock (shipping-to-zip and
5068
+ * pickup-at-nearest-branch fulfillment estimates) are all live.
3473
5069
  */
3474
5070
  interface Unit {
5071
+ /**
5072
+ * Searches Grainger's industrial MRO catalog by keyword, returning matching products — item
5073
+ * number, name, brand, list price and thumbnail. Takes `query` (free text, e.g. "antistatic
5074
+ * gloves"). A SPECIFIC query resolves to Grainger's own matching leaf category and returns its
5075
+ * real products; a broad query (e.g. "gloves" alone) can resolve to a category-of-categories
5076
+ * browse page one or more levels above any actual product and throws rather than returning an
5077
+ * empty array — narrow the query if that happens.
5078
+ */
5079
+ search(args: object): Promise<graingerSearchRow[]>;
5080
+
3475
5081
  /**
3476
5082
  * Finds Grainger's own U.S. branches near a ZIP, city or state — address, phone, hours and
3477
5083
  * curbside-pickup availability, off the site's own nationwide directory. `zip` matches by its
@@ -3481,6 +5087,26 @@ interface graingerBranchRow {
3481
5087
  * truncating.
3482
5088
  */
3483
5089
  findBranch(args: object): Promise<graingerBranchRow[]>;
5090
+
5091
+ /**
5092
+ * Reads one Grainger product page in full — price and pack size/unit of measure, the full spec
5093
+ * table, the manufacturer's own part number, and a shipping/pickup availability summary. Takes
5094
+ * `itemNumber` (Grainger's own catalog id, e.g. "26K909" — resolves directly, no descriptive
5095
+ * slug needed) or `url` (a full grainger.com product URL). Throws if the item number doesn't
5096
+ * exist (a clean 404) rather than returning an empty row.
5097
+ */
5098
+ getProduct(args: object): Promise<graingerProductRow>;
5099
+
5100
+ /**
5101
+ * Checks real fulfillment availability for one item (`itemNumber` or `url`, same as
5102
+ * `getProduct`) at a caller-supplied `zip` (required, 5-digit US) — both shipping-to-that-zip
5103
+ * and pickup-at-the-nearest-branch-to-that-zip, in one call. Returns the site's own message
5104
+ * text (an arrival/ready-by estimate, never a literal stock count — the site doesn't publish
5105
+ * one) plus its opaque status codes for each mode, and the ACTUAL branch that answered the
5106
+ * pickup half (nearest-to-point, not necessarily one the caller could have named). Optional
5107
+ * `quantity` (default 1) is forwarded to the site.
5108
+ */
5109
+ checkStock(args: object): Promise<graingerStockRow>;
3484
5110
  }
3485
5111
  }
3486
5112
 
@@ -4278,6 +5904,72 @@ interface HellofreshRecipeSearchPage {
4278
5904
  }
4279
5905
  }
4280
5906
 
5907
+ declare namespace BowmarkProvider_hellotend {
5908
+ // ── Tend Dental — the unit's own declarations, verbatim ──
5909
+ interface HellotendMarket {
5910
+ slug: string; // e.g. "new-york-city"
5911
+ name: string; // e.g. "New York City"
5912
+ location: { lat: number; lon: number } | null;
5913
+ bookingEnabled: boolean;
5914
+ }
5915
+ interface HellotendStudio {
5916
+ slug: string; // e.g. "hells-kitchen" — what listServices takes
5917
+ name: string;
5918
+ market: string; // e.g. "new-york-city"
5919
+ address: string | null;
5920
+ location: { lat: number; lon: number } | null;
5921
+ openingDate: string | null;
5922
+ serviceCodes: string[]; // ["CLNCHK","WHTNG",...] — the codes this studio accepts
5923
+ bookingEnabled: boolean;
5924
+ familyBookingEnabled: boolean;
5925
+ }
5926
+ interface HellotendService {
5927
+ code: string | null; // e.g. "CLNCHK" — null on category-level entries
5928
+ name: string; // e.g. "Exam"
5929
+ longName: string | null; // e.g. "Dental Exam"
5930
+ description: string | null;
5931
+ bookingDescription: string | null;
5932
+ duration: string | null; // e.g. "70 minutes or less"
5933
+ }
5934
+
5935
+ /**
5936
+ * Reads Tend Dental's public booking chain — every market, every studio, every service a
5937
+ * studio offers — straight from hellotend.com's own Next.js data route, no key, no browser.
5938
+ */
5939
+ interface Unit {
5940
+ /**
5941
+ * Lists every market Tend serves — the 6 metros the booking chain currently offers (NYC,
5942
+ * Washington DC, Atlanta, Boston, Chicago, Nashville), with each market's slug, lat/lon and
5943
+ * booking-enabled flag. Takes nothing. The slug it returns is what listStudios and
5944
+ * listServices take. THROWS rather than returning [] when the data route answers without its
5945
+ * payload or names no markets — Tend operates 6 metros and zero is never an honest answer.
5946
+ */
5947
+ listMarkets(): Promise<HellotendMarket[]>;
5948
+
5949
+ /**
5950
+ * Lists every Tend dental studio — 33+ across all markets, with name, slug, market, address,
5951
+ * lat/lon, opening date, the service codes that studio accepts, and whether it offers
5952
+ * family-booking. The market arg is OPTIONAL: omit it to get the full set across all markets,
5953
+ * pass a market slug to filter. THROWS rather than returning [] when the data route answers
5954
+ * without its payload or names no studios; surfaces an unknown market slug as a caller-fixable
5955
+ * error listing the real ones.
5956
+ */
5957
+ listStudios(market?: string): Promise<HellotendStudio[]>;
5958
+
5959
+ /**
5960
+ * Lists the service codes a specific Tend studio offers (Dental Exam CLNCHK, Clear Aligners
5961
+ * INVISALN, Emergency EMGNCY, Sleep Apnea Consult SLPCONS, Cosmetic, Procedures) with each
5962
+ * service's display name, code, duration and short description. The CODE is what a real Tend
5963
+ * booking needs to advance to the time-picker page. The first four carry a code; the last two
5964
+ * (Cosmetic, Procedures) are category-level landing entries that route to sub-flows and are
5965
+ * returned with a null code rather than dropped. THROWS rather than returning [] when the data
5966
+ * route answers without its payload or names no services; surfaces an unknown studio as a
5967
+ * caller-fixable error listing the real ones in that market.
5968
+ */
5969
+ listServices(market: string, studio: string): Promise<HellotendService[]>;
5970
+ }
5971
+ }
5972
+
4281
5973
  declare namespace BowmarkProvider_hilton {
4282
5974
  // ── Hilton — the unit's own declarations, verbatim ──
4283
5975
  interface hiltonRoomOffer {
@@ -5523,6 +7215,99 @@ interface InteriorDefineCartHandoff {
5523
7215
  }
5524
7216
  }
5525
7217
 
7218
+ declare namespace BowmarkProvider_joybird {
7219
+ // ── Joybird — the unit's own declarations, verbatim ──
7220
+ interface JoybirdConfigurator {
7221
+ slug: string;
7222
+ name: string;
7223
+ sku: string;
7224
+ type: string;
7225
+ family: string;
7226
+ url: string;
7227
+ finalPrice: number;
7228
+ originalPrice: number;
7229
+ discountPercent: number;
7230
+ }
7231
+ interface JoybirdOptionValue {
7232
+ sku: string;
7233
+ value: string;
7234
+ cover: string | null;
7235
+ color: string | null;
7236
+ family: string;
7237
+ tier: number;
7238
+ petFriendly: boolean;
7239
+ performanceFabric: boolean;
7240
+ sustainableFabric: boolean;
7241
+ popular: boolean;
7242
+ }
7243
+ interface JoybirdOption {
7244
+ id: number;
7245
+ name: string;
7246
+ type: string | null;
7247
+ values: JoybirdOptionValue[];
7248
+ }
7249
+ interface JoybirdCatalog {
7250
+ slug: string;
7251
+ name: string;
7252
+ sku: string;
7253
+ type: string;
7254
+ family: string;
7255
+ url: string;
7256
+ dimensions: string;
7257
+ finalPrice: number;
7258
+ originalPrice: number;
7259
+ discountPercent: number;
7260
+ promotionStart: string | null;
7261
+ promotionEnd: string | null;
7262
+ options: JoybirdOption[];
7263
+ }
7264
+ interface JoybirdPriceLine {
7265
+ optionId: number;
7266
+ optionName: string;
7267
+ optionSku: string;
7268
+ valueSku: string;
7269
+ valueName: string;
7270
+ }
7271
+ interface JoybirdPriceResult {
7272
+ slug: string;
7273
+ sku: string;
7274
+ finalPrice: number;
7275
+ originalPrice: number;
7276
+ discountPercent: number;
7277
+ lines: JoybirdPriceLine[];
7278
+ }
7279
+
7280
+ /**
7281
+ * Reads Joybird's real sofa/sectional configurator — every configurable product, every fabric
7282
+ * and wood stain, and the live configured price Joybird's own page shows.
7283
+ */
7284
+ interface Unit {
7285
+ /**
7286
+ * Lists every configurable product Joybird sells — sofas, sectionals, chairs, ottomans, beds,
7287
+ * organised by collection — with its slug, name, current displayed price, list price and
7288
+ * active discount. Takes nothing. The slug it returns is what getConfigurator and
7289
+ * priceConfigurator take.
7290
+ */
7291
+ listConfigurators(): Promise<JoybirdConfigurator[]>;
7292
+
7293
+ /**
7294
+ * Reads one product's full configurator — its dimensions, current price, active promotion
7295
+ * window, and every option slot the product exposes (Fabric, Wood Stain, Orientation, ...)
7296
+ * with the site's full swatch list for each. The slot ids and swatch SKUs it returns are what
7297
+ * priceConfigurator takes.
7298
+ */
7299
+ getConfigurator(slug: string): Promise<JoybirdCatalog>;
7300
+
7301
+ /**
7302
+ * Prices an exact configuration for one product given the caller's swatch picks (one swatch
7303
+ * SKU per slot id; any slot left out uses its first available swatch as a documented default).
7304
+ * Returns the real live total Joybird's own page shows, plus a per-slot breakdown of what was
7305
+ * picked.
7306
+ */
7307
+ priceConfigurator(slug: string, selections: Record<string, string>): Promise<JoybirdPriceResult>;
7308
+ }
7309
+ }
7310
+
5526
7311
  declare namespace BowmarkProvider_kayak {
5527
7312
  // ── Kayak — the unit's own declarations, verbatim ──
5528
7313
  interface KayakQuery {
@@ -5678,6 +7463,17 @@ interface LabcorpTestSummary {
5678
7463
  currency: string; // "USD"
5679
7464
  }
5680
7465
 
7466
+ interface LabcorpTestDetail extends LabcorpTestSummary {
7467
+ sampleType: string; // "Blood & Urine", "Nasal Swab"
7468
+ collectionMethod: string; // "In person at a Labcorp location"
7469
+ turnaroundTime: string; // "1-2 days from when your sample arrives at our lab"
7470
+ ageRange: string; // "18-100", "" if absent
7471
+ metaDescription: string;
7472
+ metaTitle: string;
7473
+ shortDescriptionHtml: string;
7474
+ descriptionHtml: string;
7475
+ }
7476
+
5681
7477
  /** Lab test pricing, PSC location lookup and appointment availability from Labcorp. */
5682
7478
  interface Unit {
5683
7479
  /**
@@ -5686,6 +7482,14 @@ interface LabcorpTestSummary {
5686
7482
  * No doctor's visit required to order.
5687
7483
  */
5688
7484
  search(query: string): Promise<LabcorpTestSummary[]>;
7485
+
7486
+ /**
7487
+ * Returns the full OnDemand test detail for one sku — price, descriptions, sample type,
7488
+ * collection method, turnaround time and acceptable age band. Combines the catalog row
7489
+ * (GraphQL) with the specimen/turnaround facts the site renders on the PDP HTML. Pass the sku
7490
+ * returned by `search`.
7491
+ */
7492
+ getTest(sku: string): Promise<LabcorpTestDetail>;
5689
7493
  }
5690
7494
  }
5691
7495
 
@@ -6161,6 +7965,132 @@ interface LufthansaBaggageAllowance {
6161
7965
  }
6162
7966
  }
6163
7967
 
7968
+ declare namespace BowmarkProvider_lululemon {
7969
+ // ── lululemon — the unit's own declarations, verbatim ──
7970
+ interface LululemonVariant {
7971
+ /** The identifier lululemon's own checkout uses, e.g. "us_117376359". */
7972
+ sku: string;
7973
+ /** Which option each dimension is set to, e.g. { size: "4" }. */
7974
+ options: Record<string, string>;
7975
+ /** The store's own availability flag for this exact SKU. */
7976
+ available: boolean;
7977
+ price: number | null;
7978
+ salePrice: number | null;
7979
+ }
7980
+ interface LululemonOptionGroup {
7981
+ /** The machine name. "size" on every lululemon product measured. */
7982
+ type: string;
7983
+ /** The site's own label for the picker, e.g. "Size". */
7984
+ label: string;
7985
+ options: { value: string; label: string }[];
7986
+ }
7987
+ interface LululemonColorway {
7988
+ /** lululemon's own colour code, e.g. "TRUE-NAVY". */
7989
+ colorId: string;
7990
+ color: string;
7991
+ colorFamily: string | null;
7992
+ price: number | null;
7993
+ /** Set only when this colourway is marked down. */
7994
+ salePrice: number | null;
7995
+ promoMessage: string | null;
7996
+ /** The product URL pinned to this colour, as the store publishes it. */
7997
+ url: string;
7998
+ swatchImage: string | null;
7999
+ images: string[];
8000
+ inStock: boolean;
8001
+ optionGroups: LululemonOptionGroup[];
8002
+ /** What can be BOUGHT in this colour right now — not the full size run. */
8003
+ variants: LululemonVariant[];
8004
+ }
8005
+ interface LululemonSizeType {
8006
+ /** A sibling product that is the same style in another length. */
8007
+ productId: string;
8008
+ size: string;
8009
+ selected: boolean;
8010
+ }
8011
+ interface LululemonProduct {
8012
+ id: string;
8013
+ title: string;
8014
+ brand: string;
8015
+ url: string;
8016
+ /** The store's own audience attribute, e.g. "women". */
8017
+ gender: string | null;
8018
+ rating: number | null;
8019
+ reviewCount: number | null;
8020
+ inStock: boolean;
8021
+ priceLow: number | null;
8022
+ priceHigh: number | null;
8023
+ colorways: LululemonColorway[];
8024
+ /** Other lengths of the same style. Empty on every product measured — on this
8025
+ * site an inseam is its OWN product, not an option. */
8026
+ sizeTypes: LululemonSizeType[];
8027
+ }
8028
+ interface LululemonRow {
8029
+ id: string;
8030
+ title: string;
8031
+ url: string;
8032
+ priceLow: number | null;
8033
+ priceHigh: number | null;
8034
+ colorCount: number | null;
8035
+ inStock: boolean | null;
8036
+ /** False when the row came from the site's product index and the catalogue
8037
+ * behind the prices does not carry it. id and url still work. */
8038
+ priced: boolean;
8039
+ }
8040
+ interface LululemonSearch {
8041
+ query: string;
8042
+ products: LululemonRow[];
8043
+ /** How many entries matched before the row cap. */
8044
+ matched: number;
8045
+ warnings: string[];
8046
+ }
8047
+ interface LululemonSimilarProducts {
8048
+ seedProductId: string;
8049
+ products: LululemonRow[];
8050
+ totalRanked: number | null;
8051
+ warnings: string[];
8052
+ }
8053
+
8054
+ /**
8055
+ * lululemon's athletic apparel catalogue — search it, and read one product's full
8056
+ * configurator: every colourway with its own price and images, the size options, and which
8057
+ * exact SKUs are buyable right now.
8058
+ */
8059
+ interface Unit {
8060
+ /**
8061
+ * Searches lululemon's catalogue by free text and returns matching product rows, closest match
8062
+ * first — id, title, URL, price range, how many colours the style comes in, and whether it is
8063
+ * in stock. Ranks over the site's own published product index, then reads the price and colour
8064
+ * count per row. A match the pricing catalogue does not carry still comes back, with `priced:
8065
+ * false` and null prices; `matched` says how many matched before the row cap so a caller can
8066
+ * raise `limit` (default 8, max 24).
8067
+ */
8068
+ search(query: { query: string; limit?: number }): Promise<LululemonSearch>;
8069
+
8070
+ /**
8071
+ * Reads one product's full configurator the way its product page presents it — every colourway
8072
+ * with its own price, sale price, promo message, swatch, image set and URL; the size picker
8073
+ * listing the sizes that colourway can CURRENTLY SELL; and one entry per sellable SKU with the
8074
+ * store's own id, so a caller can answer 'which colours can I get in a 6 right now'. This feed
8075
+ * expresses sold-out by OMISSION rather than by a flag — measured across all three captured
8076
+ * fixtures, the picker and the SKU list are the same set in all 61 colourways and `available`
8077
+ * is true on 363 of 363 SKUs — so presence is the stock signal and `available` is passed
8078
+ * through rather than relied on.
8079
+ */
8080
+ getProduct(query: { productId: string }): Promise<LululemonProduct>;
8081
+
8082
+ /**
8083
+ * Returns the products lululemon's own product pages recommend alongside one product — the
8084
+ * 'You may also like' rail — as priced rows in the store's own ranked order, de-duplicated to
8085
+ * one row per style. It is the store's ranking, not ours, and it does NOT reliably surface the
8086
+ * same garment in another length: measured on the Align 25" pant, none of the six recommended
8087
+ * rows was a sibling inseam even though the sitemap carries them, so reaching another length
8088
+ * is a `search`.
8089
+ */
8090
+ getSimilarProducts(query: { productId: string; limit?: number }): Promise<LululemonSimilarProducts>;
8091
+ }
8092
+ }
8093
+
6164
8094
  declare namespace BowmarkProvider_mailchimp {
6165
8095
  // ── Mailchimp — the unit's own declarations, verbatim ──
6166
8096
  interface mailchimpPlanTier {
@@ -6206,6 +8136,29 @@ interface mailchimpPlanPricing {
6206
8136
  }
6207
8137
  }
6208
8138
 
8139
+ declare namespace BowmarkProvider_marriott {
8140
+ // ── Marriott — the unit's own declarations, verbatim ──
8141
+ interface MarriottHotelListing {
8142
+ id: string; // marsha code
8143
+ name: string;
8144
+ brand: string;
8145
+ url: string;
8146
+ place: string; // the resolved place slug, e.g. "usa-maryland"
8147
+ }
8148
+
8149
+ /** Marriott Bonvoy hotel search, award availability, reservations and property details. */
8150
+ interface Unit {
8151
+ /**
8152
+ * Lists Marriott-family properties published on the site's own hotel-sitemap directory for one
8153
+ * US state or country (`place`, e.g. "Maryland", "France" — never a bare city or landmark,
8154
+ * which this directory does not index per property). `query` (optional) narrows the list by a
8155
+ * case-insensitive substring match against each property's own display name, which often but
8156
+ * not always carries a city. Returns each property's marsha id, name, brand and overview URL.
8157
+ */
8158
+ findHotels(args: { place: string; query?: string }): Promise<MarriottHotelListing[]>;
8159
+ }
8160
+ }
8161
+
6209
8162
  declare namespace BowmarkProvider_mcdonalds {
6210
8163
  // ── McDonald's — the unit's own declarations, verbatim ──
6211
8164
  interface mcdonaldsMenuItem {
@@ -6538,6 +8491,101 @@ interface medicareNursingHomeSearch {
6538
8491
  homes: medicareNursingHome[];
6539
8492
  }
6540
8493
 
8494
+ interface medicareHospitalMeasureGroup {
8495
+ /** How many measures CMS defines for this group nationally. */
8496
+ measuresInGroup: number | null;
8497
+ /** How many of them THIS hospital actually reported — can be fewer than
8498
+ * `measuresInGroup`; the gap is itself informative. */
8499
+ measuresReported: number | null;
8500
+ /** Null for `patientExperience`/`timelyAndEffectiveCare` — CMS publishes no
8501
+ * national-average comparison for those two groups, only a rate. */
8502
+ better: number | null;
8503
+ noDifferent: number | null;
8504
+ worse: number | null;
8505
+ /** CMS's own footnote code(s), verbatim — occasionally more than one,
8506
+ * comma-separated. */
8507
+ footnote: string | null;
8508
+ }
8509
+
8510
+ interface medicareHospital {
8511
+ /** CMS Certification Number — the same id `findNursingHomes` and
8512
+ * `findDoctors`'s hospital affiliations key on. */
8513
+ ccn: string;
8514
+ name: string;
8515
+ address: string;
8516
+ city: string;
8517
+ state: string;
8518
+ zip: string;
8519
+ phone: string | null;
8520
+ county: string | null;
8521
+ /** Straight-line miles to the CENTROID OF THIS HOSPITAL'S OWN ZIP, not its
8522
+ * street address — this dataset carries no coordinates at all, the same gap
8523
+ * `findDoctors`'s clinician file has. Everyone sharing a ZIP shares a
8524
+ * distance, and a large rural ZIP carries real slack. */
8525
+ distanceMiles: number;
8526
+ /** e.g. "Acute Care Hospitals", "Critical Access Hospitals", "Psychiatric",
8527
+ * "Childrens", "Rural Emergency Hospital". Never "Long-term" — that type
8528
+ * belongs to `findRehabAndLongTermCareFacilities`. */
8529
+ hospitalType: string;
8530
+ ownershipType: string | null;
8531
+ emergencyServices: boolean;
8532
+ birthingFriendly: boolean;
8533
+ /** 1-5, or null when CMS publishes none — about 40% of hospitals nationally
8534
+ * carry no overall rating, mostly because they don't participate in the
8535
+ * reporting programs this rating requires, not because they scored poorly.
8536
+ * A null is NOT a bad rating; read it with `overallRatingFootnote`. */
8537
+ overallRating: number | null;
8538
+ /** Can be present even alongside a real star rating — always surface it. */
8539
+ overallRatingFootnote: string | null;
8540
+ /** The measure GROUPS behind the star, not just the rollup. */
8541
+ measureGroups: {
8542
+ mortality: medicareHospitalMeasureGroup;
8543
+ safety: medicareHospitalMeasureGroup;
8544
+ readmission: medicareHospitalMeasureGroup;
8545
+ patientExperience: medicareHospitalMeasureGroup;
8546
+ timelyAndEffectiveCare: medicareHospitalMeasureGroup;
8547
+ };
8548
+ }
8549
+
8550
+ interface medicareHospitalQuery {
8551
+ /** 5-digit US ZIP, placed via the Census Bureau's ZCTA centroid. Either this
8552
+ * or a `latitude`/`longitude` pair is required. */
8553
+ zip?: string;
8554
+ latitude?: number;
8555
+ longitude?: number;
8556
+ /** Straight-line miles, default 25, max 100. */
8557
+ radiusMiles?: number;
8558
+ /** Max hospitals returned, default 20. `matchesInSearchedZips` reports the
8559
+ * unlimited-by-`limit` count for the ZIPs actually searched. */
8560
+ limit?: number;
8561
+ }
8562
+
8563
+ interface medicareHospitalSearch {
8564
+ origin: {
8565
+ zip: string | null;
8566
+ latitude: number;
8567
+ longitude: number;
8568
+ source: "zcta-centroid" | "caller";
8569
+ };
8570
+ radiusMiles: number;
8571
+ /** ZIP Code Tabulation Areas the Census Bureau places inside the radius. */
8572
+ zipsInRadius: number;
8573
+ /** How many of them this call actually queried, nearest-batch-first. */
8574
+ zipsSearched: number;
8575
+ /** FALSE when the walk stopped before every ranked ZIP was queried —
8576
+ * normally because `limit` was already satisfied. Read it before describing
8577
+ * the result as "every hospital in the radius". */
8578
+ radiusFullyScanned: boolean;
8579
+ /** Hospitals found in the ZIPs actually searched, before `limit` — NOT a
8580
+ * radius-wide total when `radiusFullyScanned` is false. */
8581
+ matchesInSearchedZips: number;
8582
+ /** CMS's own publication date for this extract. Not "today" — CMS refreshes
8583
+ * quarterly. */
8584
+ dataAsOf: string | null;
8585
+ /** Nearest first. */
8586
+ hospitals: medicareHospital[];
8587
+ }
8588
+
6541
8589
  /** Whether a clinician takes Medicare's approved amount as payment in full.
6542
8590
  * NOT a boolean, and that is load-bearing: CMS's `ind_assgn` is only ever "Y"
6543
8591
  * or "M" — never "N" — so "does not take Medicare" is not a state this data can
@@ -6663,17 +8711,188 @@ interface medicareClinicianSearch {
6663
8711
  clinicians: medicareClinician[];
6664
8712
  }
6665
8713
 
8714
+ interface medicareMedigapDiscountRange {
8715
+ min: number;
8716
+ max: number;
8717
+ }
8718
+
8719
+ /** How the premium changes with the buyer's age. Attained-age premiums RISE with
8720
+ * age; issue-age and community-rated do not (community additionally moves with
8721
+ * inflation for everyone at once, regardless of age). "unknown" is a real,
8722
+ * intended value — see `ratingMethodRaw` on the policy it appears on — never a
8723
+ * parse failure. */
8724
+ type medicareMedigapRatingMethod = "attainedAge" | "issueAge" | "communityRated" | "unknown";
8725
+
8726
+ interface medicareMedigapPolicy {
8727
+ /** The insurer, exactly as CMS lists it. A parenthetical suffix like
8728
+ * "(Standard I)" is the SAME company selling this plan type under more than one
8729
+ * underwriting tier, each priced separately — do not dedupe by a company name
8730
+ * with the parenthetical stripped. */
8731
+ company: string;
8732
+ ratingMethod: medicareMedigapRatingMethod;
8733
+ /** CMS's raw rate-type string, kept ONLY when `ratingMethod` is "unknown" — a
8734
+ * value CMS started publishing after this mapping was written. Null whenever
8735
+ * `ratingMethod` is one of the three known values. */
8736
+ ratingMethodRaw: string | null;
8737
+ monthlyRateMin: number;
8738
+ monthlyRateMax: number;
8739
+ address: string;
8740
+ phoneNumber: string;
8741
+ website: string | null;
8742
+ /** A married/related-household discount, when this insurer offers one. Priced
8743
+ * SEPARATELY from `householdDiscountRoommate` — one existing does not imply
8744
+ * the other does. */
8745
+ householdDiscountStandard: medicareMedigapDiscountRange | null;
8746
+ /** An unrelated-adults-sharing-a-residence discount, priced separately from
8747
+ * `householdDiscountStandard` and frequently absent when that one is present. */
8748
+ householdDiscountRoommate: medicareMedigapDiscountRange | null;
8749
+ }
8750
+
8751
+ interface medicareMedigapPlanType {
8752
+ /** CMS's discriminator minus its "MEDIGAP_PLAN_TYPE_" prefix — "A", "HIGH_F", or
8753
+ * a Minnesota/Wisconsin waiver type ("MN_BASIC", "WI_HIGH_DEDUCTIBLE", …). Pass
8754
+ * this back as `searchMedigapPlans`'s `planType` argument to re-fetch just
8755
+ * this one type. */
8756
+ planType: string;
8757
+ /** The range Medicare.gov reports ACROSS every insurer selling this plan type
8758
+ * here, before picking one. Null means the `planType` filter named a type the
8759
+ * overview did not list as offered here — `policies` is then reliably empty
8760
+ * too, and null is the honest value rather than a fabricated 0. */
8761
+ monthlyRateMin: number | null;
8762
+ monthlyRateMax: number | null;
8763
+ householdDiscountStandard: medicareMedigapDiscountRange | null;
8764
+ householdDiscountRoommate: medicareMedigapDiscountRange | null;
8765
+ /** Every insurer selling this plan type here. */
8766
+ policies: medicareMedigapPolicy[];
8767
+ }
8768
+
8769
+ interface medicareMedigapQuery {
8770
+ /** 5-digit US ZIP. */
8771
+ zip: string;
8772
+ /** Omit to fetch every plan type the state offers. A result's own `planType`
8773
+ * (`'G'`, `'HIGH_F'`, or a waiver state's `'MN_BASIC'`) fetches just that one. */
8774
+ planType?: string;
8775
+ /** Only needed for the rare ZIP that crosses a STATE line — Medigap is priced
8776
+ * by state, so the wrong side returns a different market, not an error. */
8777
+ county?: string;
8778
+ }
8779
+
8780
+ interface medicareMedigapSearch {
8781
+ zip: string;
8782
+ /** Resolved from the ZIP, never taken from the caller — Medigap is priced by
8783
+ * state and a wrong one silently returns an empty result rather than an error. */
8784
+ state: string;
8785
+ county: medicareCounty;
8786
+ countiesConsidered: medicareCounty[];
8787
+ /** Empty is a real, honest answer for a state/ZIP CMS reports no Medigap market
8788
+ * data for — never a sign this call failed. */
8789
+ planTypes: medicareMedigapPlanType[];
8790
+ }
8791
+
8792
+ interface medicarePlanDetail {
8793
+ /** CMS's contract-plan-segment triple joined by '-', e.g. "S5884-103-0". */
8794
+ id: string;
8795
+ name: string;
8796
+ nameSpanish: string | null;
8797
+ organization: string;
8798
+ contractId: string;
8799
+ planId: string;
8800
+ segmentId: string;
8801
+ year: number;
8802
+ /** CMS's own category string: "Medicare Advantage" / "Medicare Advantage with
8803
+ * Prescription Drug Coverage" / "Medicare Prescription Drug Plan" /
8804
+ * "Special Needs Plan". */
8805
+ category: string;
8806
+ planType: "PLAN_TYPE_PDP" | "PLAN_TYPE_MA" | "PLAN_TYPE_MAPD" | "PLAN_TYPE_SNP";
8807
+ carrierUrl: string | null;
8808
+ contractYear: string;
8809
+ partcPremium: number;
8810
+ partdPremium: number;
8811
+ partbPremiumReduction: number;
8812
+ /** Annual drug deductible in dollars; 0 means none. PDP only. */
8813
+ drugPlanDeductible: number | null;
8814
+ /** Annual in-network OOP maximum, verbatim. Empty when not published. */
8815
+ maximumOopc: string;
8816
+ /** Per-visit cost strings, verbatim. Empty when CMS publishes no figure —
8817
+ * "$0" (a real benefit) and "" (not published) are deliberately distinct. */
8818
+ primaryDoctorVisitCost: string;
8819
+ specialistDoctorVisitCost: string;
8820
+ emergencyCareCost: string;
8821
+ /** MA/MAPD only — null on PDP, which has no primary/specialist visits. */
8822
+ primaryDoctorCostSharing: string | null;
8823
+ specialistDoctorCostSharing: string | null;
8824
+ /** 1-5 in half steps, or null when CMS publishes none (with starRatingNote
8825
+ * naming the reason — e.g. "too new to be rated"). */
8826
+ starRating: number | null;
8827
+ starRatingNote: string | null;
8828
+ lowPerforming: boolean;
8829
+ highPerforming: boolean;
8830
+ /** All false on a PDP — supplemental benefits live on the Part C side. */
8831
+ supplementalBenefits: {
8832
+ silverSneakers: boolean;
8833
+ transportation: boolean;
8834
+ telehealth: boolean;
8835
+ otcDrugs: boolean;
8836
+ homeSafetyDevices: boolean;
8837
+ inHomeSupport: boolean;
8838
+ supportForCaregivers: boolean;
8839
+ healthEducation: boolean;
8840
+ counselingServices: boolean;
8841
+ emergencyResponseDevice: boolean;
8842
+ worldwideEmergency: boolean;
8843
+ };
8844
+ providerCoverage: {
8845
+ /** False on plans with no network (e.g. PFFS); providers is then reliably empty. */
8846
+ hasProviderCoverageData: boolean;
8847
+ providerCount: number;
8848
+ };
8849
+ /** Extra Help / Low-Income Subsidy dollar amounts at each LIS band. */
8850
+ lis: {
8851
+ level100: number;
8852
+ level75: number;
8853
+ level50: number;
8854
+ level25: number;
8855
+ };
8856
+ snpType: string;
8857
+ dsnpIntegrationLevel: string;
8858
+ /** When CMS marks the plan as terminated for the search year. */
8859
+ terminatedWithoutCrosswalk: string | null;
8860
+ /** Empty when the plan is published in full; the SPA hides fields CMS marks
8861
+ * for redaction and the same fields arrive here. */
8862
+ redactions: string[];
8863
+ }
8864
+
8865
+ interface medicareGetPlanQuery {
8866
+ /** "pdp" | "ma" | "mapd" | "snp" — the caller's MUST match the row they
8867
+ * have in hand. The same (contractId, planId, segmentId) triple does NOT
8868
+ * exist across plan types by design. */
8869
+ planType: "pdp" | "ma" | "mapd" | "snp";
8870
+ /** CMS's contract id (e.g. "S5884" for Part D, "H1234" for Part C). */
8871
+ contractId: string;
8872
+ planId: string;
8873
+ segmentId: string;
8874
+ /** Defaults to the current calendar year — CMS renumbers every January. */
8875
+ year?: number;
8876
+ /** 5-digit US ZIP. Required because the API is keyed on (fips, zip). */
8877
+ zip: string;
8878
+ /** Needed only for the rare ZIP that crosses a state line. */
8879
+ county?: string;
8880
+ }
8881
+
6666
8882
  /**
6667
8883
  * The US government's own Medicare site — Medicare Advantage, Part D and Medigap plan search
6668
8884
  * with real drug-cost estimates, the Care Compare directory of doctors, hospitals, nursing
6669
8885
  * homes, home health, hospice and dialysis providers with CMS quality ratings, the A-to-Z
6670
- * coverage database, and what Medicare itself costs this year. Part D drug-plan search, the
6671
- * doctor-and-clinician directory (specialties, group practice, hospital affiliations by name,
6672
- * and whether they accept Medicare assignment), the nursing-home directory with CMS's full
6673
- * Five-Star record (component ratings, staffing hours, fines, payment denials and Special
6674
- * Focus status), and the Medicare cost reference (premiums, deductibles, coinsurance tiers and
6675
- * the Part B/Part D income brackets) are callable now; the other fifteen declared functions
6676
- * are still stubs.
8886
+ * coverage database, and what Medicare itself costs this year. Part D drug-plan search,
8887
+ * Medigap plan search (every insurer selling each plan type, with its rating method and any
8888
+ * household discount), the doctor-and-clinician directory (specialties, group practice,
8889
+ * hospital affiliations by name, and whether they accept Medicare assignment), the
8890
+ * nursing-home directory with CMS's full Five-Star record (component ratings, staffing hours,
8891
+ * fines, payment denials and Special Focus status), the hospital directory with CMS's overall
8892
+ * rating AND the five measure groups behind it (mortality, safety, readmission, patient
8893
+ * experience, timely and effective care), and the Medicare cost reference (premiums,
8894
+ * deductibles, coinsurance tiers and the Part B/Part D income brackets) are callable now; the
8895
+ * other thirteen declared functions are still stubs.
6677
8896
  */
6678
8897
  interface Unit {
6679
8898
  // UNTYPED, DELIBERATELY OMITTED — `searchDrugPlans({ zip, year, county, limit })` declares no types for
@@ -6730,6 +8949,63 @@ interface medicareClinicianSearch {
6730
8949
  * `dataAsOf` carries CMS's own publication date — this is a periodic extract, not a live read.
6731
8950
  */
6732
8951
  findDoctors(query: medicareClinicianQuery): Promise<medicareClinicianSearch>;
8952
+
8953
+ /**
8954
+ * The Medigap (Medicare Supplement) plan types sold in a ZIP's state, each with the insurers
8955
+ * selling it, their premium range, their RATING METHOD (attained-age — rises with age;
8956
+ * issue-age or community-rated — does not) and any household discount. `zip` is a 5-digit US
8957
+ * ZIP; `county` disambiguates the rare ZIP that crosses a STATE line (Medigap is priced by
8958
+ * state, not region), the same shape as `searchDrugPlans`'s own `county`. Omit `planType` to
8959
+ * fetch every plan type the state offers (Minnesota and Wisconsin price under their own
8960
+ * federal waiver — `MN_BASIC`, `WI_HIGH_DEDUCTIBLE`, etc. — rather than the national letters,
8961
+ * and this function returns exactly what the state offers); pass a result's own `planType`
8962
+ * (e.g. `'G'`, `'HIGH_F'`) to fetch just that one, one call instead of every letter's. NOTE
8963
+ * the field the manifest exists for: two policies can share the same letter (which by law
8964
+ * means identical coverage) and today's premium, and still diverge by hundreds of dollars a
8965
+ * year within a decade purely because one is `attainedAge` and the other is not — never rank
8966
+ * or recommend a Medigap policy on premium alone without surfacing `ratingMethod`.
8967
+ */
8968
+ searchMedigapPlans(arg0: medicareMedigapQuery): Promise<medicareMedigapSearch>;
8969
+
8970
+ /**
8971
+ * The Medicare-registered hospitals near a place, nearest first, each with CMS's overall star
8972
+ * rating AND the five measure groups behind it (mortality, safety, readmission, patient
8973
+ * experience, timely and effective care — each with how many measures the hospital reported
8974
+ * and, for the first three, how many beat/matched/trailed the national average), the hospital
8975
+ * type (acute care, critical access, psychiatric, children's, rural emergency, VA, DoD — never
8976
+ * the long-term/rehab types `findRehabAndLongTermCareFacilities` covers), ownership, whether
8977
+ * it offers emergency services, and CMS's birthing-friendly designation. Pass a 5-digit `zip`
8978
+ * (placed via the Census Bureau's ZCTA centroid) or a `latitude`/`longitude` pair;
8979
+ * `radiusMiles` defaults to 25 (max 100) and `limit` to 20. NOTE the two things that make this
8980
+ * answer honest. (1) `overallRating` is null for roughly 40% of hospitals nationally — mostly
8981
+ * small or non-reporting facilities, not poor performers — and is never the whole story: read
8982
+ * it alongside `measureGroups`, since a hospital can report zero of a group's measures and
8983
+ * still carry an overall star from the groups it does report. (2) `distanceMiles` is to the
8984
+ * centroid of the hospital's own ZIP, not its street address — this dataset carries no
8985
+ * coordinates — so `radiusFullyScanned` and `matchesInSearchedZips` carry the same
8986
+ * walked-radius honesty split `findDoctors` uses, for the identical reason.
8987
+ */
8988
+ findHospitals(query: medicareHospitalQuery): Promise<medicareHospitalSearch>;
8989
+
8990
+ /**
8991
+ * The full detail of one Part D / MA / MAPD / SNP plan, identified by its CMS
8992
+ * contract-plan-segment triple (e.g. `S5884-103-0` for Part D, `Hxxxx-yyyy-0` for Part C).
8993
+ * Returns the per-visit and per-event cost strings verbatim ('$0', '$20 copay', '20%', or
8994
+ * empty when CMS publishes none), the annual in-network OOP maximum, the supplemental benefits
8995
+ * (dental, fitness, telehealth, OTC drugs, transportation, worldwide emergency — PDPs set them
8996
+ * all to false because the supplemental benefit half is a Part C thing), the CMS star rating
8997
+ * with the explicit reason when none is published (e.g. 'too new to be rated' rather than
8998
+ * rendering a null as a middling rating), the Extra Help / LIS dollar amounts at each band,
8999
+ * the provider-coverage summary, and the carrier's own CMS-published page. `planType` must be
9000
+ * the same discriminator `searchDrugPlans` / a future health-plan search used to find the
9001
+ * triple — the same `(contractId, planId, segmentId)` does NOT exist across plan types by
9002
+ * design, so the wrong one throws. `zip` is required because the API is keyed on (fips, zip),
9003
+ * not on the plan id alone — without it there is no region to ask about. `year` defaults to
9004
+ * the current calendar year. NOTE: the per-visit cost strings are verbatim and the difference
9005
+ * between '$0' (a real zero-cost benefit) and '' (not published) is load-bearing — never
9006
+ * coerce an empty string to 0.
9007
+ */
9008
+ getPlan(arg0: medicareGetPlanQuery): Promise<medicarePlanDetail>;
6733
9009
  }
6734
9010
  }
6735
9011
 
@@ -7598,6 +9874,34 @@ interface ottoProduct {
7598
9874
  sizes: { label: string; selected: boolean; available: boolean }[];
7599
9875
  colors: { label: string; selected: boolean; available: boolean; image: string | null }[];
7600
9876
  }
9877
+ interface ottoSearchPrice {
9878
+ currentAmount: number;
9879
+ currentDisplay: string;
9880
+ suggestedRetailAmount: number | null;
9881
+ suggestedRetailDisplay: string | null;
9882
+ comparativeAmount: number | null;
9883
+ comparativeDisplay: string | null;
9884
+ onSale: boolean;
9885
+ isStartingPrice: boolean;
9886
+ }
9887
+ interface ottoSearchResult {
9888
+ productId: string;
9889
+ variationId: string;
9890
+ articleNumber: string;
9891
+ url: string;
9892
+ name: string;
9893
+ brand: string;
9894
+ price: ottoSearchPrice;
9895
+ availability: { state: string; detail: string };
9896
+ thumbnail: string | null;
9897
+ rating: { value: number; count: number } | null;
9898
+ matchType: string;
9899
+ totalCount: number;
9900
+ }
9901
+ interface ottoSearchQuery {
9902
+ query: string;
9903
+ limit?: number;
9904
+ }
7601
9905
 
7602
9906
  /** German online marketplace — fashion, furniture, electronics and more. */
7603
9907
  interface Unit {
@@ -7609,6 +9913,99 @@ interface ottoProduct {
7609
9913
  * retired listing).
7610
9914
  */
7611
9915
  getProduct(url: string): Promise<ottoProduct>;
9916
+
9917
+ /**
9918
+ * Searches OTTO's catalog for a free-text keyword the way the site's own search bar does,
9919
+ * across its whole marketplace (OTTO's own catalog and third-party sellers) and returns
9920
+ * matching rows: price (current + UVP + the site's own comparison price when it publishes
9921
+ * one), availability, brand, rating and a thumbnail. `matchType` on each row is the site's own
9922
+ * retrieval-type token ("hybrid" for a real keyword match, "semantic" when nothing matched
9923
+ * literally and the site is showing similar items instead — OTTO's engine almost never returns
9924
+ * a hard empty result). Returns one page (up to ~150 rows); `totalCount` on each row is the
9925
+ * site's own total match count across every page. `url` feeds `getProduct` directly for OTTO's
9926
+ * own catalog rows; a third-party marketplace row's URL does not match `getProduct`'s current
9927
+ * `-C<id>/` pattern.
9928
+ */
9929
+ search(query: ottoSearchQuery): Promise<ottoSearchResult[]>;
9930
+ }
9931
+ }
9932
+
9933
+ declare namespace BowmarkProvider_paypal {
9934
+ // ── PayPal — the unit's own declarations, verbatim ──
9935
+ interface PaypalEstimateFeeArgs {
9936
+ amount: number; // > 0, in `currency`
9937
+ currency: string; // ISO 4217, e.g. "USD"
9938
+ crossBorder: boolean; // sender and recipient in different countries
9939
+ fundingSource: "balance" | "bank" | "card" | "amexSend";
9940
+ }
9941
+ interface PaypalFeeCitation {
9942
+ documentId: string; // the CMS fee-table id this figure came from, e.g. "FEETB20"
9943
+ feeDataKey: string; // the exact published value used, e.g. "2.90%"
9944
+ internalName: string;
9945
+ }
9946
+ interface PaypalFeeEstimate {
9947
+ amount: number;
9948
+ currency: string;
9949
+ crossBorder: boolean;
9950
+ fundingSource: "balance" | "bank" | "card" | "amexSend";
9951
+ fee: number;
9952
+ net: number; // amount - fee
9953
+ citations: PaypalFeeCitation[];
9954
+ }
9955
+ interface PaypalGetFeesArgs {
9956
+ audience?: "consumer"; // defaults to "consumer"; merchant is a separate, unverified page
9957
+ country?: string; // ISO 3166-1 alpha-2, defaults to "us"; only "us" is verified end-to-end
9958
+ }
9959
+ interface PaypalFeeToken {
9960
+ feeDataKey: string; // the exact published value, e.g. "2.90%" or "0.30 USD"
9961
+ internalName: string;
9962
+ percent: number | null; // 0.029 when "2.90%", else null
9963
+ amount: { amount: number; currency: string } | null; // when "0.30 USD", else null
9964
+ }
9965
+ interface PaypalFeeRow {
9966
+ labels: string[]; // plain-text label cells, in cell order
9967
+ tokens: PaypalFeeToken[]; // every published fee token on the row, across all columns
9968
+ cells: string[]; // plain-text rendering of each cell, in cell order
9969
+ noFee: boolean; // true iff the row carries no fee token (PayPal's "No fee" rows)
9970
+ citations: PaypalFeeCitation[];
9971
+ }
9972
+ interface PaypalFeeTable {
9973
+ documentId: string; // the CMS fee-table id, e.g. "FEETB20"
9974
+ caption: string; // PayPal's own caption, e.g. "Sending domestic personal transactions"
9975
+ rows: PaypalFeeRow[];
9976
+ }
9977
+ interface PaypalFeeSchedule {
9978
+ audience: "consumer";
9979
+ country: string; // lowercased to match PayPal's URL path, e.g. "us"
9980
+ sourceUrl: string;
9981
+ tables: PaypalFeeTable[];
9982
+ }
9983
+
9984
+ /**
9985
+ * PayPal's public, signed-out surfaces: the published consumer and merchant fee schedules, the
9986
+ * fee on one concrete personal (friends-and-family) transaction, currency-conversion quotes
9987
+ * and the spread PayPal adds, Pay Later instalment plans, PayPal.Me handle lookup, Help Center
9988
+ * search and articles, the binding policy documents, PayPal Shopping cashback offers, crypto
9989
+ * prices, and invoice payer-view reads. Two functions callable today — estimateFee, getFees.
9990
+ */
9991
+ interface Unit {
9992
+ /**
9993
+ * Computes what PayPal charges to send a PERSONAL (friends-and-family) payment — domestic or
9994
+ * cross-border, by funding source — off PayPal's own published fee schedule, e.g.
9995
+ * estimateFee({ amount: 100, currency: "USD", crossBorder: false, fundingSource: "card" }) ->
9996
+ * { fee: 3.2, net: 96.8, citations: [...] }. Does not (yet) cover goods-and-services/merchant
9997
+ * transactions, a separate page nobody has walked.
9998
+ */
9999
+ estimateFee(args: PaypalEstimateFeeArgs): Promise<PaypalFeeEstimate>;
10000
+
10001
+ /**
10002
+ * Reads PayPal's published fee schedule for one audience / country pair and returns every fee
10003
+ * table on the page — every row, every published feeDataKey, with documentId-level citations —
10004
+ * so a caller can inspect the schedule itself rather than asking about one amount. Currently
10005
+ * consumer / us only; merchant is on a separate unverified page and other countries have not
10006
+ * been fetched.
10007
+ */
10008
+ getFees(args: PaypalGetFeesArgs): Promise<PaypalFeeSchedule>;
7612
10009
  }
7613
10010
  }
7614
10011
 
@@ -7751,15 +10148,141 @@ interface PizzahutPricedLineItem {
7751
10148
  specialInstructions: string | null;
7752
10149
  }
7753
10150
 
10151
+ // ── getMenuItem ───────────────────────────────────────────────────────────
10152
+ interface PizzahutMenuItem {
10153
+ storeNumber: string;
10154
+ productCode: string; // pass this + a variantCode below to priceOrder
10155
+ name: string | null;
10156
+ description: string | null;
10157
+ category: string | null;
10158
+ currency: string;
10159
+ variants: PizzahutMenuItemVariant[];
10160
+ }
10161
+
10162
+ interface PizzahutMenuItemVariant {
10163
+ variantCode: string; // the priced configuration — size and crust are IN this code
10164
+ name: string | null;
10165
+ priceCents: number; // this variant's OWN starting price
10166
+ attributes: string[]; // e.g. ["Original Pan® Pizza", "Personal Pan"]
10167
+ slots: PizzahutMenuItemSlot[];
10168
+ servingSize: { quantity: number; unit: string } | null;
10169
+ allergens: { allergen: string; presence: string }[];
10170
+ }
10171
+
10172
+ interface PizzahutMenuItemSlot {
10173
+ slotCode: string; // e.g. "slot_pizza_cheese", "slot_toppings"
10174
+ name: string | null;
10175
+ minAllowedSelections: number;
10176
+ maxAllowedSelections: number | null; // null = no cap the site publishes
10177
+ modifiers: PizzahutMenuItemModifier[];
10178
+ }
10179
+
10180
+ interface PizzahutMenuItemModifier {
10181
+ modifierCode: string;
10182
+ name: string | null;
10183
+ weights: PizzahutMenuItemWeight[]; // portion/intensity choices for this modifier
10184
+ }
10185
+
10186
+ interface PizzahutMenuItemWeight {
10187
+ modifierWeightCode: string; // pass slotCode + modifierCode + this to priceOrder's modifiers
10188
+ name: string | null; // e.g. "Light", "Regular", "Extra"
10189
+ priceCents: number; // what THIS option costs on THIS variant — varies by size
10190
+ }
10191
+
10192
+ // ── getMenu ───────────────────────────────────────────────────────────────
10193
+ interface PizzahutMenuArgs {
10194
+ storeNumber: string;
10195
+ }
10196
+
10197
+ interface PizzahutMenuVariant {
10198
+ variantCode: string;
10199
+ name: string | null;
10200
+ priceCents: number;
10201
+ attributes: string[]; // e.g. ["Original Pan® Pizza", "Personal Pan"]
10202
+ }
10203
+
10204
+ interface PizzahutMenuListItem {
10205
+ productCode: string;
10206
+ name: string | null;
10207
+ description: string | null;
10208
+ categoryCode: string;
10209
+ categoryName: string;
10210
+ currency: string;
10211
+ variants: PizzahutMenuVariant[];
10212
+ }
10213
+
10214
+ interface PizzahutMenuCategory {
10215
+ categoryCode: string;
10216
+ categoryName: string;
10217
+ items: PizzahutMenuListItem[];
10218
+ }
10219
+
10220
+ interface PizzahutMenu {
10221
+ storeNumber: string;
10222
+ currency: string;
10223
+ categories: PizzahutMenuCategory[];
10224
+ }
10225
+
10226
+ // ── getDeals ──────────────────────────────────────────────────────────────
10227
+ // Mirrors the public types declared at the top of this file (PizzahutDeals,
10228
+ // PizzahutDeal, PizzahutDealImage, PizzahutDealScope) — copied here so the
10229
+ // rendered get_library blurb and the catalog signature are types the
10230
+ // gateway can resolve. The exported shapes are the source of truth.
10231
+ type PizzahutDealScopeForRender = "all" | { storeNumbers: string[] };
10232
+
10233
+ interface PizzahutDealImageForRender {
10234
+ url: string;
10235
+ title: string | null;
10236
+ }
10237
+
10238
+ interface PizzahutDealForRender {
10239
+ position: number | null;
10240
+ code: string;
10241
+ name: string;
10242
+ description: string | null;
10243
+ legalText: string | null;
10244
+ appImage: PizzahutDealImageForRender | null;
10245
+ webImage: PizzahutDealImageForRender | null;
10246
+ }
10247
+
10248
+ interface PizzahutDealsForRender {
10249
+ storeNumber: string;
10250
+ deals: PizzahutDealForRender[];
10251
+ sources: { name: string; scope: PizzahutDealScopeForRender }[];
10252
+ }
10253
+
7754
10254
  /**
7755
10255
  * Pizza Hut's US ordering site. `findStores` returns the stores serving any US address or ZIP,
7756
10256
  * nearest first, with each one's number, hours, distance, phone and the terms of the carryout
7757
- * and delivery it offers. `priceOrder` then prices a basket at one of those stores WITHOUT
7758
- * placing it line items, subtotal, sales tax, delivery fee and the real total Pizza Hut
7759
- * would charge, for carryout or to a delivery address, anonymously. Reading the store menu and
7760
- * the current deals are declared and still stubs.
10257
+ * and delivery it offers. `getMenu` reads a store's whole menu every category, every item,
10258
+ * and every variant's price at THAT store. `getMenuItem` reads one item's full store-level
10259
+ * configuration by name every size/crust, and every optional topping/sauce/cheese slot with
10260
+ * what each choice costs on THAT variant. `getDeals` reads the deals and bundle offers Pizza
10261
+ * Hut is running AT ONE STORE right now, filtered to what is actually redeemable there.
10262
+ * `priceOrder` then prices a basket at one of those stores WITHOUT placing it — line items,
10263
+ * subtotal, sales tax, delivery fee and the real total Pizza Hut would charge, for carryout or
10264
+ * to a delivery address, anonymously.
7761
10265
  */
7762
10266
  interface Unit {
10267
+ /**
10268
+ * Reads a store's whole menu — every category (pizza, wings, pasta, sides, desserts, drinks,
10269
+ * dips, melts, …), every item in each, and each item's variants with their price AT THAT
10270
+ * STORE, all in cents. `storeNumber` comes from `findStores` and is required because Pizza
10271
+ * Hut's prices are store-level — measured 2026-08-07, the same Pepperoni Pizza was $5.50 /
10272
+ * $20.08 at store 026196 (North Hollywood CA) and $6.69 / $12.99 at store 027278 (Plano TX),
10273
+ * all 11 variants differing between the two, so omitting the store would silently return
10274
+ * whatever default the site happens to serve. One GraphQL read returns the whole menu in a
10275
+ * single ~200 KB response (measured 2026-08-07 on store 026196: 20 categories, 138 items, 731
10276
+ * variants, 731/731 with prices), so no fan-out is needed. Bundle items and bare-variant
10277
+ * category items are out of scope — they are not configurable products — same exclusion as
10278
+ * `flattenProductCatalog`. A variant is the priced configuration (size + crust already in
10279
+ * `variantCode`), so a `variantCode` read here plus a `slotCode` / `modifierCode` /
10280
+ * `modifierWeightCode` triple from `getMenuItem` is everything `priceOrder` needs to price a
10281
+ * configured basket. Wholly anonymous: no account, no session, no identity of any kind, same
10282
+ * guest-token read `priceOrder` and `getMenuItem` use.
10283
+ */
10284
+ getMenu(args: { storeNumber: string }): Promise<PizzahutMenu>;
10285
+
7763
10286
  /**
7764
10287
  * Finds the Pizza Hut stores that serve a US location — each store's number, street address,
7765
10288
  * phone, opening hours, straight-line distance, online status, and the terms of every
@@ -7806,6 +10329,47 @@ interface PizzahutPricedLineItem {
7806
10329
  * cart so totals never accumulate across calls.
7807
10330
  */
7808
10331
  priceOrder(order: { storeNumber: string; items: { productCode: string; variantCode: string; quantity?: number; modifiers?: { slotCode: string; modifierCode: string; modifierWeightCode: string }[]; specialInstructions?: string }[]; fulfillment?: "carryout" | "delivery"; deliveryAddress?: { address: string; address2?: string; city: string; state: string; zip: string; deliveryInstructions?: string; phone?: string }; requestedTime?: string; promoCode?: string }): Promise<PizzahutPricedOrder>;
10332
+
10333
+ /**
10334
+ * Reads one menu item in full for a store — every size/crust it comes in, each one's own
10335
+ * starting price, and every optional slot (sauce, cheese, toppings, seasoning, cut) with what
10336
+ * each choice costs ON THAT VARIANT, plus nutrition serving size and allergens where the site
10337
+ * publishes them. `storeNumber` comes from `findStores`. `getMenu` (the sibling function that
10338
+ * would normally hand out a `productCode` to browse by) is still a stub, so `item` is a NAME
10339
+ * instead — "Pepperoni Pizza" — matched first as an exact `productCode` if you already have
10340
+ * one, then an exact case-insensitive name, then a substring; `category` (a code like "pizza"
10341
+ * or a display name like "Pizza") narrows the search when a name alone is ambiguous. Zero
10342
+ * matches or more than one both throw as caller-fixable, the second one listing every
10343
+ * candidate's name, category and `productCode` so a retry can pick one exactly.
10344
+ * **Configuration prices are per VARIANT, not per product** — measured 2026-08-06 on the same
10345
+ * Pepperoni Pizza, Extra Cheese is +$0.50 on a Personal Pan, +$2.89 on a Medium, +$3.39 on a
10346
+ * Large, so this returns each variant's own priced slot tree rather than one flat add-on price
10347
+ * for the whole item. A `variantCode` plus a `slotCode`/`modifierCode`/`modifierWeightCode`
10348
+ * triple read here is exactly what `priceOrder` takes to price a configured basket. Wholly
10349
+ * anonymous, same guest-token read `priceOrder` uses — no account, no session, nothing
10350
+ * identifying.
10351
+ */
10352
+ getMenuItem(args: { storeNumber: string; item: string; category?: string }): Promise<PizzahutMenuItem>;
10353
+
10354
+ /**
10355
+ * Reads the deals, coupons and bundle offers Pizza Hut is running AT ONE STORE right now —
10356
+ * every deal that applies there, its bundle code, display name, description and legal text, in
10357
+ * the order the site puts them on the deals page. `storeNumber` comes from `findStores` and is
10358
+ * REQUIRED: Pizza Hut runs national deals AND franchise-local ones, and a deal listed but not
10359
+ * available at the caller's store is the honest-vs-misleading line — the function filters by
10360
+ * `MenuDealPageSortOverride.storesList` (a comma-separated list of stores, or the literal
10361
+ * "ALL") so a caller gets only what is actually redeemable where they asked. The store's deals
10362
+ * page lives on Contentful (NOT the Yum storefront GraphQL the rest of the provider hits): the
10363
+ * deals page's own `__NEXT_DATA__.runtimeConfig` publishes `CONTENTFUL_SPACE_ID` +
10364
+ * `CONTENTFUL_ACCESS_TOKEN` + `CONTENTFUL_ENVIRONMENT` + `CONTENTFUL_BASE_URL`, and this reads
10365
+ * them out of the page rather than asking the caller for them. The bootstrap throws on a
10366
+ * missing payload the way `parsePhdConfig` does — a 200 without the runtimeConfig is the
10367
+ * Canadian site, and serving a caller the wrong country’s deals is worse than no answer. The
10368
+ * list is sorted by `dealPagePosition` (1-based, lower = higher up); positions the site leaves
10369
+ * null fall back to a stable code-order tiebreak rather than being treated as "first". Wholly
10370
+ * anonymous, one Contentful read per call.
10371
+ */
10372
+ getDeals(args: { storeNumber: string }): Promise<PizzahutDealsForRender>;
7809
10373
  }
7810
10374
  }
7811
10375
 
@@ -9029,6 +11593,60 @@ interface SearsSearchQuery {
9029
11593
  zipCode?: string;
9030
11594
  limit?: number;
9031
11595
  }
11596
+ interface SearsProductPrice {
11597
+ currentAmount: number;
11598
+ currentDisplay: string;
11599
+ regularAmount: number | null;
11600
+ regularDisplay: string | null;
11601
+ onSale: boolean;
11602
+ }
11603
+ interface SearsProductSpecification {
11604
+ label: string;
11605
+ attributes: string[];
11606
+ }
11607
+ interface SearsProduct {
11608
+ productId: string;
11609
+ url: string;
11610
+ name: string;
11611
+ brand: string | null;
11612
+ price: SearsProductPrice;
11613
+ inStock: boolean;
11614
+ images: string[];
11615
+ description: string | null;
11616
+ specifications: SearsProductSpecification[];
11617
+ }
11618
+ interface SearsShippingAvailability {
11619
+ available: boolean;
11620
+ availableQuantity: number | null;
11621
+ ffmType: string | null;
11622
+ shipModes: string[];
11623
+ dcUnitId: string | null;
11624
+ promiseDate: string | null;
11625
+ autoUpgrade: boolean;
11626
+ freeShipping: boolean;
11627
+ freeEligible: boolean;
11628
+ freeQualified: boolean;
11629
+ }
11630
+ interface SearsStockStore {
11631
+ unitId: string | null;
11632
+ storeName: string | null;
11633
+ storeBrand: string | null;
11634
+ storeAddress: string | null;
11635
+ promiseDate: string | null;
11636
+ ffmType: string | null;
11637
+ }
11638
+ interface SearsPickupAvailability {
11639
+ available: boolean;
11640
+ stores: SearsStockStore[];
11641
+ message: string | null;
11642
+ }
11643
+ interface SearsStock {
11644
+ productId: string;
11645
+ zipCode: string;
11646
+ quantity: number;
11647
+ shipping: SearsShippingAvailability | null;
11648
+ pickup: SearsPickupAvailability;
11649
+ }
9032
11650
 
9033
11651
  /** Sears' own storefront — product search, product detail, fulfillment/stock and store locator. */
9034
11652
  interface Unit {
@@ -9042,6 +11660,28 @@ interface SearsSearchQuery {
9042
11660
  * further paging parameter this function reaches.
9043
11661
  */
9044
11662
  search(query: SearsSearchQuery): Promise<SearsSearchResult[]>;
11663
+
11664
+ /**
11665
+ * Reads one Sears product in full: name, brand, current and regular price, whether it's in
11666
+ * stock, every image and the site's own full labelled spec sheet (dimensions, features,
11667
+ * overview). Takes the product id or full URL from Sears's own "/p-<id>" pattern — `search`
11668
+ * returns both, so the ordinary path is a `search` row's `id` or `url`. `zipCode` narrows
11669
+ * price/availability the way the site's own zip cookie does; omit it for the site's own
11670
+ * default (New York, 10101). THROWS on an id the site does not recognise.
11671
+ */
11672
+ getProduct(idOrUrl: string, opts?: { zipCode?: string }): Promise<SearsProduct>;
11673
+
11674
+ /**
11675
+ * Answers whether a Sears product is buyable right now — for shipping/delivery AND for
11676
+ * in-store/curbside pickup — the way the product page's own fulfillment panel does, in one
11677
+ * call. `shipping` carries the site's own available quantity, ship modes and promise date.
11678
+ * `pickup.stores` is the stores the site found able to fulfil it near `zipCode` — routinely
11679
+ * empty (Sears' physical footprint has shrunk sharply), which is a real, common answer, not an
11680
+ * error; `pickup.message` carries the site's own explanation when it is. `zipCode` narrows the
11681
+ * search the way the site's own zip cookie does; omit it for the site's own default (New York,
11682
+ * 10101). Takes the product id or URL from `search`/`getProduct` — same as `getProduct`.
11683
+ */
11684
+ checkStock(idOrUrl: string, opts?: { zipCode?: string; quantity?: number }): Promise<SearsStock>;
9045
11685
  }
9046
11686
  }
9047
11687
 
@@ -9636,6 +12276,198 @@ interface StatefarmBusinessCoverage {
9636
12276
  }
9637
12277
  }
9638
12278
 
12279
+ declare namespace BowmarkProvider_stickergiant {
12280
+ // ── StickerGiant — the unit's own declarations, verbatim ──
12281
+ // StickerGiant's OWN shape — not a capability contract.
12282
+
12283
+ interface StickergiantListArgs {
12284
+ format?: string; // optional material code filter, e.g. "WHP"
12285
+ }
12286
+
12287
+ interface StickergiantProduct {
12288
+ url: string; // The configurator's own entry URL — durable key
12289
+ name: string; // "Individual Stickers (Die Cut) - White"
12290
+ sku: string; // The site's own material code, e.g. "WHP"
12291
+ priceUsd: string; // "$37.90" — per-100 stickers starting price
12292
+ priceValue: number; // Same number unformatted
12293
+ priceCurrency: string; // "USD"
12294
+ availability: string; // Schema.org URL, e.g. "https://schema.org/InStock"
12295
+ imageUrl: string;
12296
+ }
12297
+
12298
+ interface StickergiantBuild {
12299
+ widthInches: number; // required, from SITE_SIZES
12300
+ heightInches: number; // required, from SITE_SIZES
12301
+ lamination: "OGL" | "MAL"; // required — Outdoor Gloss / Matte
12302
+ quantity?: number; // optional — omit for the full 15-tier ladder back
12303
+ }
12304
+
12305
+ interface StickergiantQuantityPrice {
12306
+ quantity: number;
12307
+ price: number; // the pricing engine's own total (not the rendered 'Total')
12308
+ pricePerUnit: number;
12309
+ }
12310
+
12311
+ interface StickergiantPriceResult {
12312
+ selections: { // echoes back what the engine actually priced
12313
+ widthInches: number;
12314
+ heightInches: number;
12315
+ lamination: "OGL" | "MAL";
12316
+ product: string; // "DCU" — the only product the API honors
12317
+ material: string; // "WHP" — the only material the API honors
12318
+ };
12319
+ selectedQuantity?: StickergiantQuantityPrice; // when caller passed quantity
12320
+ quantityPrices: StickergiantQuantityPrice[]; // always: the full 15-tier ladder
12321
+ }
12322
+
12323
+ /**
12324
+ * StickerGiant's sticker configurator and its published catalog — every sticker SKU on
12325
+ * /custom-stickers with its real starting price, material code and configurator entry URL.
12326
+ */
12327
+ interface Unit {
12328
+ /**
12329
+ * Lists every sticker SKU the /custom-stickers page publishes — name, the configurator's
12330
+ * material URL, the site's own material code (sku), the per-100-stickers starting price the
12331
+ * page carries in its schema.org Product block, the price currency, availability, and the
12332
+ * page's hero image. Optional { format } restricts to one material code (e.g. 'WHP' for Die
12333
+ * Cut White). THROWS rather than returning [] when the page carries no schema.org Product
12334
+ * blocks or when the format filter names an unknown code — both are honest failure modes and
12335
+ * an empty array would read as 'StickerGiant sells no stickers', which is the
12336
+ * confident-wrong-answer failure this provider exists to avoid.
12337
+ */
12338
+ listStickerProducts(args?: StickergiantListArgs): Promise<StickergiantProduct[]>;
12339
+
12340
+ /**
12341
+ * Prices one exact custom-sticker build against Sticker Giant's own live pricing backend (POST
12342
+ * prod.pricing-backend.service.stickergiant.com/item) and returns the full 15-tier quantity
12343
+ * ladder — each tier's price and price-per-unit. With a `quantity` passed, the response also
12344
+ * carries a `selectedQuantity` with the priced value for that exact qty. The returned `price`
12345
+ * is the pricing engine's own canonical number (not the rendered 'Total' on the page, which
12346
+ * carries a small UI markup). THROWS on a missing lamination or out-of-range width/height —
12347
+ * both are caller-fixable.
12348
+ */
12349
+ priceCustomSticker(build: StickergiantBuild): Promise<StickergiantPriceResult>;
12350
+ }
12351
+ }
12352
+
12353
+ declare namespace BowmarkProvider_sunhomesaunas {
12354
+ // ── Sun Home Saunas — the unit's own declarations, verbatim ──
12355
+ // Sun Home Saunas' OWN shapes — not a capability contract.
12356
+
12357
+ interface SunHomeSaunasQuizOption {
12358
+ id: string;
12359
+ label: string;
12360
+ }
12361
+
12362
+ interface SunHomeSaunasQuizQuestion {
12363
+ id: string; // pass back as answers[].questionId
12364
+ title: string;
12365
+ type: string; // the site's own node type, e.g. "SIMPLE_MULTI"
12366
+ options: SunHomeSaunasQuizOption[]; // option.id -> answers[].optionIds
12367
+ }
12368
+
12369
+ interface SunHomeSaunasMatch {
12370
+ handle: string; // the key addSaunaToCart takes
12371
+ title: string;
12372
+ price: number; // dollars — real live Shopify price
12373
+ matchScore: number; // e.g. 5
12374
+ matchOutOf: number; // e.g. 5 -> the site's own "5/5 match"
12375
+ }
12376
+
12377
+ interface SunHomeSaunasCartResult {
12378
+ handle: string;
12379
+ title: string;
12380
+ variantId: number;
12381
+ linePrice: number; // dollars, for the quantity added
12382
+ quantity: number;
12383
+ cartItemCount: number; // the live cart's total items AFTER this add
12384
+ cartTotal: number; // dollars — the live cart's total price after this add
12385
+ }
12386
+
12387
+ /**
12388
+ * Sun Home Saunas' real Perfect Product Finder quiz — the site's own 5-question buyer quiz,
12389
+ * its real server-computed ranked product matches with live prices, and a real Shopify cart
12390
+ * write for the winning match — no login, no dealer routing.
12391
+ */
12392
+ interface Unit {
12393
+ /**
12394
+ * Reads Sun Home Saunas' real, live Perfect Product Finder quiz straight off its quiz vendor's
12395
+ * own API — the current 5 questions and every real option, with the real ids
12396
+ * getPersonalizedSaunaMatches() needs to answer them.
12397
+ */
12398
+ getSaunaFinderQuestions(): Promise<SunHomeSaunasQuizQuestion[]>;
12399
+
12400
+ /**
12401
+ * Submits real answers (from getSaunaFinderQuestions()) through the same quiz session flow the
12402
+ * site's own UI uses, and returns the site's own SERVER-COMPUTED ranked product matches with
12403
+ * real live prices and a real match score — the exact personalized result a real buyer would
12404
+ * see, never a guess from general knowledge.
12405
+ */
12406
+ getPersonalizedSaunaMatches(answers: {questionId: string, optionIds: string[]}[]): Promise<SunHomeSaunasMatch[]>;
12407
+
12408
+ /**
12409
+ * Adds one real matched sauna (a handle from getPersonalizedSaunaMatches()) to a real Shopify
12410
+ * cart at Sun Home Saunas' own real live price, and reads the cart back to confirm the write
12411
+ * landed. THROWS if the product is currently out of stock.
12412
+ */
12413
+ addSaunaToCart(handle: string, quantity?: number): Promise<SunHomeSaunasCartResult>;
12414
+ }
12415
+ }
12416
+
12417
+ declare namespace BowmarkProvider_teladoc {
12418
+ // ── Teladoc Health — the unit's own declarations, verbatim ──
12419
+ interface teladocRow {
12420
+ id: string;
12421
+ }
12422
+
12423
+ interface teladocPricingRow {
12424
+ service: string;
12425
+ priceUsd: number;
12426
+ unit: "visit" | "review" | null;
12427
+ href: string | null;
12428
+ }
12429
+
12430
+ interface teladocPricing {
12431
+ source: string;
12432
+ disclaimer: string;
12433
+ services: teladocPricingRow[];
12434
+ }
12435
+
12436
+ interface teladocInsuranceCoverage {
12437
+ source: string;
12438
+ headline: string;
12439
+ headlinePriceUsd: number;
12440
+ services: string[];
12441
+ disclaimer: string;
12442
+ }
12443
+
12444
+ /**
12445
+ * Virtual-care company: searches its public Health Library and self-pay visit pricing. Booking
12446
+ * a visit requires a member login and is out of scope.
12447
+ */
12448
+ interface Unit {
12449
+ /**
12450
+ * Returns Teladoc's published self-pay (no-insurance) visit pricing — the per-visit dollar
12451
+ * amount for each service line (24/7 Urgent Care, Nutrition, Dermatology, Mental Health), the
12452
+ * unit (visit vs review), the page's own eligibility disclaimer, and the source URL. THROWS
12453
+ * when the no-insurance tile renders without a price list (a real re-skin, not a zero-priced
12454
+ * answer).
12455
+ */
12456
+ getPricing(): Promise<teladocPricing>;
12457
+
12458
+ /**
12459
+ * Returns the with-insurance side of /start/no-insurance — the page's own headline figure (a
12460
+ * literal '$0*' on the live page, since the per-plan price lives behind member.teladoc.com and
12461
+ * is out of scope), the services the page promises are 'Included in your coverage*' (Primary
12462
+ * Care, 24/7 Care, Mental Health, And more!), and the same eligibility disclaimer as
12463
+ * `getPricing`. THROWS when the with-insurance tile renders without its service list, so a
12464
+ * re-skin that drops the second tile or rewrites it in a way this parser cannot read surfaces
12465
+ * as an error rather than an empty answer.
12466
+ */
12467
+ getInsurancePricing(): Promise<teladocInsuranceCoverage>;
12468
+ }
12469
+ }
12470
+
9639
12471
  declare namespace BowmarkProvider_tentree {
9640
12472
  // ── tentree — the unit's own declarations, verbatim ──
9641
12473
  interface TentreeVariant {
@@ -9728,6 +12560,82 @@ interface TentreeCart {
9728
12560
  }
9729
12561
  }
9730
12562
 
12563
+ declare namespace BowmarkProvider_therabody {
12564
+ // ── Therabody — the unit's own declarations, verbatim ──
12565
+ interface TherabodyVariant {
12566
+ /** Shopify's numeric variant id as a string. The future addToCart entry. */
12567
+ id: string;
12568
+ /** The variant's own label, e.g. "Default Title". */
12569
+ title: string;
12570
+ /** Decimal string exactly as the store publishes it, e.g. "54998" (cents). */
12571
+ price: string;
12572
+ /** Same scale as price. Null when the product is not on sale. */
12573
+ compareAtPrice: string | null;
12574
+ /** The store's own SKU. Null on a product without one. */
12575
+ sku: string | null;
12576
+ /** Whether the variant is purchasable right now. */
12577
+ available: boolean;
12578
+ options: string[];
12579
+ }
12580
+ interface TherabodyProduct {
12581
+ /** The handle is the only stable identifier across the catalogue. */
12582
+ handle: string;
12583
+ title: string;
12584
+ vendor: string;
12585
+ productType: string;
12586
+ url: string;
12587
+ descriptionHtml: string | null;
12588
+ optionNames: string[];
12589
+ variants: TherabodyVariant[];
12590
+ /**
12591
+ * The store's own price scale per endpoint — see TherabodyVariant.price for
12592
+ * why the two strings may differ. Range keeps the same scale as the input.
12593
+ */
12594
+ priceRange: { min: string; max: string } | null;
12595
+ /** True if ANY variant is purchasable. The "is it in stock?" answer. */
12596
+ inStock: boolean;
12597
+ tags: string[];
12598
+ /** Therabody's own images, in the order the storefront publishes them. */
12599
+ images: string[];
12600
+ }
12601
+ interface TherabodyRecommendation {
12602
+ /** The matching products, in-stock first, then by handle. */
12603
+ products: TherabodyProduct[];
12604
+ /** What the filter DROPPED, in the same register the rest of the library uses. */
12605
+ warnings: string[];
12606
+ }
12607
+
12608
+ /**
12609
+ * Therabody (Theragun) product catalogue — every device, its variants, its prices and what is
12610
+ * in stock — read off the live Shopify storefront.
12611
+ */
12612
+ interface Unit {
12613
+ /**
12614
+ * Reads the live Therabody catalogue as Therabody publishes it — every product, its handle,
12615
+ * title, vendor, description, tags, images and the per-variant price the storefront is quoting
12616
+ * right now. Returns [] on a transport failure (warnings would be on an object envelope; this
12617
+ * is a list). The catalog page is the line and the parse is the unit of work.
12618
+ */
12619
+ listTheragunProducts(opts?: { limit?: number }): Promise<TherabodyProduct[]>;
12620
+
12621
+ /**
12622
+ * Reads one product by its handle — every variant, its exact price, the image the storefront
12623
+ * is showing and whether that specific variant is purchasable right now. Takes the handle
12624
+ * listTheragunProducts returns. THROWS on an unknown handle (the store answers a real 404).
12625
+ */
12626
+ getTheragunProduct(handle: string): Promise<TherabodyProduct>;
12627
+
12628
+ /**
12629
+ * Filters the live catalogue by what a shopper actually needs — device family, audience, and
12630
+ * the features named (percussion, recovery, hot/cold, breath). Returns the matching products
12631
+ * with their real prices, ranked by in-stock first. The storefront does not publish a query or
12632
+ * filter endpoint, so the function is local filtering on the catalogue listTheragunProducts
12633
+ * already returns — the divide is what the function does with the data, not how it gets there.
12634
+ */
12635
+ recommendTheragun(criteria: { audience?: string; features?: string[]; inStockOnly?: boolean }): Promise<TherabodyRecommendation>;
12636
+ }
12637
+ }
12638
+
9731
12639
  declare namespace BowmarkProvider_thezebra {
9732
12640
  // ── The Zebra — the unit's own declarations, verbatim ──
9733
12641
  interface thezebraStateRatesQuery {
@@ -9992,6 +12900,47 @@ interface thezebraRentersQuotes {
9992
12900
  url: string
9993
12901
  }
9994
12902
 
12903
+ interface thezebraAutoDriver {
12904
+ firstName: string
12905
+ lastName: string
12906
+ dob: string // ISO YYYY-MM-DD — carriers rate on the DATE, not on an age
12907
+ email: string
12908
+ }
12909
+
12910
+ interface thezebraAutoVehicle {
12911
+ year: number // 4-digit; a model year The Zebra does not rate THROWS
12912
+ make: string // "Toyota", "Tesla"
12913
+ model: string // "Camry", "Model 3" — a TRIM is not a page
12914
+ }
12915
+
12916
+ interface thezebraAutoQuotesQuery {
12917
+ driver: thezebraAutoDriver
12918
+ vehicle: thezebraAutoVehicle
12919
+ state: string // 2-letter postal code
12920
+ zip: string // 5 digits
12921
+ county: string // the county the ZIP sits in — the gateway validates server-side
12922
+ }
12923
+
12924
+ interface thezebraAutoQuote {
12925
+ carrier: string // e.g. "Progressive"
12926
+ carrierSlug: string // the site's own slug, e.g. "progressive"
12927
+ monthlyPremium: number // USD per MONTH; the card's period is asserted
12928
+ sixMonthPremium: number | null // USD per 6-month policy, where the card publishes one
12929
+ totalPremium: number | null // USD for the whole term, never derived
12930
+ policyLengthMonths: number | null
12931
+ deductible: number | null
12932
+ coverages: string[] // every coverage the card lists, verbatim
12933
+ }
12934
+
12935
+ interface thezebraAutoQuotes {
12936
+ quotes: thezebraAutoQuote[] // cheapest monthly premium first; [] is a real answer
12937
+ // The carriers ADVERTISED beside the quotes — paid placements with no price.
12938
+ // Returned under their own name so they can never be read as offers.
12939
+ advertisedCarriers: string[]
12940
+ warnings: string[] // names every dropped source / what the gateway refused
12941
+ url: string
12942
+ }
12943
+
9995
12944
  /**
9996
12945
  * US insurance comparison marketplace — side-by-side auto, home and renters rates from 100+
9997
12946
  * carriers, plus published rate research by state, city, vehicle, carrier and driver history.
@@ -10165,6 +13114,34 @@ interface thezebraRentersQuotes {
10165
13114
  * homeowners funnel reaches the same results page and publishes no premium anywhere on it.
10166
13115
  */
10167
13116
  getRentersQuotes(query: thezebraRentersQuotesQuery): Promise<thezebraRentersQuotes>;
13117
+
13118
+ /**
13119
+ * Returns REAL auto insurance quotes for one driver and one vehicle at a US ZIP — each
13120
+ * carrier's own monthly and six-month premium, deductible, and the coverage it priced, as The
13121
+ * Zebra's auto quote funnel prices them. This is a priced offer for the person asking, NOT the
13122
+ * published averages `getStateRates` and its siblings return. Pass `driver` (`firstName`,
13123
+ * `lastName`, `dob` ISO YYYY-MM-DD, `email`), one `vehicle` (`year`, `make`, `model` — a model
13124
+ * The Zebra does not rate THROWS naming the URL it tried), the 2-letter `state`, a 5-digit
13125
+ * `zip`, and `county` (the county the ZIP sits in — The Zebra validates it server-side and a
13126
+ * missing or wrong county is bounced). **The write binds, the read does not — yet**: the
13127
+ * GraphQL gateway at `graphql-gateway.production.thezebra.com` accepts the auto seed
13128
+ * (`LegacyStartInput.start.currentlyInsured` is the only field Apollo currently exposes on
13129
+ * that input), but the results route STILL bounces the session to the homepage with the four
13130
+ * fields this function sends. The function throws on the bounce with a message naming the gap;
13131
+ * the second required field on `LegacyStartInput` is the next attempt's work, and the rejected
13132
+ * probes — `helpToday`, `userPurchaseTimeframe`, `hadActiveInsurance`, `residenceOwnership`,
13133
+ * `presumedAnswers`, `policyLinkInfo`, `startDate`, `desiredCoverage` — are documented in
13134
+ * `agents/capability-engineer/instances/vertical-insurance/tools/zebra-auto-quotes/shape-summary.json`
13135
+ * (and the e5 clone) so they don't have to be re-derived. **`advertisedCarriers` is not a
13136
+ * quote list and must never be read as one**: the results page would carry paid carrier
13137
+ * placements alongside real offers, separated by `data-cy="results-card_ad_<carrier>"` (ad)
13138
+ * versus `data-cy="results-card_q2b_<carrier>"` (real offer), and the advertised names are
13139
+ * returned in their own field with no price attached. Every premium is USD and
13140
+ * `monthlyPremium` is per MONTH — the card's own period is checked rather than assumed, and a
13141
+ * card printing any other term THROWS instead of relabelling a figure. `totalPremium` is the
13142
+ * site's own whole-term number and is never divided out of the monthly one.
13143
+ */
13144
+ getAutoQuotes(query: thezebraAutoQuotesQuery): Promise<thezebraAutoQuotes>;
10168
13145
  }
10169
13146
  }
10170
13147
 
@@ -10315,6 +13292,46 @@ interface UlrichPriceResult {
10315
13292
  }
10316
13293
  }
10317
13294
 
13295
+ declare namespace BowmarkProvider_viewrail {
13296
+ // ── Viewrail — the unit's own declarations, verbatim ──
13297
+ interface ViewrailMaterial {
13298
+ slug: string;
13299
+ title: string;
13300
+ metal: boolean;
13301
+ defaultFinish: string | null;
13302
+ finishes: string[];
13303
+ }
13304
+
13305
+ interface ViewrailMountingStyle {
13306
+ slug: string;
13307
+ title: string;
13308
+ availableMaterials: string[];
13309
+ }
13310
+
13311
+ /**
13312
+ * Cable railing / floating-stair manufacturer — the material and mounting-style catalog behind
13313
+ * Victor, Viewrail's own draw-and-quote design app (victor.viewrail.com). listMaterials and
13314
+ * listMountingStyles are live; the rest of Victor's option set (infill, posts, handrails,
13315
+ * newels) are stubs.
13316
+ */
13317
+ interface Unit {
13318
+ /**
13319
+ * Lists the metal and metal-look composite families Victor's cable railing configurator offers
13320
+ * (304/316/2205 stainless steel, aluminum, wood-grain aluminum, …), each with whether it's a
13321
+ * true metal, its default finish, and every finish slug it supports — off Victor's own
13322
+ * materials-config API.
13323
+ */
13324
+ listMaterials(): Promise<ViewrailMaterial[]>;
13325
+
13326
+ /**
13327
+ * Lists Victor's post-mounting styles (Surface Mount, Side Mount, SLIM Side Mount, Bump Out
13328
+ * Side Mount, Core Drill, …) and which material families each is available in — the first
13329
+ * choice Victor's own design flow asks a user to make before drawing a run.
13330
+ */
13331
+ listMountingStyles(): Promise<ViewrailMountingStyle[]>;
13332
+ }
13333
+ }
13334
+
10318
13335
  declare namespace BowmarkProvider_visible {
10319
13336
  // ── Visible — the unit's own declarations, verbatim ──
10320
13337
  interface VisibleDealOffer {
@@ -10419,15 +13436,91 @@ interface VisibleGetPhoneResult {
10419
13436
  flashSale: VisiblePhoneFlashSale | null;
10420
13437
  }
10421
13438
 
13439
+ interface VisibleCoveragePoint {
13440
+ matchedAddress: string | null;
13441
+ city: string | null;
13442
+ state: string | null;
13443
+ zip: string | null;
13444
+ latitude: number;
13445
+ longitude: number;
13446
+ }
13447
+
13448
+ interface VisibleCheckCoverageResult {
13449
+ input: string;
13450
+ point: VisibleCoveragePoint;
13451
+ tier: "5gUltraWideband" | "5gNationwide" | "4gLte" | "none";
13452
+ fiveGUltraWideband: boolean;
13453
+ fiveGNationwide: boolean;
13454
+ fourGLte: boolean;
13455
+ /** The site's own one-word verdict, forwarded verbatim. Measured to disagree
13456
+ * with the tier flags on a real point — trust the flags over this. */
13457
+ summary: string;
13458
+ }
13459
+
13460
+ interface VisibleSearchPhone {
13461
+ slug: string;
13462
+ name: string;
13463
+ make: string;
13464
+ deviceOs: string | null;
13465
+ listPrice: number | null;
13466
+ price: number | null;
13467
+ monthlyPrice: number | null;
13468
+ financingTermMonths: number | null;
13469
+ inStock: boolean;
13470
+ preOwned: boolean;
13471
+ fiveG: boolean;
13472
+ eSIMCompatible: boolean;
13473
+ comingSoon: boolean;
13474
+ tradeInEligible: boolean;
13475
+ visiblePaybackEligible: boolean | null;
13476
+ imageUrl: string | null;
13477
+ source: string;
13478
+ flashSale: VisiblePhoneFlashSale | null;
13479
+ }
13480
+
13481
+ interface VisibleSearchPhonesResult {
13482
+ source: string;
13483
+ totalCatalogueCount: number;
13484
+ filteredCount: number;
13485
+ page: number;
13486
+ pageSize: number;
13487
+ hasMore: boolean;
13488
+ availableMakes: string[];
13489
+ results: VisibleSearchPhone[];
13490
+ }
13491
+ interface VisiblePlanFeature {
13492
+ label: string | null;
13493
+ items: string[];
13494
+ }
13495
+ interface VisiblePlan {
13496
+ name: string;
13497
+ monthlyPrice: number;
13498
+ regularPrice: number | null;
13499
+ promoCode: string | null;
13500
+ promoText: string | null;
13501
+ taxesAndFeesIncluded: boolean | null;
13502
+ badge: string | null;
13503
+ ctaCode: string | null;
13504
+ ctaUrl: string | null;
13505
+ features: VisiblePlanFeature[];
13506
+ }
13507
+ interface VisibleGetPlansResult {
13508
+ source: string;
13509
+ plans: VisiblePlan[];
13510
+ }
13511
+
10422
13512
  /**
10423
13513
  * Visible (Verizon's prepaid brand): the promotions running right now — the offer grid with
10424
13514
  * its promo codes and fine print, plus the standing referral, trade-in, payback, Stack'em and
10425
- * Fios home-internet bundle programmes — and one phone in full from its catalogue slug or URL,
13515
+ * Fios home-internet bundle programmes — one phone in full from its catalogue slug or URL,
10426
13516
  * every storage/colour SKU with its own price, monthly financing terms and live stock,
10427
- * alongside the specs, images, device-protection plans and eSIM/5G support. Also declared, not
10428
- * yet built: plan pricing, network coverage by address, bring-your-own-device compatibility,
10429
- * phone SEARCH across the catalogue, per-device trade-in values, international rates, the
10430
- * wearable catalogue and the support estate.
13517
+ * alongside the specs, images, device-protection plans and eSIM/5G support Verizon's real
13518
+ * network coverage at a caller-supplied US address or ZIP, broken down by 5G Ultra Wideband /
13519
+ * 5G Nationwide / 4G LTE rather than a single yes/no — and the three-tier line-up as the plans
13520
+ * page renders it, with each tier's headline price, the running promo and the code that
13521
+ * unlocks it, the marketing badge and the four labelled feature sections. Also declared, not
13522
+ * yet built: bring-your-own-device compatibility, per-device trade-in values, international
13523
+ * rates, the wearable catalogue and the support estate.
10431
13524
  */
10432
13525
  interface Unit {
10433
13526
  /**
@@ -10453,6 +13546,48 @@ interface VisibleGetPhoneResult {
10453
13546
  * that ended months ago.
10454
13547
  */
10455
13548
  getPhone(slugOrUrl: string, options?: { preOwned?: boolean }): Promise<VisibleGetPhoneResult>;
13549
+
13550
+ /**
13551
+ * Returns the phones Visible currently sells, with the headline facts a purchase turns on —
13552
+ * name, make, OS, list price, current price, financed monthly payment and term, in-stock
13553
+ * status, pre-owned vs new, 5G support, eSIM compatibility, trade-in / Payback eligibility,
13554
+ * and the catalogue image. Optional filters narrow by make (Apple, Samsung, Google, Motorola,
13555
+ * TCL), by a `priceMax` the buyer's actually-going-to-pay price (NOT the strikethrough on a
13556
+ * stale flash-sale banner), by 5G support, and by in-stock availability. Pagination is
13557
+ * explicit and client-side over the catalogue's bounded 42-row response — the endpoint does
13558
+ * NOT paginate server-side; every tried pagination parameter is ignored. Joins naturally with
13559
+ * `getPhone`, which takes the same `slug` as its input — `searchPhones` answers "what does
13560
+ * Visible sell?", `getPhone` answers "what does this specific device cost across storage and
13561
+ * colour?".
13562
+ */
13563
+ searchPhones(options?: { make?: string; priceMax?: number; supports5G?: boolean; inStock?: boolean; page?: number; pageSize?: number }): Promise<VisibleSearchPhonesResult>;
13564
+
13565
+ /**
13566
+ * Returns Verizon's real network coverage — the tier that actually determines usable speed (5G
13567
+ * Ultra Wideband, 5G Nationwide, or 4G LTE) — at a caller-supplied US street address or
13568
+ * 5-digit ZIP, straight from the same point-level lookup Verizon's own coverage map (embedded
13569
+ * in visible.com/plans/coverage) queries. Geocodes the input first — a full address via the US
13570
+ * Census Bureau's public geocoder, a bare ZIP via a ZIP-centroid lookup — then reads the tiers
13571
+ * at that exact point, never a national or per-ZIP summary standing in for an address-level
13572
+ * answer. Also returns the site's own one-word verdict ("Best"/"Good"/"Moderate"/"No
13573
+ * Coverage") as `summary`, measured to sometimes DISAGREE with the tier flags — the flags are
13574
+ * the ones to trust.
13575
+ */
13576
+ checkCoverage(addressOrZip: string): Promise<VisibleCheckCoverageResult>;
13577
+
13578
+ /**
13579
+ * Returns the three tiers Visible sells today (Visible, Visible+, Visible+ Pro) as the plans
13580
+ * page renders them — each tier's headline monthly price, the regular price the running promo
13581
+ * unlocks (e.g. $19/mo with code SAVE6 unlocking $25/mo), the promo code itself, the "Taxes &
13582
+ * fees included" guarantee, the marketing badge ("Most popular" / "Best value" / "Ultimate
13583
+ * experience"), the CTA button code that pre-fills /shop/plan-selected, and four labelled
13584
+ * feature sections (Network, Mobile Hotspot, International, The Extras) with every bullet the
13585
+ * page shows. Reads the LIVE page only, never the site's own /docs/visible_plans.md, which is
13586
+ * dated 2025-11-12 and answers the same prompt with two stale tiers and no code. Three tiers
13587
+ * is hard — a future fourth tier changes the answer visibly rather than reading as a
13588
+ * half-broken response.
13589
+ */
13590
+ getPlans(): Promise<VisibleGetPlansResult>;
10456
13591
  }
10457
13592
  }
10458
13593
 
@@ -10480,12 +13615,38 @@ interface walmartStore {
10480
13615
  services: Array<{ name: string; displayName: string; phone: string | null }>;
10481
13616
  }
10482
13617
 
13618
+ interface walmartSearchResult {
13619
+ itemId: string;
13620
+ name: string;
13621
+ brand: string | null;
13622
+ url: string;
13623
+ image: string | null;
13624
+ price: number | null;
13625
+ wasPrice: number | null;
13626
+ priceRangeMin: number | null;
13627
+ inStock: boolean;
13628
+ rating: number | null;
13629
+ reviewCount: number;
13630
+ sponsored: boolean;
13631
+ totalMatches: number;
13632
+ }
13633
+
10483
13634
  /**
10484
- * Walmart.com — product search, product detail, store-level stock, store locator and more. One
10485
- * function built: finding nearby stores by ZIP, with address, hours, phone and department
10486
- * availability.
13635
+ * Walmart.com — product search, product detail, store-level stock, store locator and more. Two
13636
+ * functions built: keyword search across the catalog, and finding nearby stores by ZIP with
13637
+ * address, hours, phone and department availability.
10487
13638
  */
10488
13639
  interface Unit {
13640
+ /**
13641
+ * Searches walmart.com's catalog for a keyword and returns matching products — item id, name,
13642
+ * brand, price (plus the pre-markdown price and the cheapest OTHER purchase option's price
13643
+ * when the site names a range), image, in-stock flag, rating, review count and whether the row
13644
+ * is a sponsored placement — the way the site's own search bar does. Returns the site's own
13645
+ * first results page (organic rows only, its own trending/related carousels excluded) in the
13646
+ * site's own default relevance order.
13647
+ */
13648
+ search(args: { query: string; limit?: number }): Promise<walmartSearchResult[]>;
13649
+
10489
13650
  /**
10490
13651
  * Finds nearby Walmart stores for a 5-digit US ZIP code — address, phone, hours,
10491
13652
  * geo-coordinates, distance, which fulfilment methods each store supports (curbside pickup,
@@ -10516,6 +13677,26 @@ interface wellfoundRow {
10516
13677
  equityMax: number | null;
10517
13678
  }
10518
13679
 
13680
+ interface wellfoundJobDetail {
13681
+ id: string;
13682
+ title: string;
13683
+ url: string;
13684
+ descriptionHtml: string;
13685
+ employmentType: string | null;
13686
+ experienceLevel: string | null;
13687
+ remote: boolean;
13688
+ locations: string[];
13689
+ remoteLocations: string[];
13690
+ compensationRaw: string | null;
13691
+ salaryMin: number | null;
13692
+ salaryMax: number | null;
13693
+ salaryCurrency: "USD" | null;
13694
+ equityMin: number | null;
13695
+ equityMax: number | null;
13696
+ datePosted: string | null;
13697
+ company: { name: string; slug: string | null; url: string | null; website: string | null; logoUrl: string | null };
13698
+ }
13699
+
10519
13700
  interface wellfoundCompanyRow {
10520
13701
  id: string;
10521
13702
  name: string;
@@ -10534,6 +13715,27 @@ interface wellfoundCompanyRow {
10534
13715
  highlightedRoles: { id: string; title: string; url: string; locations: string[] }[];
10535
13716
  }
10536
13717
 
13718
+ interface wellfoundCompanyDetail {
13719
+ id: string;
13720
+ name: string;
13721
+ slug: string;
13722
+ url: string;
13723
+ highConcept: string | null;
13724
+ productDescription: string | null;
13725
+ companySize: string | null;
13726
+ employeesMin: number | null;
13727
+ employeesMax: number | null;
13728
+ markets: string[];
13729
+ stage: string | null;
13730
+ activelyHiring: boolean;
13731
+ badges: { id: string; label: string; tooltip: string | null }[];
13732
+ locations: { slug: string; displayName: string }[];
13733
+ remotePolicy: "remote" | null;
13734
+ companyUrl: string | null;
13735
+ totalRaisedAmount: number | null;
13736
+ logoUrl: string | null;
13737
+ }
13738
+
10537
13739
  /**
10538
13740
  * Wellfound (formerly AngelList Talent) — startup job search with salary and equity bands,
10539
13741
  * startup profiles and their open roles.
@@ -10556,6 +13758,24 @@ interface wellfoundCompanyRow {
10556
13758
  * filters over the fields the search itself returns.
10557
13759
  */
10558
13760
  searchCompanies(args: object): Promise<wellfoundCompanyRow[]>;
13761
+
13762
+ /**
13763
+ * Reads one job posting in full the way its own detail page does — takes the `url` a
13764
+ * `searchJobs`/`searchCompanies` row already carries (a bare id 404s, measured 2026-08-06) —
13765
+ * returning the full description, salary band, equity range (both parsed off the header chip;
13766
+ * equity has no structured-data field on this site), location, remote policy, the site's own
13767
+ * experience-requirement text and the hiring startup.
13768
+ */
13769
+ getJob(args: { url: string }): Promise<wellfoundJobDetail>;
13770
+
13771
+ /**
13772
+ * Reads one startup's `/company/<slug>` profile — the longer product description (HTML), the
13773
+ * full market tagging, location tags with display names, the explicitly-set Remote policy,
13774
+ * total raised, the company's own website, every badge verbatim, and the same `companySize`
13775
+ * band `searchCompanies` already decodes — the context a candidate weighs a startup on before
13776
+ * applying to it. Takes the `slug` a `searchCompanies` row already carries.
13777
+ */
13778
+ getCompany(args: { slug: string }): Promise<wellfoundCompanyDetail>;
10559
13779
  }
10560
13780
  }
10561
13781
 
@@ -10729,17 +13949,23 @@ interface BowmarkProviders {
10729
13949
  aa: BowmarkProvider_aa.Unit;
10730
13950
  abercrombie: BowmarkProvider_abercrombie.Unit;
10731
13951
  ashleyfurniture: BowmarkProvider_ashleyfurniture.Unit;
13952
+ avis: BowmarkProvider_avis.Unit;
10732
13953
  azure: BowmarkProvider_azure.Unit;
10733
13954
  barletta: BowmarkProvider_barletta.Unit;
10734
13955
  bhphoto: BowmarkProvider_bhphoto.Unit;
10735
13956
  blenderseyewear: BowmarkProvider_blenderseyewear.Unit;
13957
+ bluehaven: BowmarkProvider_bluehaven.Unit;
10736
13958
  bmwusa: BowmarkProvider_bmwusa.Unit;
13959
+ cancer: BowmarkProvider_cancer.Unit;
13960
+ caraway: BowmarkProvider_caraway.Unit;
10737
13961
  cars: BowmarkProvider_cars.Unit;
10738
13962
  cheapflights: BowmarkProvider_cheapflights.Unit;
10739
13963
  chriscraft: BowmarkProvider_chriscraft.Unit;
10740
13964
  classpass: BowmarkProvider_classpass.Unit;
10741
13965
  cloudflare: BowmarkProvider_cloudflare.Unit;
13966
+ cyberpowerpc: BowmarkProvider_cyberpowerpc.Unit;
10742
13967
  decked: BowmarkProvider_decked.Unit;
13968
+ dice: BowmarkProvider_dice.Unit;
10743
13969
  dickssportinggoods: BowmarkProvider_dickssportinggoods.Unit;
10744
13970
  dillards: BowmarkProvider_dillards.Unit;
10745
13971
  discounttire: BowmarkProvider_discounttire.Unit;
@@ -10754,18 +13980,22 @@ interface BowmarkProviders {
10754
13980
  grainger: BowmarkProvider_grainger.Unit;
10755
13981
  healthcare_gov: BowmarkProvider_healthcare_gov.Unit;
10756
13982
  hellofresh: BowmarkProvider_hellofresh.Unit;
13983
+ hellotend: BowmarkProvider_hellotend.Unit;
10757
13984
  hilton: BowmarkProvider_hilton.Unit;
10758
13985
  hunter: BowmarkProvider_hunter.Unit;
10759
13986
  ibuypower: BowmarkProvider_ibuypower.Unit;
10760
13987
  insurify: BowmarkProvider_insurify.Unit;
10761
13988
  interiordefine: BowmarkProvider_interiordefine.Unit;
13989
+ joybird: BowmarkProvider_joybird.Unit;
10762
13990
  kayak: BowmarkProvider_kayak.Unit;
10763
13991
  labcorp: BowmarkProvider_labcorp.Unit;
10764
13992
  linkedin: BowmarkProvider_linkedin.Unit;
10765
13993
  liquiddeath: BowmarkProvider_liquiddeath.Unit;
10766
13994
  lonelyplanet: BowmarkProvider_lonelyplanet.Unit;
10767
13995
  lufthansa: BowmarkProvider_lufthansa.Unit;
13996
+ lululemon: BowmarkProvider_lululemon.Unit;
10768
13997
  mailchimp: BowmarkProvider_mailchimp.Unit;
13998
+ marriott: BowmarkProvider_marriott.Unit;
10769
13999
  mcdonalds: BowmarkProvider_mcdonalds.Unit;
10770
14000
  medicare: BowmarkProvider_medicare.Unit;
10771
14001
  microcenter: BowmarkProvider_microcenter.Unit;
@@ -10778,6 +14008,7 @@ interface BowmarkProviders {
10778
14008
  newegg: BowmarkProvider_newegg.Unit;
10779
14009
  oanda: BowmarkProvider_oanda.Unit;
10780
14010
  otto: BowmarkProvider_otto.Unit;
14011
+ paypal: BowmarkProvider_paypal.Unit;
10781
14012
  pirateship: BowmarkProvider_pirateship.Unit;
10782
14013
  pizzahut: BowmarkProvider_pizzahut.Unit;
10783
14014
  progressive: BowmarkProvider_progressive.Unit;
@@ -10790,10 +14021,15 @@ interface BowmarkProviders {
10790
14021
  semihandmade: BowmarkProvider_semihandmade.Unit;
10791
14022
  soundcloud: BowmarkProvider_soundcloud.Unit;
10792
14023
  statefarm: BowmarkProvider_statefarm.Unit;
14024
+ stickergiant: BowmarkProvider_stickergiant.Unit;
14025
+ sunhomesaunas: BowmarkProvider_sunhomesaunas.Unit;
14026
+ teladoc: BowmarkProvider_teladoc.Unit;
10793
14027
  tentree: BowmarkProvider_tentree.Unit;
14028
+ therabody: BowmarkProvider_therabody.Unit;
10794
14029
  thezebra: BowmarkProvider_thezebra.Unit;
10795
14030
  trektravel: BowmarkProvider_trektravel.Unit;
10796
14031
  ulrichlifestyle: BowmarkProvider_ulrichlifestyle.Unit;
14032
+ viewrail: BowmarkProvider_viewrail.Unit;
10797
14033
  visible: BowmarkProvider_visible.Unit;
10798
14034
  walmart: BowmarkProvider_walmart.Unit;
10799
14035
  wellfound: BowmarkProvider_wellfound.Unit;
@@ -16264,6 +19500,7 @@ interface BowmarkProviders {
16264
19500
  avedaisland: BowmarkFamily_shopify_store.Unit;
16265
19501
  avenatheme: BowmarkFamily_shopify_store.Unit;
16266
19502
  avenidabresil: BowmarkFamily_shopify_store.Unit;
19503
+ aventon: BowmarkFamily_shopify_store.Unit;
16267
19504
  aventsbyaugust: BowmarkFamily_shopify_store.Unit;
16268
19505
  aventureextension: BowmarkFamily_shopify_store.Unit;
16269
19506
  avenues3: BowmarkFamily_shopify_store.Unit;
@@ -17598,6 +20835,7 @@ interface BowmarkProviders {
17598
20835
  beyondthemeatsuit: BowmarkFamily_shopify_store.Unit;
17599
20836
  beyondthenotes: BowmarkFamily_shopify_store.Unit;
17600
20837
  beyondtheshimmer: BowmarkFamily_shopify_store.Unit;
20838
+ beyondyoga: BowmarkFamily_shopify_store.Unit;
17601
20839
  beyourstheme: BowmarkFamily_shopify_store.Unit;
17602
20840
  beyoursthemeclothing: BowmarkFamily_shopify_store.Unit;
17603
20841
  beyoursthemefashion: BowmarkFamily_shopify_store.Unit;