All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog and this project follows Semantic Versioning.
[0.2.0] - 11.06.2026
Added
:timeoutoption forKagi.summarize/1..3, the total request timeout in milliseconds. Precedence: per-call:timeout, then the client'sreq_options[:receive_timeout], then the summarizer default of 60 seconds.req0.6 support: the requirement is now~> 0.5 or ~> 0.6, andcloaked_req0.4.2 carries the matching adapter support.:invalid_session_tokenerror reason: tokens with characters that cannot appear in a cookie value (a pastedCookieheader, for example) are rejected before any request instead of being sent raw.
Fixed
inspect(%Kagi.Client{})no longer prints the session token; the field is redacted from the derivedInspectimplementation.- Search results keep Kagi's ranking: grouped and standard rows are parsed in
one document-order pass, so
:limitno longer drops grouped results that Kagi ranks near the top. - Search queries that are not strings or lists of strings (charlists, keyword
lists) return
:invalid_optioninstead of being mangled or raising. CloakedReqadapter options (:impersonate,:cookie_jar, ...) passed via:req_optionsno longer raiseArgumentError; the adapter is attached before the configured options are merged.- Maps results with drifting scalar types (numeric
price, stringrating, ...) normalize tonilinstead of crashingsort: :pricewith aFunctionClauseError; integer ratings and distances convert to floats. - Maps
:limitis validated before the HTTP request, matching search, so an invalid value no longer burns an authenticated request. - A
poisvalue that is not an array of objects returns a descriptive:parse_errorinstead of raising. - Maps and search parse errors no longer embed whole response payloads in the error message; inspected values are bounded.
- Maps queries that are not strings or lists of strings (charlists, keyword
lists) return
:invalid_optioninstead of being mangled or raising.
Changed
- Challenge detection runs only when a page has no recognizable results and no longer downcases the whole HTML body on the happy path.
- Requests no longer follow redirects, so the session cookie cannot travel to
another host. Re-enable with
redirect: truein:req_options. The endpoint URL and method are pinned after configuration merging, so:req_optionscan never point a request at another host. - Requests no longer retry transient HTTP errors behind the caller's back; a
429 returns
:rate_limitedafter a single attempt. Re-enable withretry: :safe_transientin:req_options. - Transport failures now include the adapter's failure reason (timeout, DNS,
TLS, ...) in the
:request_failederror message. - Summarizer requests default to a 60-second timeout instead of inheriting the adapter's 15-second total request timeout, which failed long summaries.
- Summarizer-reported failures (
"state": "error"payloads and empty summaries) return the new:summarizer_errorreason instead of:parse_error, so callers can tell an unfetchable URL from a client parsing bug. Code matching on:parse_errorfor these cases must be updated.
[0.1.1] - 23.05.2026
Changed
- Update
cloaked_reqto~> 0.4.0, which runs native HTTP requests on the shared Tokio runtime, aborts in-flight requests when the caller exits, and honours Reqconnect_optionsfor proxy configuration.
[0.1.0] - 17.05.2026
Added
- Typed
Kagi.search/2,Kagi.search/3,Kagi.summarize/2, andKagi.summarize/3APIs. - Typed
Kagi.maps/2andKagi.maps/3API with%Kagi.Maps{},%Kagi.MapsResult{}, and%Kagi.MapsResult.Coordinates{}structs. - Client-side maps sorting by
:relevance,:rating,:distance, or:pricewith sensible default orders. - Reusable
%Kagi.Client{}with configurable session token resolution. Reqtransport by default and explicitCloakedReqtransport support.- Search, summarizer, and maps parsers ported from the Rust
kagiCLI. - Release, CI, and package documentation matching the companion Elixir libraries.