feat: add search for the runtime's /v1/search endpoint - #177
Conversation
Adds Client.search, exposing vector, keyword, and hybrid search from Python. Previously only spice.js could reach /v1/search; users of every other SDK had to hand-roll the HTTP call. Response types (SearchResult, SearchMatch) are modelled on the runtime's actual wire shape: matches is a list per column because one column can contribute several chunks to a match, and data / primary_key / metadata are omitted by the runtime when empty. Adds HttpRequests.post_json, which surfaces the runtime's plain-text error body instead of the generic message raise_for_status produces.
There was a problem hiding this comment.
Pull request overview
Adds first-class Python SDK support for the runtime’s /v1/search endpoint by introducing request/response types, local argument validation, and HTTP plumbing to preserve runtime error messages, alongside documentation and unit tests.
Changes:
- Add
Client.search(...)plus_search.pyrequest builder and response dataclasses (SearchResult,SearchMatch). - Add
HttpRequests.post_json(...)to surface plain-text error bodies from the runtime instead of losing them viaraise_for_status(). - Add unit tests for search body building/parsing and for the new HTTP helper; document
search()usage in the README.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_search.py | Adds unit coverage for request-body validation/building, response parsing, and Client.search wiring. |
| tests/test_http.py | Adds unit coverage for HttpRequests.post_json behavior and error handling. |
| spicepy/_search.py | Introduces search types and request body construction/validation for /v1/search. |
| spicepy/_http.py | Adds post_json helper to POST JSON and preserve runtime error details. |
| spicepy/_client.py | Adds Client.search method that calls /v1/search and parses results. |
| spicepy/init.py | Exports SearchMatch and SearchResult at the package top level. |
| README.md | Documents Client.search usage, parameters, and returned types. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
CI ran on this branch for the first time (the workflow runs had been parked at Mine, fixed in Not mine — pre-existing on trunk: Not mine — fork secret: |
|
Correction to my previous comment: the ruff #176 is green and awaiting review. Merging it turns the |
What
Adds
Client.search(...), wrapping the runtime's/v1/searchendpoint — vector similarity search, with optional keywords for a hybrid lexical + vector ranking.Why
/v1/searchworks on a defaultspice run, but of the six client SDKs only spice.js could reach it. Python users had to hand-roll the HTTP call, including the response shape.Part of aligning capabilities across the SDKs against the runtime's own API surface.
Two details the response types encode, taken from the runtime's wire format rather than the OpenAPI example (which is out of date on the first point):
matchesis a list of values per column — one column can contribute several chunks to a single match.data,primary_key, andmetadataare omitted by the runtime when empty, so each defaults to{}rather than being required.Also adds
HttpRequests.post_json.send_requestrelies onraise_for_status, which discards the response body; the runtime reports search failures as plain text ("No data sources provided"), so that message would otherwise be lost behind a generic400 Client Error. Arguments the runtime would reject with a 400 — empty text, an emptydatasetslist, alimitbelow 1 — are validated locally so the error names the argument to fix.Verification
pytest tests/test_search.py tests/test_http.py— 58 passedpytest -m "unit or not (integration or cloud or slow)") — 401 passed, 8 failed. All 8 failures are pre-existingImportError: adbc_driver_managerintests/test_main.py(ADBC driver not installed in this environment); none are in changed code.ruff checkclean onspicepy/_search.py,spicepy/_http.py,spicepy/__init__.py,tests/test_search.py,tests/test_http.py.spicepy/_client.pyreports 2PLR0917, both pre-existing on_SpiceFlight.__init__andClient.__init__.mypy spicepy --ignore-missing-imports— success, no issues in 11 source filesmake format-check— not run. It fails on trunk today (17 files would be reformatted under the configuredline-length = 120), so the new code follows the wrapping style actually committed in the repo rather than reformatting.