Skip to content

feat(search): add the Serply direct provider - #29

Open
googio wants to merge 1 commit into
tinyhumansai:mainfrom
googio:feat/serply-search
Open

googio wants to merge 1 commit into
tinyhumansai:mainfrom
googio:feat/serply-search

Conversation

@googio

@googio googio commented Oct 15, 2026

Copy link
Copy Markdown

Summary

I work with Serply. This adds Serply as a keyed direct provider with one tool, serply_search, for the search role. It calls GET https://api.serply.io/v1/search with the user's own key in X-Api-Key and maps the organic results (title, link, description) onto the normalized result fields. Search sends query, max_results (1-20, defaulting to the configured count; Serply returns at most 10 per request, so num is capped at 10) and an optional two-letter country, forwarded as gl. Rows without a link are dropped before the list is trimmed to the requested count.

Related issue

None

API or behavior changes

Additive, not breaking. PROVIDERS and KEYED_DIRECT_PROVIDERS gain serply. It is listed only on the direct route with a credential, like Tavily and Seltz, and serves the search role, after Keenable and before Gemini in the default order. A rejected key maps to Error::Unauthorized(401), so the search role falls back as it does for the other keyed providers. Nothing changes for existing providers or configurations. I left CONTRACT_VERSION at 2.2; tell me if a new provider should bump it.

Validation

Commands actually run, with their outcome:

  • cargo fmt --all -- --check: clean
  • cargo clippy --all-targets --all-features -- -D warnings: clean
  • cargo build --all-targets --all-features: ok
  • cargo test --all-features: 163 passed in tinysearch (160 before, plus 3 new) and 52 passed in tinysearch-bus, 0 failed

cargo llvm-cov per file: serply.rs 100%, catalog/mod.rs 98.9%, roles.rs 100%, labels/mod.rs 100%, direct/mod.rs 97.8%, provider/mod.rs 94.8%, all above the 90% gate. RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features is clean.

A live run with a real key, through SearchService::with_builtins with only serply configured on the direct route, for "rust async runtime" with max_results 4:

tools ["web_search_tool"]
role Some(Search) provider serply status Ok
search https://corrode.dev/blog/async/ | The State of Async Rust: Runtimes | corrode Rust Consulting | 139
search https://rust-lang.github.io/async-book/08_ecosystem/00_chapter.html | The Async Ecosystem - Asynchronous Programming in Rust | 138
search https://www.reddit.com/r/rust/comments/16p47f1/the_state_of_async_rust_runtimes/ | The State of Async Rust: Runtimes : r/rust - Reddit | 146
search https://medium.com/@bartekwinter3/build-an-async-runtime-in-rust-part-1-hooch-d43e3d96c3e6 | (title omitted) | 118

(Search lines are URL, title and snippet length.) The same run with a bad key returns serply rejected the configured API key (HTTP 401).

Tests

Three tests in provider/direct/serply/serply_tests.rs, two against a local server:

  • search: request line (q, num, gl), the X-Api-Key header, title/URL/snippet mapping, a result without a link dropped, the list trimmed to max_results
  • a 401 becomes Error::Unauthorized(401)
  • num capped at 10, a blank query and an unknown tool rejected

catalog/mod_tests.rs now also pins serply in the catalog, the keyed provider list, its role, its role tool, the default search order and credential-based availability. labels/mod_tests.rs covers the display name.

Documentation

README.md: Serply added to the role table, plus a paragraph under Built-in providers. Docs for the API: https://serply.io/docs

Once this lands, I'd follow up in OpenHuman with a serply entry in the search settings (an API key field), if you want it there.

Checklist

  • The change is focused on one logical change
  • No new #[allow(...)], #[ignore], or relaxed lints
  • No secrets, tokens, or .env contents in the diff or the description

@tinysweeper

tinysweeper Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Tiny Sweeper review

Tiny Sweeper reviewed this change across 5 lane(s) and found 0 active actionable finding(s). Detailed lane evidence and any incomplete work are listed below.

State: Incomplete
Priority: none
Reviewed head: 3408488769f2
Updated: 2026-10-15T17:06:57Z

Review snapshot

Change surface Files Review signal Count
Production 6 Active findings 0
Tests 3 Noted findings 0
Documentation 1 Resolved findings 0
Configuration 0 Pending checks/questions 1

Completeness: Incomplete
Test assessment: No supported feature-to-test mapping was available; this does not mean tests are absent or passed.

Features

None identified with supported citations.

Tests

No supported feature-to-test mapping was produced. Test execution is not inferred.

Findings

No active actionable findings.

Could not review: README.md

Before merge

  • Complete the critique review for README.md.

How this fits together

flowchart LR
  n0["direct_provider_specs<br/>changed"]:::changed
  n1["catalog_and_selection_are_stable<br/>changed"]:::changed
  n2["...ols_require_a_nonempty_private_credential<br/>changed"]:::changed
  n3["provider_tool_specs"]:::impacted
  n4["configured_provider_tools"]:::impacted
  n5["default"]:::impacted
  n6["keyed"]:::impacted
  n7["parallel_is_direct_only"]:::impacted
  n1 -->|calls| n3
  n1 -->|tests| n3
  n1 -->|calls| n5
  n1 -->|tests| n5
  n2 -->|calls| n3
  n2 -->|tests| n3
  n2 -->|calls| n4
  n2 -->|tests| n4
  n2 -->|calls| n5
  n2 -->|tests| n5
  n2 -->|calls| n6
  n2 -->|tests| n6
  n3 -->|calls| n0
  n6 -->|calls| n5
  n7 -->|calls| n3
  n7 -->|tests| n3
  n7 -->|calls| n4
  n7 -->|tests| n4
  n7 -->|calls| n5
  n7 -->|tests| n5
  n7 -->|calls| n6
  n7 -->|tests| n6
  classDef changed fill:#0d4429,stroke:#238636,color:#e6edf3
  classDef impacted fill:#161b22,stroke:#6e7681,color:#c9d1d9
  classDef flagged fill:#5a1e02,stroke:#d93f0b,color:#ffffff
  classDef blocking fill:#67060c,stroke:#f85149,color:#ffffff
Loading
Agent review details

critique

  • Conclusion: Success
  • Scope reviewed: incomplete; unanswered: README.md
  • Lane summary: Reviewed 9 files; 0 findings. 1 file could not be reviewed: README.md.

security

  • Conclusion: Success
  • Scope reviewed: all assigned evidence
  • Lane summary: Reviewed 9 files; 0 findings. 1 file was not security-reviewed: README.md (prose or tabular data).

tests

  • Conclusion: Success
  • Scope reviewed: all assigned evidence
  • Lane summary:

commits

  • Conclusion: Neutral
  • Scope reviewed: all assigned evidence
  • Lane summary: Nothing sensitive found in what this pull request commits.

description

  • Conclusion: Success
  • Scope reviewed: all assigned evidence
  • Lane summary: The PR description says Serply is added as a keyed direct provider: catalog entries (PROVIDERS, KEYED_DIRECT_PROVIDERS, roles, tool spec, default order), the serply.rs prepare/unwrap mapping, wiring into direct/mod.rs and provider/mod.rs, plus labels and tests. The diff matches all of that, and the claims I could check against shown code line up: the tool name `serply_search`, the `X-Api-Key` header, `q`/`num`/`gl` params, `num` capped at 10 via `count(...).min(MAX_PAGE)`, rows without `link` dropped, trimming to `max_results`, and 401 → `Error::Unauthorized` (asserted in the test against the real `run` path). The description asks about bumping `CONTRACT_VERSION` — left at 2.2 — which is the author's open question, not a defect I can substantiate from the diff. Repo rules appear respected: no inline `#[cfg(test)] mod tests` (test file declared with `#[cfg(test)] #[path = ...]` matching the existing pattern), tests live in `serply_tests.rs`, the bus crate only gains pure catalog/label data, provider HTTP stays in `crates/tinysearch`, and no credentials or lint exemptions appear in the diff. No findings.
Evidence and run details
  • Models: ladder/vectors-oai3, glm-5.3-flash
  • Spend: $0.002318
  • Tokens: 230151 input · 5572 output · 0 cached · 606 embedding
Head State Pass summary
3408488769f2 incomplete 0 active finding(s), 0 resolved finding(s) (at 2026-10-15T17:06:57Z)

tinysweeper 0.1.2

@coderabbitai

coderabbitai Bot commented Oct 15, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 0a84c617-77e9-430d-9ec8-654e25199ff9
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@tinysweeper tinysweeper Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tinysweeper found nothing blocking, but could not review everything, so this is not an approval: README.md.

             $0.0023 · 230,151 in / 5,572 out · 0 cached (0%) · ladder/vectors-oai3, glm-5.3-flash · 606 embedded
critique:    $0.0011 · 113,905 in / 1,288 out · 0 cached (0%) · glm-5.3-flash
security:    $0.0006 · 67,281 in  / 722 out   · 0 cached (0%) · glm-5.3-flash
tests:       $0.0002 · 17,693 in  / 11 out    · 0 cached (0%) · glm-5.3-flash
description: $0.0002 · 23,619 in  / 978 out   · 0 cached (0%) · glm-5.3-flash

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant