Commit Graph

87 Commits

Author SHA1 Message Date
Daniil Schovkunov
87e5c1c6dd feat(combo): add Fusion strategy — parallel panel + judge synthesis
Adds Fusion as a third combo strategy alongside fallback/round-robin. A
fusion combo fans the prompt out to all member models in parallel, then a
configurable judge model synthesizes one final answer from the panel.

- handleFusionChat in open-sse/services/combo.js: quorum-grace collection
  caps the straggler penalty, anonymized sources prevent judge brand-bias,
  degrades to a direct answer on single survivor and 503 on total failure.
- chat.js dispatches strategy==="fusion" at both combo entry points.
- Combos dashboard: per-combo strategy Select replaces the round-robin
  toggle, fusion reveals a judge picker, plus a strategy/capacity explainer.
- tests/unit/combo-fusion.test.js covers fan-out, judge routing/default,
  quorum-grace straggler drop, single-survivor and total-failure degradation.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-17 10:34:27 +07:00
thienpv
706e6513c9 feat(kiro): headless API-key auth + direct Claude/Kiro route
Adds long-lived API-key (ksk_) authentication for Kiro/AWS CodeWhisperer
and a direct claude:kiro / kiro:claude translation route that avoids the
lossy OpenAI two-hop pivot.

- translator: claude-to-kiro request + kiro-to-claude response translators,
  registered on the exact source:target pair (direct route ahead of the
  OpenAI pivot in index.js). claude-to-kiro uses shared schema constants
  (ROLE/CLAUDE_BLOCK/DEFAULT_IMAGE_MIME) per app convention.
- auth: POST /api/oauth/kiro/api-key imports + validates a key via
  ListAvailableProfiles, persists authMethod="api_key" (no refresh token).
- executor: send tokentype: API_KEY header and try *.amazonaws.com hosts
  first for api-key creds; OAuth keeps kiro.dev first.
- fix: never inject the default placeholder profileArn for api-key auth
  (CodeWhisperer 403s an ARN not owned by the key's account).
- ui: API Key method in the Kiro connect modal; surface api-key accounts
  on the Quota Tracker and provider count.
- stream: env-overridable TTFT vs stall timeouts + Kiro keepalive frame.
- tests: claude-kiro-direct + kiro-profile-arn (11 tests).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-17 10:01:30 +07:00
Khanh Le
db9ec3af61 fix(antigravity): strip optional from tool schemas before Gemini
Closes #1537, #1841

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-17 09:46:41 +07:00
decolua
b282f05549 Refactor 2026-06-15 18:18:04 +07:00
decolua
8ab5af0052 test(real): add capability survey (vision/audio) over all DB creds
Probes every chat model of every active provider with an image/audio content
block and classifies the outcome against declared capabilities. Surfaces models
where non-vision/non-audio models 400 on modality input (auto-strip candidates)
and where capability data is stale. Survey-only: logs a grouped table, never
fails on capability outcomes (cred/account noise filtered via status + message).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-15 12:08:05 +07:00
decolua
aba4c45da6 fix(translator): ESM-safe registry + tool-id pairing + responses max_tokens; add real-creds tests
- translator/index.js: replace require() with static side-effect imports (ESM-safe),
  lazy-init registry maps to survive circular import order
- openai-responses->openai: map max_output_tokens -> max_tokens (avoid leaking field upstream)
- gemini/antigravity -> openai: derive deterministic tool_call id from name so
  functionCall/functionResponse pair correctly (fixes provider tool-pairing 400s)
- add offline unit tests (finish-reason, usage, session-manager, ollama malformed args, const guard)
- add real-creds integration tests (provider-cases + all-formats matrix: 6 inbound formats x 4 scenarios)

Includes co-located provider registry refactor (pricing/capabilities/media providers) and sessionManager updates.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-15 11:38:43 +07:00
decolua
24a2d19bd7 refactor(app): RISKY pass R1-R3 — config-driven modal, cursor frame dedup, chunk helper
R1: merge AddOpenAICompatibleModal + AddAnthropicCompatibleModal → AddCompatibleModal (variant config-driven, ~180 dup removed, preserves per-variant useEffect behavior)
R3: extract readCursorFrame() helper — dedup protobuf frame header/decompress loop (JSON+SSE transforms, byte-identical)
R2: add chatChunkSse() helper, wire 7 cursor SSE scaffolds (byte-identical, cursor golden pass)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 21:54:35 +07:00
decolua
fbf973f2e7 refactor(app): DRY pass — split large files, extract shared utils
S1: delete page.new.js (1724L abandoned) + remove dead getAntigravityProjectId
S2: split large files by natural seams
  - usage.js → usage/{github,google,claude,codex,kiro,minimax,misc,shared}.js
  - media-providers page → components/{Embedding,Tts,Generic,Stt}ExampleCard.js
  - EndpointPageClient → endpointConstants.js + endpointPing.js + components/
  - tokenRefresh.js → tokenRefresh/{dedup,providers}.js
  - ProviderLimits/index.js: 16 pure fn + 9 constants → utils.js
  - oauth/providers.js: 7 pure helpers → providerHelpers.js
S3: shared utils
  - getModelKind(m, fallback) → shared/constants/models.js (replaces 20× m.kind||m.type)
  - getStatusVariant → shared/utils/connectionStatus.js (dedup ConnectionRow/ConnectionsCard)
  - sseChunk → open-sse/utils/sse.js (dedup grok-web/perplexity-web)
  - fetchWithTimeout → usage/shared.js (replace 4× AbortController pattern in google.js)
fix: enableObservability2 field name in requestDetailsRepo
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 19:31:09 +07:00
decolua
d3f61aac2f refactor(open-sse): translator DRY + schema enums, bug fixes, dead code cleanup
- Bug B1-B7: media UI m.kind||m.type, serviceKinds, gemini mediaPriority, schema kind, models/info lookup by kind
- Dead code D1-D6: safeParseJSON, drop PROVIDER_ENDPOINTS, orphan fetcher, GITHUB_CONFIG derive, getProviderConfig internal, legacy kiro file
- Translator concerns: toOpenAIUsage, toOpenAIFinish (gemini/kiro/ollama + fix kiro tool finish), thinking effort maps
- Reorg helpers/ → concerns/ (logic) + formats/ (per-format) + schema/ (pure enums: roles/blocks/finishReasons/defaults)
- Wire ~280 hardcoded role/block/finish/default literals to schema enums across 20+ files
- collapseTextParts + extractTextContent dedup
- Normalize translator fn names to openaiToXRequest / xToOpenAIResponse
- Golden tests lock behavior; 0 regression (byte-for-byte providers/alias, 26=26 known fails)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 18:49:38 +07:00
decolua
bb9e9aa91f refactor(open-sse): registry consolidation + DRY media/oauth/adhoc cleanup
- Single-source registry: oauth clientId/tokenUrl, usage URLs, image/embed
  configs, search defaultModel, codex fixedPort, google token url derive.
- Remove 29 unused OmniRoute providers (registry 100→71); media intact.
- De-adhoc: codex literals → registry format/oauth flags; reasoningInject,
  image/embed openrouter headers + xai bodyFields config-driven.
- Add REGISTRY_TEMPLATE.js + expand PROVIDER_DEFAULTS/schema JSDoc.
- Baselines updated; PROVIDERS 62 + alias 90 byte-for-byte, golden snapshots.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 13:15:48 +07:00
decolua
4da1d6dad4 refactor(open-sse): D1c — forceStream hardcode → PROVIDERS schema (#5)
chatCore providerRequiresStreaming: switch provider-name →
PROVIDERS[provider].forceStream. Thêm forceStream:true vào registry
openai/codex/commandcode. verify-providers allowlist added-fields
(forceStream/urlSuffix verified bằng golden + runtime test riêng).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 22:05:01 +07:00
decolua
72ce515709 refactor(open-sse): dedupe Google OAuth client credentials (#4)
clientId/clientSecret của antigravity + gemini bị lặp 3 nơi
(registry, usage.js, src/lib/oauth). Gom vào shared.js
(ANTIGRAVITY_OAUTH_CLIENT, GOOGLE_OAUTH_CLIENT), các file spread vào.
Byte-for-byte: PROVIDERS/alias/oauth-url equal, golden 142 pass.
Thêm test guard nội dung + alias resolution.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 21:53:14 +07:00
decolua
d4b95380b1 refactor(open-sse): usage.js dispatcher switch → USAGE_HANDLERS registry
Gộp switch 13 nhánh getUsageForProvider thành 1 registry object
(provider → handler), mỗi handler giữ nguyên signature/args qua ctx.
Behavior giữ nguyên (ollama vẫn chỉ nhận accessToken như cũ).
Thêm tests/unit/usage-dispatch.test.js guard dispatch.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 21:46:13 +07:00
decolua
0a8d92a6ba refactor(open-sse): #8 unify token refresh dispatch — 2 switch → 1 registry
- REFRESH_HANDLERS map (provider → handler) replaces two parallel switch blocks
- getAccessToken keeps gemini→Google + null default; refreshTokenByProvider keeps
  generic refreshAccessToken default (gemini intentionally not special-cased)
- Add token-refresh-dispatch.test.js guarding null-guards + defaults
- Existing xai/codex refresh tests still pass

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 21:32:52 +07:00
decolua
5a042840fd refactor(open-sse): P3 provider registry — split into providers/registry/{id}.js
- 100 registry files: transport + models co-located per provider (Mongoose-style)
- providers/shared.js: shared Claude headers + OS/arch helpers (deduped)
- providers/models/helpers.js: withCodexReviewModels (kept dynamic)
- providers/index.js builds PROVIDERS + PROVIDER_MODELS = old API (content byte-for-byte)
- config/providers.js + providerModels.js → barrel re-export, keep accessors + runtime helpers
- Verified: PROVIDERS/MODELS/OAuth/alias byte-for-byte, golden translator tests pass, 0 new regression

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 21:08:37 +07:00
decolua
7134dd71db refactor(open-sse): P2 alias single-source — derive OAuth alias→id from OAUTH_ALIASES
- Export OAUTH_ALIASES as canonical id→alias source
- model.js derives 16 OAuth alias→id pairs instead of hardcoding (mmf kept out to preserve behavior)
- Add verify-alias.mjs byte-for-byte guard (133 tokens), all equal

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 20:48:11 +07:00
decolua
1432ac61d7 fix(open-sse): remove dead duplicate opencode provider entry
Two `opencode` keys existed; the first (localhost:4096) was silently overridden
by the later one (opencode.ai, noAuth). Drop the dead entry. Resolved PROVIDERS
output unchanged (verified byte-for-byte).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 20:41:41 +07:00
decolua
bb597cbced refactor(open-sse): source mimo-free/opencode base URL from PROVIDERS
CHAT_URL and opencode buildUrl base now read from PROVIDERS instead of repeating
the literal. Values identical; providers byte-for-byte + gate clean.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 20:40:43 +07:00
decolua
64182c0484 refactor(open-sse): merge beta-url case + single-source refresh URLs (D)
buildUrl: fold kimi-coding into the shared ?beta=true case. refreshCline/
refreshKimiCoding now read URL (and kimi-coding clientId) from PROVIDERS instead
of hardcoded strings. Extend verify-oauth-urls with refresh/clientId snapshot;
URLs byte-for-byte equal, golden + gate clean.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 20:33:38 +07:00
decolua
22f6c42738 refactor(open-sse): single-source OAuth token URLs via PROVIDERS (C2)
OAUTH_ENDPOINTS.{openai,anthropic,iflow}.token now reference PROVIDERS.*.tokenUrl
(values identical) so each backend token URL is declared once. qwen left as-is
(its appConstants/PROVIDERS values intentionally differ). Add verify-oauth-urls
script; URLs byte-for-byte equal, gate clean.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 20:22:36 +07:00
decolua
6597b81e5e refactor(open-sse): add reasoningDelta helper, dedup thinking deltas (B4)
Centralize the reasoning_content delta shape (optional assistant role) used by
claude/gemini/kiro/codex/commandcode response translators. Keeps the cross-format
convention consistent for future translators. Output byte-for-byte identical;
golden + gate clean. Ollama left as-is (mutates existing delta object).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 18:21:46 +07:00
decolua
997860aa1f refactor(open-sse): dedup fallback tool_call id helper (B3)
Add fallbackToolCallId() and apply to kiro/ollama/openai-responses response
translators (identical id shape). Leave commandcode (different order) and
request-side gemini/antigravity (random suffix) untouched. Golden + gate clean.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 18:12:40 +07:00
decolua
f4c39042a0 refactor(open-sse): dedup format default in PROVIDERS via resolver (C1)
Wrap PROVIDERS in defineProviders() that appends format:"openai" when omitted,
removing 72 repeated `format:"openai"` lines. Output stays byte-for-byte
identical (verified by tests/__baseline__/verify-providers.mjs deep-equal
against snapshot). No runtime fields added; consumers unchanged.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 17:57:51 +07:00
decolua
3a26d5fb40 refactor(open-sse): remove dead buildProviderUrl/Headers path (A1)
These translate-path builders had no runtime consumers: the translator route
uses executor.buildUrl/buildHeaders, and the barrel re-exports were unused.
Removing them eliminates the parallel URL/header build path (single source of
truth = executors). Drop their private helpers and the now-unused clineAuth
import. Golden executor snapshots + gate: no regression.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 17:34:39 +07:00
decolua
cc1f4f6c53 test(open-sse): golden lock provider.js translate-path (A1-prep)
Snapshot buildProviderUrl/buildProviderHeaders/getTargetFormat for all providers
before merging the translate-path with executor URL/header builders.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 17:19:56 +07:00
decolua
39278e9613 refactor(open-sse): extract buildUsage helper, dedup token-details (B2)
Add helpers/usageHelper.js for conditional prompt/completion token details.
Apply to gemini/codex/claude response translators; keep each provider's token
math intact. No behavior change; golden + gate: no regression.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 17:18:15 +07:00
decolua
17202f7111 refactor(open-sse): extract chunkBuilder, dedup chat.completion.chunk (B1)
Add helpers/chunkBuilder.js; apply to claude/gemini/kiro/ollama/commandcode/
openai-responses response translators. Caller supplies id/created/model so each
keeps exact id-generation + usage semantics. Extend golden response stream to
openai-responses (codex). No behavior change; gate: no regression.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 17:05:42 +07:00
decolua
0e34358e74 test(open-sse): extend golden response stream to kiro/ollama (T0.5)
Lock chunk/usage/tool/thinking/finish behavior for kiro + ollama before
chunkBuilder refactor. Sanitize volatile stream/tool ids.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 16:47:25 +07:00
decolua
b87cf0c96a refactor(open-sse): extract safeParseJSON util, dedup tryParseJSON (B5)
Consolidate two tryParseJSON variants into helpers/jsonUtil.js with explicit
fallback param. Preserve exact per-call semantics: openai-to-claude passthrough
(fallback=str), geminiHelper null. geminiHelper keeps tryParseJSON re-export.
No behavior change; gate: no regression.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 16:45:10 +07:00
decolua
87fe069e9e refactor(open-sse): remove reverse coupling open-sse -> src (E2)
Move clineAuth into open-sse/shared (src re-exports back). Add standalone
open-sse/shared/machineId for codex session hashing (no @/lib/dataDir).
sttCore receives sttConfig via param instead of importing AI_PROVIDERS.
No behavior change; gate: no regression (26 known-fails unchanged).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 16:35:07 +07:00
decolua
8f0a9ff9d4 test(open-sse): add P0 golden tests (url/header, response stream, request body)
Lock current behavior before refactor: buildUrl/buildHeaders per default-executor
provider, translateResponse streaming (claude/gemini), translateRequest body
(openai->claude/gemini/kiro). Sanitize volatile fields (tokens, kimi device-id,
kiro conversationId, timestamps) for stable snapshots.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 16:22:00 +07:00
decolua
9532ec804e chore(refactor): snapshot test baseline + no-regression gate truoc refactor open-sse
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 16:13:40 +07:00
decolua
05e483c02e fix(provider-topology): update label assignment to include nodeName
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 11:43:18 +07:00
Ngô Tấn Tài
b33cbb0280 feat(vercel-ai-gateway): support embeddings, images and credit usage
Extend Vercel AI Gateway beyond chat: add OpenAI-compatible embeddings
and image generation endpoints, credit balance fetch on the usage
dashboard, retry on 429, and models catalog fetcher.

Thinking/reasoning mapping is omitted pending a project-wide refactor.

Co-authored-by: Ngô Tấn Tài <tantai@newnol.io.vn>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 10:54:51 +07:00
Fadjrir Herlambang
b40e96d0ef feat(provider): add MiMo Free no-auth provider
Bootstrap → JWT → chat flow with auto-retry. Inject the MiMoCode
system marker required to pass the upstream 403 anti-abuse gate,
derive JWT expiry from the exp claim, and use a stable per-machine
fingerprint as the bootstrap client.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 10:14:21 +07:00
decolua
9caea88528 fix(codex): harden streaming timeouts + Responses terminal events
Raise stall/connect timeouts to 60s (configurable per-provider), accept
codex response.done, and always emit a terminal response.failed + [DONE]
for Responses passthrough when a stream closes, stalls, or aborts before
a terminal event — preventing codex clients from hanging.

Co-authored-by: jonathanli12 <jonathanli12@users.noreply.github.com>
Co-authored-by: rifuki <rifuki@users.noreply.github.com>
Co-authored-by: nguyenha935 <nguyenha935@users.noreply.github.com>
Co-authored-by: trananhtung <trananhtung@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 16:07:43 +07:00
Claude Code
c785051360 fix(claude): forced tool_choice 400 on cc/ OAuth route
convertOpenAIToolChoice mapped {type:"function"} verbatim and cloakClaudeTools
left tool_choice.name unsuffixed, both rejected by Claude on the cc/ path.
Map forced-function to {type:"tool",name}, allowlist Claude-valid types, and
suffix tool_choice.name when it targets a renamed client tool.

Fixes #1592

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 12:54:01 +07:00
decolua
64f58420db feat(i18n): add endpoint exposure notice across multiple languages
Added a new translation for the message "Endpoint is exposed without an API key." to various language files, enhancing user awareness regarding API security. This update ensures that users are informed about potential risks associated with unprotected endpoints in their respective languages.
2026-06-06 12:45:32 +07:00
Farhan Usman
4fc02e67e5 fix(minimax): echo reasoning_content on follow-up turns to avoid 400
MiniMax requires reasoning_content echoed back on assistant messages in
multi-turn/tool-call conversations. Add minimax and minimax-cn to
PROVIDER_RULES (scope all), same fix as DeepSeek (#1543).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 12:25:12 +07:00
Simon Shi
8ad95542da fix(kiro): handle 400 on tool-bearing history without client tools
Kiro requires a non-empty currentMessage tools array whenever history
references any tool use, else returns "Improperly formed request" (400).
Clients trip this by omitting tools on follow-ups after client-side
compaction.

- flattenToolInteractions(): no client tools -> collapse tool_use/result
  to text so the "tools required" rule never fires
- reconcileOrphanedToolResults(): client tools -> salvage orphaned
  results as text, keep matched ones, guard co-located tools array
- safeJSONParse(): guard tool-call argument parsing against bad JSON
- merge consecutive user userInputMessageContext; null-guard
  currentMessage for assistant-only input

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 12:23:47 +07:00
decolua
281f292f63 test(translator): add data-driven coverage, bug-exposing cases, and real provider smoke
- matrix.js generates N providers x M models from PROVIDER_MODELS
- coverage-all-models + format-roundtrip for structural/semantic checks
- bugs-* files expose known translation issues via it.fails
- real/smoke-providers runs full handleChatCore path against live providers (RUN_REAL=1), concurrent
- registerAll.js eagerly imports translators (Vitest ESM require fix)
- vitest.config: array aliases for subpaths + maxConcurrency 60

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 12:19:59 +07:00
Kevin Le
c233c7c8fc fix(codex): durable OAuth refresh lifecycle
Add shared OAuth credential lifecycle manager with provider-aware refresh
decisions. Implement CodexExecutor.refreshCredentials so 401/403 retry
refresh works for Codex, track lastRefreshAt and refresh before the
upstream stale-token window, preserve omitted idToken, and add
per-connection single-flight refresh to avoid refresh-token rotation races.

Merged from PR #1664.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 11:04:36 +07:00
Delcado19
38b73bfc6b fix(antigravity): passthrough tab-autocomplete + mark default agent slot mandatory
MODEL_NO_MAP guard never re-routes Antigravity tab-autocomplete (tab_* models)
so latency-critical inline completion stays native. Flags gemini-3.5-flash-low
(agent/Default) as mandatory in the dashboard.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 10:48:14 +07:00
therunnas
61d546627e fix(qoder): allow qmodel_latest model key
- Add qmodel_latest to QODER_MODEL_MAP
- Expose qmodel_latest in static Qoder provider catalog (qd)
- Generalize executor comment so model set does not go stale
- Add unit coverage for the new model key + catalog

Closes #1638

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 10:44:37 +07:00
Delcado19
3dda651bad fix(kiro): add mappable "auto" model slot for Kiro agent mode
Kiro sends modelId "auto" for the main agent turn; without a defaultModels
slot getMappedModel returned null and the call leaked to AWS instead of the
configured provider. Adds the slot + guard test.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 10:31:39 +07:00
decolua
8671468360 Merge PR #1628: fix(model-test) route image and STT probes to their real endpoints
Route image model tests to /api/v1/images/generations and STT to
/api/v1/audio/transcriptions instead of forcing all non-embedding
models through chat completions. Adds kind-aware pingModelByKind,
hf->huggingface alias, and silent WAV sample for STT reachability.

Scoped to dashboard/internal model testing only; runtime inference
routing is unchanged.

Author: yicone <yicone@gmail.com>
Closes #1628
2026-06-06 10:03:32 +07:00
hodtien
41f94ce8c8 fix(minimax): Bổ sung MiniMax-M3 + cập nhật Quota Tracker coding/CN
Squash-merge PR #1631 (decolua/9router) — chỉ lấy file code + test, bỏ docs.

- feat(minimax): add MiniMax-M3 to intl + cn provider models (targetFormat claude)
- feat(minimax): add MiniMax-M3 pricing entry
- fix(minimax): translate Claude body khi content=null (M3 thinking-only)
- fix(minimax): hiển thị quota M-series bucket "general"/"MiniMax-M*" + percent-only
- test: minimax usage / model registration / pricing

Co-Authored-By: Claude <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 10:01:05 +07:00
yicone
c980e1f7ad Harden STT ping input and expand model-test coverage 2026-06-03 01:53:34 +08:00
yicone
d4c3e6383a Fix STT model test routing 2026-06-02 21:14:42 +08:00
yicone
e414975d0c Fix model test routing for image providers 2026-06-02 21:14:36 +08:00