Skip to content

Feat: add more filters based on browser testing deep dive#99

Merged
punitarani merged 10 commits intopunitarani:mainfrom
zspherez:feat/more-filters
Apr 1, 2026
Merged

Feat: add more filters based on browser testing deep dive#99
punitarani merged 10 commits intopunitarani:mainfrom
zspherez:feat/more-filters

Conversation

@zspherez
Copy link
Copy Markdown
Contributor

@zspherez zspherez commented Mar 31, 2026

Add flight search filters: emissions, bags, alliances, sort modes, and show-all results. Utilized a combination of browser testing and automated probing to determine results of changes to various flags in the requests.

Summary

  • Emissions filter: New --emissions flag (ALL/LESS) maps to Google Flights' "Less emissions only" toggle
  • Bags filter: New --bags and --carry-on flags include baggage fees in displayed prices, making budget vs full-service carrier comparisons fairer
  • Show all results: --all/--no-all (default on) returns ~100 results instead of ~30 curated ones, equivalent to clicking "Show more flights"
  • Alliance filtering: Added ONEWORLD, SKYTEAM, STAR_ALLIANCE to the Airline enum so users can filter by alliance (e.g. --airlines STAR_ALLIANCE)
  • Sort modes: Updated SortBy enum to match Google Flights — renamed NONETOP_FLIGHTS, TOP_FLIGHTSBEST, added EMISSIONS sort
  • Documented unknown flags: Added detailed comments on every placeholder position in the API payload based on systematic probing (~150 requests testing each position)

Notable

  • Self-transfer tickets toggle was identified (browser uses wrapper nesting at [1][6]) but cannot be implemented in our flat payload format — documented as a known limitation
  • All new features are wired through CLI, MCP server, and models
  • Existing test expectations updated for new enum values/defaults; 9 new tests added

Test plan

  • make lint passes
  • All 146 tests pass (0 failures)
  • New tests cover emissions parsing, bags format output, show-all toggle, alliance filtering, and updated sort enum values

Greptile Summary

This PR adds five new Google Flights search capabilities — emissions filtering, bags-in-price display, show-all-results toggle, airline alliance filtering, and updated sort modes — all wired consistently through the CLI, MCP server, and data models. The implementation is backed by documented systematic API probing (~150 requests) and includes 9 new tests covering all added features.

Key changes:

  • New filters: EmissionsFilter enum, BagsFilter model, and show_all_results bool added to both FlightSearchFilters and DateSearchFilters (except show_all_results which is flights-only, correctly omitted from date search).
  • SortBy enum renamed: NONETOP_FLIGHTS (value 0), TOP_FLIGHTSBEST (value 1), new EMISSIONS (value 6). The model default changed from NONE to BEST, which is a semantic shift for any code constructing FlightSearchFilters without an explicit sort_by.
  • Alliance filtering: ONEWORLD, SKYTEAM, STAR_ALLIANCE added to the Airline enum; they serialize as their Python name (e.g. \"STAR_ALLIANCE\") via the existing .name-based serializer, consistent with how airline IATA codes work.
  • Payload documentation: Every placeholder position in both FlightSearchFilters.format() and DateSearchFilters.format() now has a precise comment from empirical testing, significantly improving maintainability.
  • CLAUDE.md not updated: The MCP tool reference section (line 118) still lists the old sort_by values and does not mention TOP_FLIGHTS, BEST, or EMISSIONS.

Confidence Score: 5/5

Safe to merge — all remaining findings are minor style and documentation gaps with no runtime or data-integrity impact.

All 146 tests pass, the new filters are correctly wired through CLI, MCP, and models, and the payload positions were empirically verified. The three open comments are P2: a stale field description in FlightSearchParams, a missing upper-bound constraint on --bags in the CLI, and a redundant parse_emissions implementation. None affect correctness.

fli/mcp/server.py (stale sort_by description in FlightSearchParams) and CLAUDE.md (sort_by values not updated in the MCP tool reference).

Important Files Changed

Filename Overview
fli/models/google_flights/flights.py Core filter model updated with emissions, bags, show_all_results fields and detailed comments on every payload index position; default sort_by changed from removed NONE to BEST.
fli/models/google_flights/base.py Adds EmissionsFilter enum and BagsFilter Pydantic model; renames NONETOP_FLIGHTS and adds BEST/EMISSIONS to SortBy enum.
fli/models/google_flights/dates.py Mirrors FlightSearchFilters updates: adds emissions and bags fields with correct payload position comments; show_all_results not added (date API endpoint doesn't support it).
fli/models/airline.py Adds three airline alliance entries (ONEWORLD, SKYTEAM, STAR_ALLIANCE) to the Airline enum; they serialize via .name as their Python identifier in the API payload.
fli/core/parsers.py Adds parse_emissions function; updates parse_sort_by docstring; parse_emissions reimplements what resolve_enum already provides (minor style inconsistency).
fli/mcp/server.py Adds emissions, checked_bags, carry_on, show_all_results to both FlightSearchParams and the search_flights tool; FlightSearchParams.sort_by description remains stale (still lists old values).
fli/cli/commands/flights.py Adds --layover, --emissions, --bags, --carry-on, --all/--no-all options; --bags has no upper-bound enforcement unlike the MCP le=2 constraint.
tests/models/test_flight_search_filters.py Adds 5 new test cases covering emissions, bags, show_all toggle, alliance, and sort enum changes; updates existing test expectations for the new show_all_results=True default.
tests/core/test_parsers.py New test file covering parse_emissions, alliance airline parsing, and updated SortBy enum values with specific value assertions.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    CLI["CLI --emissions/--bags/--all/--layover"] --> Core["core/parsers.py\nparse_emissions()"]
    MCP["MCP search_flights()\nemissions, checked_bags,\ncarry_on, show_all_results"] --> Core
    Core --> Filters["FlightSearchFilters\n+ emissions: EmissionsFilter\n+ bags: BagsFilter | None\n+ show_all_results: bool"]
    Filters --> Format["format()\nouter[3] = show_all_results\nfilters[1][10] = bags\nsegment[13] = emissions"]
    Format --> Payload["Google Flights API\nURL-encoded payload"]
    Airline["Airline enum\n+ ONEWORLD\n+ SKYTEAM\n+ STAR_ALLIANCE"] --> Filters
    SortBy["SortBy enum\nTOP_FLIGHTS=0\nBEST=1 (new default)\nCHEAPEST=2\nEMISSIONS=6"] --> Filters
Loading

Comments Outside Diff (1)

  1. fli/mcp/server.py, line 236-239 (link)

    P2 Stale sort_by description in FlightSearchParams

    The FlightSearchParams.sort_by field description was not updated to include the new sort options added in this PR. The search_flights tool function's sort_by parameter was correctly updated, but this model's description still lists old values. While FlightSearchParams is not directly exposed as an MCP tool schema, it could mislead developers reading the code or generating SDK clients from the model.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: fli/mcp/server.py
    Line: 236-239
    
    Comment:
    **Stale `sort_by` description in `FlightSearchParams`**
    
    The `FlightSearchParams.sort_by` field description was not updated to include the new sort options added in this PR. The `search_flights` tool function's `sort_by` parameter was correctly updated, but this model's description still lists old values. While `FlightSearchParams` is not directly exposed as an MCP tool schema, it could mislead developers reading the code or generating SDK clients from the model.
    
    
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: fli/mcp/server.py
Line: 236-239

Comment:
**Stale `sort_by` description in `FlightSearchParams`**

The `FlightSearchParams.sort_by` field description was not updated to include the new sort options added in this PR. The `search_flights` tool function's `sort_by` parameter was correctly updated, but this model's description still lists old values. While `FlightSearchParams` is not directly exposed as an MCP tool schema, it could mislead developers reading the code or generating SDK clients from the model.

```suggestion
    sort_by: str = Field(
        CONFIG.default_sort_by,
        description="Sort by: TOP_FLIGHTS, BEST, CHEAPEST, DEPARTURE_TIME, ARRIVAL_TIME, DURATION, EMISSIONS",
    )
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: fli/cli/commands/flights.py
Line: 271-277

Comment:
**No upper bound validation on `--bags`**

The CLI `--bags` option accepts any non-negative integer, while the MCP `FlightSearchParams` enforces `le=2`. The underlying `BagsFilter.checked_bags` uses `NonNegativeInt` which has no maximum. Users can pass `--bags 10`, which the model will accept without error — the Google Flights API likely silently ignores or clamps out-of-range values.

For consistency with the MCP constraint and the help text ("0, 1, or 2"), consider adding validation:

```suggestion
    checked_bags: Annotated[
        int,
        typer.Option(
            "--bags",
            "-b",
            help="Number of checked bags to include in price (0, 1, or 2)",
            min=0,
            max=2,
        ),
    ] = 0,
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: fli/core/parsers.py
Line: 193-213

Comment:
**`parse_emissions` duplicates the existing `resolve_enum` helper**

The module already has a generic `resolve_enum(enum_cls, name)` helper that handles case-insensitive lookup and normalized error messages. `parse_emissions` reimplements the same logic with a manual dict. Using `resolve_enum` would keep the module consistent and make any future enum values automatically available without updating a lookup table.

```suggestion
def parse_emissions(emissions: str) -> EmissionsFilter:
    """Parse an emissions filter string into an EmissionsFilter enum.

    Args:
        emissions: Emissions filter (ALL, LESS)

    Returns:
        The corresponding EmissionsFilter enum member

    Raises:
        ParseError: If the value is not valid

    """
    return resolve_enum(EmissionsFilter, emissions)
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "lint" | Re-trigger Greptile

Greptile also left 2 inline comments on this PR.

(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!

Context used:

  • Context used - CLAUDE.md (source)

@punitarani punitarani merged commit e43845d into punitarani:main Apr 1, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants