Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .changeset/orchestrator-hardening.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
"@refkit/core": minor
"@refkit/mcp": minor
---

Harden the search orchestrator: per-provider soft timeout (default 10s) and
bounded retry on 429/5xx/network errors (default 1, exponential backoff) — on by
default, tunable or disabled via `createRefkit({ resilience })`. Provider
statuses in `searchWithMeta` now carry `latencyMs`, and supplying a `cache`
(`KeyValueCache`) now memoizes per-provider results (key
`refkit:v1:<provider>:<queryHash>`, TTL via the new `cacheTtlMs` option, default
5 min) with hits flagged `cached: true`. Merge, rerank, and the license gate
always run fresh. New exports: `withTimeout`, `retryingFetch`, and the
`ResilienceOptions`, `TimeoutHandle`, `RetryOptions` types.

The MCP `search_references` structured output (`explain: true`) now surfaces
`latencyMs` per provider and `cached` on cache hits.
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const refkit = createRefkit({
met(), // keyless
unsplash({ accessKey: process.env.UNSPLASH_KEY! }), // BYOK
],
// fetch defaults to globalThis.fetch — inject your own to add caching/retries
// fetch defaults to globalThis.fetch — timeouts/retries/caching are built in (see below)
})

// Fan out, merge (Reciprocal Rank Fusion) + dedup; every result carries rights.
Expand Down Expand Up @@ -149,6 +149,21 @@ const refkit = createRefkit({
})
```

## Resilience & caching

Fan-out is hardened by default: each provider gets a **soft 10s timeout** and **one retry** (429/5xx/network errors, exponential backoff). A slow or hanging source is reported in `meta.providers` as `failed` with `timeout after Nms` — the search still returns everyone else. Tune or disable per client:

```ts
createRefkit({ providers, resilience: { timeoutMs: 4000, retries: 2 } })
createRefkit({ providers, resilience: false }) // raw fan-out, no timeout/retry
```

Pass a `cache` to memoize **per-provider** results (keyed by provider + normalized query, TTL `cacheTtlMs`, default 5 min). Merging, reranking, and the license gate always run fresh; cache hits are flagged `cached: true` in `meta.providers`, and every provider status carries `latencyMs`:

```ts
createRefkit({ providers, cache: myKvCache, cacheTtlMs: 60_000 })
```

## Providers

| Package | Source | Modality | Auth | License |
Expand Down
Loading
Loading