fix(command-code): revert chat endpoint to /alpha/generate and fix model sync discovery (#3432)

Integrated into release/v3.8.17
This commit is contained in:
Muhammad Nabil Muyassar Rahman
2026-06-09 04:41:52 +07:00
committed by GitHub
parent fc437ddecd
commit b3372e46c4
10 changed files with 25 additions and 17 deletions

View File

@@ -113,7 +113,7 @@ Use the dashboard at `/dashboard/providers` to enable, configure, and test each
| `cloudflare-ai` | `cf` | Cloudflare Workers AI | API key | [link](https://developers.cloudflare.com/workers-ai) | Requires API Token AND Account ID (found at dash.cloudflare.com) |
| `codestral` | `codestral` | Codestral | API key | [link](https://mistral.ai) | — |
| `cohere` | `cohere` | Cohere | API key | [link](https://cohere.com) | Free Trial: 1,000 API calls/month for testing, no credit card required |
| `command-code` | `cmd` | Command Code | API key | [link](https://commandcode.ai/) | Use a Command Code API key. Requests are sent to Command Code's /provider/v1/chat/completions endpoint. |
| `command-code` | `cmd` | Command Code | API key | [link](https://commandcode.ai/) | Use a Command Code API key. Requests are sent to Command Code's /alpha/generate endpoint. |
| `coze` | `coze` | Coze | API key | [link](https://coze.com) | Get API key at coze.com/open/api |
| `crof` | `crof` | CrofAI | API key | [link](https://crof.ai) | — |
| `databricks` | `databricks` | Databricks | API key, enterprise | [link](https://www.databricks.com) | — |

View File

@@ -1626,8 +1626,8 @@ const _REGISTRY_EAGER: Record<string, RegistryEntry> = {
alias: "cmd",
format: "openai",
executor: "command-code",
baseUrl: "https://api.commandcode.ai/provider/v1",
chatPath: "/chat/completions",
baseUrl: "https://api.commandcode.ai",
chatPath: "/alpha/generate",
modelsUrl: "https://api.commandcode.ai/provider/v1/models",
authType: "apikey",
authHeader: "Authorization",

View File

@@ -509,8 +509,8 @@ export class CommandCodeExecutor extends BaseExecutor {
}
buildUrl() {
const baseUrl = (this.config.baseUrl || "https://api.commandcode.ai/provider/v1").replace(/\/$/, "");
return `${baseUrl}${this.config.chatPath || "/chat/completions"}`;
const baseUrl = (this.config.baseUrl || "https://api.commandcode.ai").replace(/\/$/, "");
return `${baseUrl}${this.config.chatPath || "/alpha/generate"}`;
}
async execute({ model, body, stream, credentials, signal, upstreamExtraHeaders }: ExecuteInput) {

View File

@@ -687,6 +687,14 @@ const PROVIDER_MODELS_CONFIG: Record<string, ProviderModelsConfigEntry> = {
authPrefix: "Bearer ",
parseResponse: (data) => data.data || data.models || [],
},
"command-code": {
url: "https://api.commandcode.ai/provider/v1/models",
method: "GET",
headers: { "Content-Type": "application/json" },
authHeader: "Authorization",
authPrefix: "Bearer ",
parseResponse: (data) => data.data || data.models || [],
},
"opencode-zen": {
url: "https://opencode.ai/zen/v1/models",
method: "GET",

View File

@@ -567,8 +567,8 @@ async function validateDirectChatProvider({
export async function validateCommandCodeProvider({ apiKey, providerSpecificData = {} }: any) {
const entry = getRegistryEntry("command-code");
const baseUrl = normalizeBaseUrl(entry?.baseUrl || "https://api.commandcode.ai/provider/v1");
const chatPath = entry?.chatPath || "/chat/completions";
const baseUrl = normalizeBaseUrl(entry?.baseUrl || "https://api.commandcode.ai");
const chatPath = entry?.chatPath || "/alpha/generate";
const url = `${baseUrl}${chatPath.startsWith("/") ? chatPath : `/${chatPath}`}`;
const validationModelId =
providerSpecificData?.validationModelId ||

View File

@@ -599,7 +599,7 @@ export const APIKEY_PROVIDERS = {
textIcon: "CC",
website: "https://commandcode.ai/",
authHint:
"Use a Command Code API key. Requests are sent to Command Code's /provider/v1/chat/completions endpoint.",
"Use a Command Code API key. Requests are sent to Command Code's /alpha/generate endpoint.",
apiHint: "Create or copy an API key from Command Code, then paste it here as a Bearer token.",
},
openrouter: {

View File

@@ -74,8 +74,8 @@ test("Command Code provider catalog has pinned models and alias lookup", () => {
assert.ok(entry);
assert.equal(entry.alias, "cmd");
assert.equal(entry.executor, "command-code");
assert.equal(entry.baseUrl, "https://api.commandcode.ai/provider/v1");
assert.equal(entry.chatPath, "/chat/completions");
assert.equal(entry.baseUrl, "https://api.commandcode.ai");
assert.equal(entry.chatPath, "/alpha/generate");
assert.deepEqual(
entry.models.map((model) => model.id),
PINNED_COMMAND_CODE_MODELS
@@ -89,7 +89,7 @@ test("getExecutor returns the specialized Command Code executor", () => {
assert.ok(getExecutor("cmd") instanceof CommandCodeExecutor);
});
test("Command Code executor posts wrapped body and required headers to /provider/v1/chat/completions", async () => {
test("Command Code executor posts wrapped body and required headers to /alpha/generate", async () => {
const calls: any[] = [];
globalThis.fetch = async (url, init = {}) => {
calls.push({ url: String(url), init });
@@ -112,9 +112,9 @@ test("Command Code executor posts wrapped body and required headers to /provider
},
});
assert.equal(url, "https://api.commandcode.ai/provider/v1/chat/completions");
assert.equal(url, "https://api.commandcode.ai/alpha/generate");
assert.equal(calls.length, 1);
assert.equal(calls[0].url, "https://api.commandcode.ai/provider/v1/chat/completions");
assert.equal(calls[0].url, "https://api.commandcode.ai/alpha/generate");
assert.equal(calls[0].init.method, "POST");
assert.equal(headers.Authorization, "Bearer cc_test_key");
assert.equal(headers["x-command-code-version"], "0.24.1");

View File

@@ -18,7 +18,7 @@ describe("CommandCodeExecutor", () => {
const executor = new mod.CommandCodeExecutor();
const url = executor.buildUrl();
assert.ok(typeof url === "string");
assert.ok(url.includes("/chat/completions") && url.includes("commandcode"));
assert.ok(url.includes("generate") && url.includes("commandcode"));
});
it("execute throws when no API key", async () => {

View File

@@ -88,7 +88,7 @@ test("specialty provider validators cover Deepgram, AssemblyAI, ElevenLabs and I
test("validateCommandCodeProvider ignores caller baseUrl and chatPath overrides", async () => {
globalThis.fetch = async (url, init = {}) => {
assert.equal(String(url), "https://api.commandcode.ai/provider/v1/chat/completions");
assert.equal(String(url), "https://api.commandcode.ai/alpha/generate");
const headers = init.headers as Record<string, string>;
assert.equal(headers.Authorization, "Bearer cc-key");
const body = JSON.parse(String(init.body));
@@ -1956,7 +1956,7 @@ test("validateCommandCodeProvider sends Command Code probe URL, headers, and wra
assert.deepEqual(result, { valid: true, error: null });
assert.equal(calls.length, 1);
assert.equal(calls[0].url, "https://api.commandcode.ai/provider/v1/chat/completions");
assert.equal(calls[0].url, "https://api.commandcode.ai/alpha/generate");
assert.equal(calls[0].method, "POST");
assert.equal(calls[0].headers.Authorization, "Bearer cc_test_key");
assert.equal(calls[0].headers["Content-Type"], "application/json");

View File

@@ -251,7 +251,7 @@ test("handleResponsesCore transforms Command Code executor SSE through Responses
});
assert.equal(result.success, true);
assert.equal(call.url, "https://api.commandcode.ai/provider/v1/chat/completions");
assert.equal(call.url, "https://api.commandcode.ai/alpha/generate");
assert.equal(call.headers.Authorization, "Bearer cc_test_key");
assert.equal(call.headers["x-command-code-version"], "0.24.1");
assert.equal(call.body.params.model, "gpt-5.4-mini");