Files
OmniRoute/tests/unit/cursor-model-effort-suffix-7289.test.ts
SB Yoon c130f2aa1c feat(providers): Cursor PKCE login with Bearer quota, auto router, and empty-turn errors (#9909)
5 — Cursor PKCE login com Bearer quota, auto router e empty-turn errors. Feature completa e testada (11 arquivos de teste, 133 testes focados, todos verdes).

**Validação (worktree combinado `.claude/worktrees/fix-9909`, board sobre `origin/release/v3.8.50`):**
- 3 conflitos reais resolvidos: `config/quality/eslint-suppressions.json` (aditivo), `open-sse/config/providers/registry/cursor/index.ts` (dedup de 208 entradas de catálogo, 0 IDs duplicados verificado), `open-sse/executors/cursor.ts` (imports aditivos).
- `npm run typecheck:core`: limpo.
- `check-changelog-integrity`, `check-file-size`, `check-complexity` (2615/2774), `check-cognitive-complexity` (1175/1223), `check-dead-code` (410/416): todos OK.
- `check-public-creds`: 1 entrada obsoleta pré-existente na allowlist (`copilot-m365-web.ts:330`), já presente no tip da release — não é desta PR.
- `npm run lint`: 0 errors (5 warnings pré-existentes).
- Testes focados (`cursor-agent-cli-version`, `cursor-available-models`, `cursor-catalog-combo-compat`, `cursor-errors-classify`, `cursor-login-pkce`, `cursor-model-effort-suffix-7289`, `cursor-streaming`, `cursor-token-extractor`, `cursor-token-refresh-wiring`, `cursor-usage-fetcher`, `empty-stream-no-content-8649`): 133/133 verdes.
- Corrigido durante a validação: 1 teste novo da própria PR (`cursor-model-effort-suffix-7289.test.ts`, "splits effort off legacy grok- ids") colidia com `CURSOR_MODEL_ALIASES` já mesclado na release (mapeia `grok-4.5-high` → `cursor-grok-4.5-high` antes do fallback legado rodar); ajustado para usar um id não-aliasado (`grok-3-high`) que de fato exercita o fallback — commit `68b58ed`.

Obrigado pela contribuição, @yansigit — feature robusta com boa cobertura de testes.
2026-08-21 10:28:01 -03:00

83 lines
3.2 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
import { resolveRequestedModel } from "../../open-sse/utils/cursorAgentProtobuf";
// Issue #7289: pinned Claude/GPT models carrying an effort/reasoning suffix
// (e.g. "claude-opus-4-8-high") return an empty turn from cursor's server.
//
// Ground truth captured from the real cursor-agent 2026.07.09 (Node) client
// via an http2/fetch preload hook: the wire request for a pinned model with
// an effort suffix carries the BASE model id (suffix stripped) plus a
// separate ModelParameter — "effort" for Claude models, "reasoning" for GPT
// models — not the full suffixed id crammed into model_id.
test("resolveRequestedModel splits the effort suffix off pinned Claude model ids (#7289)", () => {
assert.deepEqual(resolveRequestedModel("claude-opus-4-8-high"), {
modelId: "claude-opus-4-8",
parameters: [{ id: "effort", value: "high" }],
});
});
test("resolveRequestedModel splits the effort suffix off pinned Claude sonnet model ids (#7289)", () => {
assert.deepEqual(resolveRequestedModel("claude-sonnet-5-high"), {
modelId: "claude-sonnet-5",
parameters: [{ id: "effort", value: "high" }],
});
});
test("resolveRequestedModel splits the reasoning suffix off pinned GPT model ids (#7289)", () => {
assert.deepEqual(resolveRequestedModel("gpt-5.5-high"), {
modelId: "gpt-5.5",
parameters: [{ id: "reasoning", value: "high" }],
});
});
test("resolveRequestedModel does not touch the composer -fast toggle (#7289 regression guard)", () => {
assert.deepEqual(resolveRequestedModel("composer-2-fast"), {
modelId: "composer-2",
parameters: [{ id: "fast", value: "true" }],
});
});
test("resolveRequestedModel does not rewrite ids with no recognized effort suffix (#7289 regression guard)", () => {
assert.deepEqual(resolveRequestedModel("claude-2.5"), {
modelId: "claude-2.5",
parameters: [],
});
assert.deepEqual(resolveRequestedModel("gpt-4o"), {
modelId: "gpt-4o",
parameters: [],
});
});
test("resolveRequestedModel splits effort off cursor-grok ids (empty-turn fix)", () => {
assert.deepEqual(resolveRequestedModel("cursor-grok-4.5-high"), {
modelId: "cursor-grok-4.5",
parameters: [{ id: "effort", value: "high" }],
});
assert.deepEqual(resolveRequestedModel("cursor-grok-4.5-medium"), {
modelId: "cursor-grok-4.5",
parameters: [{ id: "effort", value: "medium" }],
});
});
test("resolveRequestedModel splits effort off legacy grok- ids", () => {
// "grok-4.5-*" combos are pre-aliased to "cursor-grok-4.5-*" by
// CURSOR_MODEL_ALIASES (already shipped on the release tip), so this uses
// an unaliased grok version to actually exercise the bare "grok-" fallback
// in resolveGrokRequestedModel rather than the alias table's rewrite.
assert.deepEqual(resolveRequestedModel("grok-3-high"), {
modelId: "grok-3",
parameters: [{ id: "effort", value: "high" }],
});
});
test("resolveRequestedModel splits cursor-grok effort + fast together", () => {
assert.deepEqual(resolveRequestedModel("cursor-grok-4.5-high-fast"), {
modelId: "cursor-grok-4.5",
parameters: [
{ id: "effort", value: "high" },
{ id: "fast", value: "true" },
],
});
});