Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/reference/PROVIDER_REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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) | — |
Expand Down
4 changes: 2 additions & 2 deletions open-sse/config/providerRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
4 changes: 2 additions & 2 deletions open-sse/executors/commandCode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
8 changes: 8 additions & 0 deletions src/app/api/providers/[id]/models/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
4 changes: 2 additions & 2 deletions src/lib/providers/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 ||
Expand Down
2 changes: 1 addition & 1 deletion src/shared/constants/providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down
10 changes: 5 additions & 5 deletions tests/unit/command-code-executor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 });
Expand All @@ -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");
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/executor-command-code.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 () => {
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/provider-validation-specialty.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -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");
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/responses-handler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down