fix(hyperagent): default 1M context for fable/opus/sonnet (#8496)

* fix(hyperagent): default 1M context for fable/opus/sonnet

HyperAgent Claude-family models (fable, opus, sonnet) were falling through
getTokenLimit to the generic 128k default. Agentic tool-loop prompts with
large catalogs then failed with context_length_exceeded (~137k tokens).

- defaultContextLength + per-model contextLength = 1_000_000 on hyperagent registry
- DEFAULT_LIMITS.hyperagent / ha = 1M
- Resolve hyperagent/ha (and fable/opus wire ids) before models.dev DB fallback

Verified: getTokenLimit('hyperagent','fable-latest') === 1000000; context-manager tests 30/30.

* fix(sse): scope hyperagent 1M context fix to the registry, drop unscoped model-name match

The step-1b branch in resolveTokenLimit() matched fable/opus/sonnet model
name substrings for ANY provider, before the models.dev DB lookup. That
collided with anthropic/claude, kiro, windsurf and bluesminds registries,
which serve the same Claude model ids (e.g. claude-opus-4.7-max,
claude-sonnet-5) with their own accurate per-model contextLength — those
were being clobbered to 1M instead of their real (often 200k) limit.

The registry-level defaultContextLength added on the hyperagent provider
entry already fixes the reported bug (getTokenLimit('hyperagent', ...) ===
1_000_000) on its own, scoped correctly by provider. Remove the redundant,
unscoped substring branch and add regression coverage for every hyperagent
fallback model id plus the cross-provider collision.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
This commit is contained in:
NOXX - Commiter
2026-07-26 09:53:06 +03:00
committed by GitHub
parent fae10668ba
commit 2d48bb6dca
4 changed files with 69 additions and 9 deletions

View File

@@ -34,6 +34,39 @@ test("getTokenLimit: default fallback", () => {
assert.equal(getTokenLimit("unknown"), 128000);
});
// Regression for #8496: hyperagent Claude-family agents (fable/opus/sonnet) must
// resolve to the 1M context window for every fallback model id, driven solely by
// the registry's `defaultContextLength` (open-sse/config/providers/registry/hyperagent) —
// not by a provider-unscoped model-name substring match, which previously collided
// with unrelated providers serving the same Claude model ids (see
// "getTokenLimit: does not force 1M onto non-hyperagent providers" below).
const HYPERAGENT_FALLBACK_MODEL_IDS = [
"fable-latest",
"claude-fable-5",
"opus-latest",
"claude-opus-4-8",
"sonnet-latest",
"claude-sonnet-5",
];
for (const modelId of HYPERAGENT_FALLBACK_MODEL_IDS) {
test(`getTokenLimit: hyperagent/${modelId} resolves to 1M context`, () => {
assert.equal(getTokenLimit("hyperagent", modelId), 1_000_000);
});
test(`getTokenLimit: ha (alias)/${modelId} resolves to 1M context`, () => {
assert.equal(getTokenLimit("ha", modelId), 1_000_000);
});
}
test("getTokenLimit: does not force 1M onto non-hyperagent providers serving the same model ids", () => {
// windsurf declares an explicit per-model contextLength of 200000 for this exact id —
// a provider-unscoped substring match on "claude-opus-4" would have clobbered it to 1M.
assert.equal(getTokenLimit("windsurf", "claude-opus-4.7-max"), 200000);
// bluesminds likewise pins its own claude-opus-4-5 entry to 200000.
assert.equal(getTokenLimit("bluesminds", "claude-opus-4-5"), 200000);
});
// ─── compressContext ────────────────────────────────────────────────────────
test("compressContext: returns unchanged if fits", () => {