Skip to content

feat: tryChain + createHealthTracker — walk the chain, know when it's down - #18

Merged
catomean merged 1 commit into
mainfrom
feat/health-chain-attempt
Aug 29, 2026
Merged

feat: tryChain + createHealthTracker — walk the chain, know when it's down#18
catomean merged 1 commit into
mainfrom
feat/health-chain-attempt

Conversation

@catomean

Copy link
Copy Markdown
Collaborator

Summary

  • tryChain() walks a Link[] in order and returns the first success, throwing ChainExhaustedError (naming every link's failure) when all fail — closes the gap between "here's an ordered list" and an actual fallback nobody hand-rolls the same way twice. No HTTP client added: attempt() is supplied by the caller.
  • createHealthTracker() is a small state machine (unknown → ok/degraded/down) as a factory, not a global — a consumer gets the old singleton behaviour for free (export const llmHealth = createHealthTracker()), and it's independently testable.
  • Extracted from botsmann's lib/llm-health.ts + generateWithBestProvider, built this week fixing a real outage: a dead key answered a friendly 200 and /health reported "healthy" because it only checked the database. This generalizes the fix so it doesn't stay a one-repo patch.
  • Fixes stale catomean/* org refs in README.md/package.json left over from the bitbaum rename.
  • Version 0.4.0 → 0.5.0 (additive, non-breaking).

Test plan

  • npm run verify green locally (lint + typecheck + build + 64 tests, 15 new)
  • CI green on this PR

… down

The chain and catalog modules already answer WHICH model to call and
whether the vendor still lists it. What every hand-rolled adopter still
had to build itself, differently, was the loop that actually walks the
chain on failure, and a record of whether the whole thing came back
empty — the gap a real outage fell through on 2026-08-28: an app's only
key died, the chat routes caught it and answered a friendly 200, and
/health reported healthy because it only ever checked the database.

tryChain() tries each link in order and returns the first success,
throwing ChainExhaustedError (naming every link's failure, not just the
last) when none work. It ships no HTTP client, same as the rest of this
package — attempt() is supplied by the caller and makes the real
request; this only decides which link goes next.

createHealthTracker() is a factory rather than a module-level global, so
a consumer gets old-style shared-process state for free by creating
exactly one, and tests never fight over shared state. Health only
records once per whole chain walk: a success on link two is a success,
not a "degraded" report on the fallback working as designed.

Version 0.4.0 -> 0.5.0. Also fixes stale catomean/* org references in
README and package.json left over from the bitbaum rename.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@catomean
catomean merged commit de7319a into main Aug 29, 2026
1 check passed
@catomean
catomean deleted the feat/health-chain-attempt branch August 29, 2026 07:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant