feat(rankings): expose provider reliability alongside free provider rankings - #10909
Merged
diegosouzapw merged 1 commit intoAug 21, 2026
Conversation
maxmad64bis
force-pushed
the
feat/free-provider-rankings-reliability
branch
2 times, most recently
from
August 20, 2026 23:44
f0d1277 to
a56b9ff
Compare
…ankings `computeFreeProviderRankings` already loads connection state for the configured/available filters (diegosouzapw#6150) but only used it to drop rows. Attach that same snapshot to each surviving ranking as an additive `reliability` field: raw per-connection `testStatus`/`rateLimitedUntil` plus the state they imply. No extra query, no change to the sort or the scores. States reuse `ProviderHealthState` from providerHealthMatrix (type-only import) with the same split `classifyAccount` applies, and `isProviderUsable` now sits on the shared classifier so the filter and the reported state cannot drift. Validation: 19/19 in freeProviderRankings-filters.test.ts, lint, typecheck:core, check:cycles, changelog-integrity.
maxmad64bis
force-pushed
the
feat/free-provider-rankings-reliability
branch
from
August 20, 2026 23:49
a56b9ff to
2f25e0f
Compare
5 tasks done
diegosouzapw
pushed a commit
that referenced
this pull request
Aug 21, 2026
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
…ankings (diegosouzapw#10909) Validado no worktree combinado: typecheck:core, changelog-integrity, complexity, cognitive-complexity, file-size, lint e testes focados (freeProviderRankings-filters) todos verdes. Feature aditiva bem documentada (campo reliability nos rankings). CI vermelho é o base-red já rastreado em diegosouzapw#9985. Obrigado!
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
…zapw#10926) Validado no worktree combinado: mesmos gates + testes focados verdes. Extensão opt-in bem desenhada sobre diegosouzapw#10909 (dimensão de uso real via call_logs). CI vermelho é o base-red já rastreado em diegosouzapw#9985.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
src/lib/freeProviderRankings.tsranks free providers by ELO score only. It already loads connection state (getProviderConnections) but uses it to filter, never to qualify — a provider the operator cannot use right now still ranks first, with nothing in the payload saying so.This PR exposes a second, additive dimension: each ranking gets a
reliabilityfield carrying the raw per-connection signals (testStatus,rateLimitedUntil) and the state they imply. The sort and the scores are untouched.Two constraints shape the field.
It reuses the project's health vocabulary rather than inventing one.
reliability.stateis aProviderHealthState— thehealthy | degraded | downtype already defined insrc/lib/monitoring/providerHealthMatrix.ts— with the same split that module applies: a terminaltestStatusisdown, a live cooldown isdegraded. The provider-level aggregate mirrorsclassifyProvider(all connections down ⇒down, any non-healthy ⇒degraded) minus its circuit-breaker input, which this code path does not load. The import is type-only, so nothing is pulled in at runtime. A boolean flag here would have meant the same word describing two different things in two APIs of the same product.It exposes the raw signal next to the state, never instead of it.
testStatusis written on failure paths at request time (open-sse/handlers/chatCore.tsmarksexpired,banned,deactivated,unavailable,credits_exhausted) and is reset toactiveonly by an explicit connection test or a re-auth — so it can outlive the actual recovery. Consumers get the stored value verbatim plus the datedrateLimitedUntil, and can disagree with the state if they have better information.No extra query: the field is attached to the connection snapshot the filters already load, so it exists when
configuredOnlyoravailableOnlyis set and is absent otherwise.Related Issues
Validation
npm run lint3d7ed7aa8and has not been merged forward. Six commits have landed onrelease/v3.8.50since (142ae9349..eb6f31971); none touchessrc/lib/freeProviderRankings.ts,src/lib/monitoring/providerHealthMatrix.tsor this PR's changelog fragment, and the branch merges cleanly.git merge-treereports no conflict against the current tip; the branch can be merged forward on request before review.Tests Added Or Updated
tests/unit/freeProviderRankings-filters.test.ts— eight cases forattachProviderReliability: healthy connections, a terminal status classifieddown(notdegraded), a futurerateLimitedUntildegrading while a past one does not, a mixed provider (one down + one healthy) aggregating todegraded, an all-down provider aggregating todown, rawtestStatusreturned verbatim including its original casing, providers without a connection getting no field, and inputs never mutated.Run:
node --import tsx/esm --test tests/unit/freeProviderRankings-filters.test.tsAlso run on the branch:
npm run typecheck:core(clean),npm run lint(clean),npm run check:cycles(no cycles).Coverage Notes
The new pure functions are covered by the cases above, against the same
FIXED_NOWsnapshot the filter tests use.isProviderUsableis now expressed in terms of the same per-connection classifier, so the filter and the reported state cannot drift apart; its existing tests cover that refactor unchanged. The wiring incomputeFreeProviderRankingsis one line inside the existing filter block, on the already-loaded snapshot. No mocks, no DB.Reviewer Notes
availableOnly, worth knowing when reading the payload: that filter already drops every provider without a healthy connection, so under itstatecan only behealthyordegraded(a partially rate-limited multi-connection provider) — neverdown.downis reachable withconfiguredOnlyalone.