mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-05 06:42:12 +03:00
feat(xai): route xAI clients to Grok native /v1/responses endpoint (#6709)
* feat(xai): route xAI clients to Grok native /v1/responses endpoint xAI ships a native /v1/responses endpoint (https://api.x.ai/v1/responses) alongside /v1/chat/completions, but XaiExecutor extended BaseExecutor without overriding buildUrl(), so every request always resolved to the static chat-completions baseUrl regardless of target format — the last genuinely-missing slice of decolua/9router#2439 (grok-build-0.1, the reasoning-effort suffix routing, and bare grok-* routing were already ported in prior cycles). Add responsesBaseUrl to the xai registry entry and tag grok-4.20-multi-agent-0309 (upstream's own Responses-only id) with targetFormat: "openai-responses", mirroring the existing model-tag-driven routing pattern already used by the gh executor (9router#102) and the "openai" -pro heuristic in open-sse/executors/default.ts — the per-model registry tag is the single source of truth that also drives chatCore's body translation, so URL and body stay in lockstep. XaiExecutor.buildUrl now checks getModelTargetFormat("xai", model) and resolves to the native Responses endpoint only for tagged models, leaving every other grok-* model on the existing chat-completions bridge. TDD: tests/unit/executor-xai.test.ts adds a RED-then-GREEN case asserting grok-4.20-multi-agent-0309 resolves to https://api.x.ai/v1/responses and a control case asserting grok-4.3 still resolves to https://api.x.ai/v1/chat/completions. Co-authored-by: ryanngit <74137224+ryanngit@users.noreply.github.com> Inspired-by: https://github.com/decolua/9router/pull/2439 * chore(6709): re-sync onto release tip; CHANGELOG → changelog.d fragment (fragments-first) --------- Co-authored-by: ryanngit <74137224+ryanngit@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
28fcd418a4
commit
2ef88763e4
1
changelog.d/features/6709-xai-responses-endpoint.md
Normal file
1
changelog.d/features/6709-xai-responses-endpoint.md
Normal file
@@ -0,0 +1 @@
|
||||
- **feat(xai):** route xAI clients to Grok's native `/v1/responses` endpoint instead of the chat-completions bridge. (thanks @ryanngit)
|
||||
@@ -6,12 +6,23 @@ export const xaiProvider: RegistryEntry = {
|
||||
format: "openai",
|
||||
executor: "xai",
|
||||
baseUrl: "https://api.x.ai/v1/chat/completions",
|
||||
// Port of decolua/9router#2439 (author: @ryanngit): xAI ships a native
|
||||
// `/v1/responses` endpoint alongside `/v1/chat/completions`. Consumed by
|
||||
// XaiExecutor.buildUrl (open-sse/executors/xai.ts) for models tagged
|
||||
// targetFormat: "openai-responses" below.
|
||||
responsesBaseUrl: "https://api.x.ai/v1/responses",
|
||||
authType: "apikey",
|
||||
authHeader: "bearer",
|
||||
models: [
|
||||
{ id: "grok-4.3", name: "Grok 4.3" },
|
||||
{ id: "grok-build-0.1", name: "Grok Build 0.1", contextLength: 256000 },
|
||||
{ id: "grok-4.20-multi-agent-0309", name: "Grok 4.20 Multi Agent" },
|
||||
// Responses-only per upstream 9router#2439: xAI serves this id exclusively
|
||||
// over its native /v1/responses endpoint.
|
||||
{
|
||||
id: "grok-4.20-multi-agent-0309",
|
||||
name: "Grok 4.20 Multi Agent",
|
||||
targetFormat: "openai-responses",
|
||||
},
|
||||
{ id: "grok-4.20-0309-reasoning", name: "Grok 4.20 Reasoning" },
|
||||
{ id: "grok-4.20-0309-non-reasoning", name: "Grok 4.20" },
|
||||
],
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { BaseExecutor, type ProviderCredentials } from "./base.ts";
|
||||
import { PROVIDERS } from "../config/constants.ts";
|
||||
import { getModelTargetFormat } from "../config/providerModels.ts";
|
||||
|
||||
type JsonRecord = Record<string, unknown>;
|
||||
|
||||
@@ -51,6 +52,24 @@ export class XaiExecutor extends BaseExecutor {
|
||||
super("xai", PROVIDERS.xai);
|
||||
}
|
||||
|
||||
/**
|
||||
* Port of decolua/9router#2439 (author: @ryanngit): xAI ships a native
|
||||
* `/v1/responses` endpoint alongside `/v1/chat/completions`. Models tagged
|
||||
* `targetFormat: "openai-responses"` in the registry (currently
|
||||
* grok-4.20-multi-agent-0309, per upstream) resolve to that endpoint instead
|
||||
* of the default chat-completions bridge. The per-model registry tag is the
|
||||
* single source of truth — it also drives chatCore's body translation — so
|
||||
* the URL stays in lockstep with the translated body, mirroring the gh
|
||||
* executor's targetFormat-driven routing (9router#102) and the "openai"
|
||||
* -pro heuristic in open-sse/executors/default.ts.
|
||||
*/
|
||||
buildUrl(model: string, _stream: boolean, _urlIndex = 0) {
|
||||
if (getModelTargetFormat("xai", model) === "openai-responses") {
|
||||
return this.config.responsesBaseUrl || this.config.baseUrl;
|
||||
}
|
||||
return this.config.baseUrl;
|
||||
}
|
||||
|
||||
transformRequest(
|
||||
model: string,
|
||||
body: unknown,
|
||||
|
||||
@@ -92,3 +92,21 @@ test("leaves a plain, unlisted model id and body unchanged (no suffix, not allow
|
||||
assert.equal(out.reasoning_effort, undefined);
|
||||
assert.deepEqual(out.messages, body.messages);
|
||||
});
|
||||
|
||||
// Port of decolua/9router#2439 (author: @ryanngit): xAI ships a native
|
||||
// `/v1/responses` endpoint. grok-4.20-multi-agent-0309 is tagged
|
||||
// targetFormat: "openai-responses" in the registry (upstream's own tag) — it
|
||||
// must resolve to xAI's native Responses URL, not the chat-completions
|
||||
// bridge, mirroring the gh executor's targetFormat-driven routing (9router#102)
|
||||
// and the "openai" -pro heuristic in open-sse/executors/default.ts.
|
||||
test("XaiExecutor.buildUrl routes the Responses-tagged model (grok-4.20-multi-agent-0309) to xAI's native /v1/responses endpoint", () => {
|
||||
const executor = new XaiExecutor();
|
||||
const url = executor.buildUrl("grok-4.20-multi-agent-0309", true);
|
||||
assert.equal(url, "https://api.x.ai/v1/responses");
|
||||
});
|
||||
|
||||
test("XaiExecutor.buildUrl keeps a plain chat model (grok-4.3) on /v1/chat/completions", () => {
|
||||
const executor = new XaiExecutor();
|
||||
const url = executor.buildUrl("grok-4.3", true);
|
||||
assert.equal(url, "https://api.x.ai/v1/chat/completions");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user