feat(providers): add Command Code provider (#2199)

Integrated into release/v3.8.0 after syncing the contributor branch, removing unrelated workflow/package-lock changes, and validating Command Code provider, auth, validation, and Responses coverage locally.
This commit is contained in:
Dohyun Jung
2026-05-13 07:57:35 +09:00
committed by GitHub
parent e6aee3d26c
commit fc620514a9
19 changed files with 2514 additions and 23 deletions

View File

@@ -156,6 +156,135 @@ const KIMI_CODING_SHARED = {
const buildModels = (ids: readonly string[]): RegistryModel[] => const buildModels = (ids: readonly string[]): RegistryModel[] =>
ids.map((id) => ({ id, name: id })); ids.map((id) => ({ id, name: id }));
const COMMAND_CODE_MODELS: RegistryModel[] = [
{
id: "claude-opus-4-7",
name: "Claude Opus 4.7 (CC)",
supportsReasoning: true,
contextLength: 200000,
maxOutputTokens: 32000,
},
{
id: "claude-opus-4-6",
name: "Claude Opus 4.6 (CC)",
supportsReasoning: true,
contextLength: 200000,
maxOutputTokens: 32000,
},
{
id: "claude-sonnet-4-6",
name: "Claude Sonnet 4.6 (CC)",
supportsReasoning: true,
contextLength: 200000,
maxOutputTokens: 16384,
},
{
id: "claude-haiku-4-5-20251001",
name: "Claude Haiku 4.5 (CC)",
supportsReasoning: true,
contextLength: 200000,
maxOutputTokens: 8192,
},
{
id: "gpt-5.5",
name: "GPT-5.5 (CC)",
supportsReasoning: true,
contextLength: 256000,
maxOutputTokens: 128000,
},
{
id: "gpt-5.4",
name: "GPT-5.4 (CC)",
supportsReasoning: true,
contextLength: 256000,
maxOutputTokens: 128000,
},
{
id: "gpt-5.3-codex",
name: "GPT-5.3 Codex (CC)",
supportsReasoning: true,
contextLength: 256000,
maxOutputTokens: 128000,
},
{
id: "gpt-5.4-mini",
name: "GPT-5.4 Mini (CC)",
supportsReasoning: false,
contextLength: 256000,
maxOutputTokens: 128000,
},
{
id: "deepseek/deepseek-v4-pro",
name: "DeepSeek V4 Pro (CC)",
supportsReasoning: true,
contextLength: 1000000,
maxOutputTokens: 384000,
},
{
id: "deepseek/deepseek-v4-flash",
name: "DeepSeek V4 Flash (CC)",
supportsReasoning: true,
contextLength: 1000000,
maxOutputTokens: 384000,
},
{
id: "moonshotai/Kimi-K2.6",
name: "Kimi K2.6 (CC)",
supportsReasoning: true,
contextLength: 262144,
maxOutputTokens: 131072,
},
{
id: "moonshotai/Kimi-K2.5",
name: "Kimi K2.5 (CC)",
supportsReasoning: true,
contextLength: 262144,
maxOutputTokens: 131072,
},
{
id: "zai-org/GLM-5.1",
name: "GLM-5.1 (CC)",
supportsReasoning: true,
contextLength: 200000,
maxOutputTokens: 131072,
},
{
id: "zai-org/GLM-5",
name: "GLM-5 (CC)",
supportsReasoning: true,
contextLength: 200000,
maxOutputTokens: 131072,
},
{
id: "MiniMaxAI/MiniMax-M2.7",
name: "MiniMax M2.7 (CC)",
supportsReasoning: true,
contextLength: 1048576,
maxOutputTokens: 131072,
},
{
id: "MiniMaxAI/MiniMax-M2.5",
name: "MiniMax M2.5 (CC)",
supportsReasoning: true,
contextLength: 1048576,
maxOutputTokens: 131072,
},
{
id: "Qwen/Qwen3.6-Max-Preview",
name: "Qwen 3.6 Max (CC)",
supportsReasoning: true,
contextLength: 1000000,
maxOutputTokens: 131072,
},
{
id: "Qwen/Qwen3.6-Plus",
name: "Qwen 3.6 Plus (CC)",
supportsReasoning: true,
contextLength: 1000000,
maxOutputTokens: 131072,
},
];
const GPT_5_5_CONTEXT_LENGTH = 1050000; const GPT_5_5_CONTEXT_LENGTH = 1050000;
const GPT_5_5_CODEX_CAPABILITIES = { const GPT_5_5_CODEX_CAPABILITIES = {
targetFormat: "openai-responses", targetFormat: "openai-responses",
@@ -991,6 +1120,20 @@ export const REGISTRY: Record<string, RegistryEntry> = {
passthroughModels: true, passthroughModels: true,
}, },
"command-code": {
id: "command-code",
alias: "cmd",
format: "openai",
executor: "command-code",
baseUrl: "https://api.commandcode.ai",
chatPath: "/alpha/generate",
authType: "apikey",
authHeader: "Authorization",
authPrefix: "Bearer ",
defaultContextLength: 200000,
models: COMMAND_CODE_MODELS,
},
openrouter: { openrouter: {
id: "openrouter", id: "openrouter",
alias: "openrouter", alias: "openrouter",

View File

@@ -0,0 +1,545 @@
import { randomUUID } from "node:crypto";
import { REGISTRY } from "../config/providerRegistry.ts";
import { BaseExecutor, mergeUpstreamExtraHeaders, type ExecuteInput } from "./base.ts";
type JsonRecord = Record<string, unknown>;
const COMMAND_CODE_VERSION = "0.24.1";
const MAX_COMMAND_CODE_TOKENS = 200_000;
const encoder = new TextEncoder();
function isRecord(value: unknown): value is JsonRecord {
return typeof value === "object" && value !== null && !Array.isArray(value);
}
function asRecordArray(value: unknown): JsonRecord[] {
return Array.isArray(value) ? value.filter(isRecord) : [];
}
function stringValue(value: unknown): string | undefined {
return typeof value === "string" ? value : undefined;
}
function numberValue(value: unknown): number | undefined {
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
}
function recordOrEmpty(value: unknown): JsonRecord {
if (isRecord(value)) return value;
if (typeof value === "string" && value.trim()) {
try {
const parsed: unknown = JSON.parse(value);
if (isRecord(parsed)) return parsed;
} catch {
// Tool argument fragments may be incomplete in streamed deltas.
}
}
return {};
}
function normalizeContentText(content: unknown): string {
if (typeof content === "string") return content;
return asRecordArray(content)
.filter((part) => part.type === "text")
.map((part) => stringValue(part.text) || "")
.join("\n");
}
function convertTools(tools: unknown): unknown[] {
return asRecordArray(tools).map((tool) => {
const fn = isRecord(tool.function) ? tool.function : tool;
return {
type: "function",
name: stringValue(fn.name) || "",
description: stringValue(fn.description) || "",
input_schema: isRecord(fn.parameters) ? fn.parameters : {},
};
});
}
function completeToolCallIds(messages: JsonRecord[]): Set<string> {
const callIds = new Set<string>();
const resultIds = new Set<string>();
for (const message of messages) {
if (message.role === "assistant") {
for (const call of asRecordArray(message.tool_calls)) {
const id = stringValue(call.id);
if (id) callIds.add(id);
}
} else if (message.role === "tool") {
const id = stringValue(message.tool_call_id);
if (id) resultIds.add(id);
}
}
return new Set([...callIds].filter((id) => resultIds.has(id)));
}
function convertMessages(messages: unknown): { system: string; messages: unknown[] } {
const source = asRecordArray(messages);
const pairedToolCallIds = completeToolCallIds(source);
const out: unknown[] = [];
const system: string[] = [];
for (const message of source) {
const role = stringValue(message.role);
if (role === "system" || role === "developer") {
const text = normalizeContentText(message.content);
if (text) system.push(text);
continue;
}
if (role === "user") {
out.push({ role: "user", content: message.content ?? "" });
continue;
}
if (role === "assistant") {
const parts: unknown[] = [];
const text = normalizeContentText(message.content);
if (text) parts.push({ type: "text", text });
for (const call of asRecordArray(message.tool_calls)) {
const id = stringValue(call.id) || "";
if (!id || !pairedToolCallIds.has(id)) continue;
const fn = isRecord(call.function) ? call.function : {};
parts.push({
type: "tool-call",
toolCallId: id,
toolName: stringValue(fn.name) || "",
input: recordOrEmpty(fn.arguments),
});
}
if (parts.length > 0) out.push({ role: "assistant", content: parts });
continue;
}
if (role === "tool") {
const toolCallId = stringValue(message.tool_call_id) || "";
if (!toolCallId || !pairedToolCallIds.has(toolCallId)) continue;
out.push({
role: "tool",
content: [
{
type: "tool-result",
toolCallId,
toolName: stringValue(message.name) || "",
output: { type: "text", value: normalizeContentText(message.content) },
},
],
});
}
}
return { system: system.join("\n\n"), messages: out };
}
function clampMaxTokens(value: unknown): number {
const numeric = numberValue(value) ?? MAX_COMMAND_CODE_TOKENS;
return Math.max(1, Math.min(Math.floor(numeric), MAX_COMMAND_CODE_TOKENS));
}
function buildCommandCodeBody(model: string, body: unknown): JsonRecord {
const input = isRecord(body) ? body : {};
const converted = convertMessages(input.messages);
const explicitSystem = typeof input.system === "string" ? input.system : "";
const system = [converted.system, explicitSystem].filter(Boolean).join("\n\n");
return {
config: {
workingDir: "/workspace",
date: new Date().toISOString().slice(0, 10),
environment: "omniroute",
structure: [],
isGitRepo: false,
currentBranch: "",
mainBranch: "",
gitStatus: "",
recentCommits: [],
},
memory: "",
taste: "",
skills: null,
permissionMode: "standard",
params: {
model,
messages: converted.messages,
tools: convertTools(input.tools),
system,
max_tokens: clampMaxTokens(input.max_tokens ?? input.max_completion_tokens),
stream: true,
},
};
}
function parseStreamLine(line: string): unknown | undefined {
let trimmed = line.trim();
if (!trimmed || trimmed.startsWith(":") || trimmed.startsWith("event:")) return undefined;
if (trimmed.startsWith("data:")) trimmed = trimmed.slice(5).trim();
if (!trimmed || trimmed === "[DONE]") return undefined;
try {
return JSON.parse(trimmed);
} catch {
return undefined;
}
}
function mapFinishReason(reason: unknown): "stop" | "length" | "tool_calls" {
if (reason === "tool-calls" || reason === "tool_calls" || reason === "toolUse")
return "tool_calls";
if (
reason === "length" ||
reason === "max_tokens" ||
reason === "max-tokens" ||
reason === "max_output_tokens"
) {
return "length";
}
return "stop";
}
function chatCompletionChunk(
id: string,
model: string,
delta: JsonRecord,
finishReason: unknown = null
) {
return {
id,
object: "chat.completion.chunk",
created: Math.floor(Date.now() / 1000),
model,
choices: [{ index: 0, delta, finish_reason: finishReason }],
};
}
function sse(data: unknown): Uint8Array {
return encoder.encode(`data: ${JSON.stringify(data)}\n\n`);
}
type AggregateState = {
content: string;
reasoning: string;
toolCalls: JsonRecord[];
finishReason: "stop" | "length" | "tool_calls";
usage: JsonRecord | null;
};
function applyEventToAggregate(event: JsonRecord, state: AggregateState): void {
switch (event.type) {
case "text-delta":
state.content += stringValue(event.text) || "";
break;
case "reasoning-delta":
state.reasoning += stringValue(event.text) || "";
break;
case "tool-call": {
const args = recordOrEmpty(event.input ?? event.args ?? event.arguments);
state.toolCalls.push({
id: stringValue(event.toolCallId) || stringValue(event.id) || randomUUID(),
type: "function",
function: {
name: stringValue(event.toolName) || stringValue(event.name) || "",
arguments: JSON.stringify(args),
},
});
break;
}
case "finish":
state.finishReason = mapFinishReason(event.finishReason);
state.usage = isRecord(event.totalUsage) ? event.totalUsage : null;
break;
}
}
function applyEventToAggregateOrThrow(event: JsonRecord, state: AggregateState): void {
if (event.type === "error") {
const error = isRecord(event.error) ? event.error : {};
throw new Error(
stringValue(error.message) || stringValue(event.error) || "Command Code stream error"
);
}
applyEventToAggregate(event, state);
}
function usageFromCommandCode(usage: JsonRecord | null) {
if (!usage) return undefined;
const details = isRecord(usage.inputTokenDetails) ? usage.inputTokenDetails : {};
const prompt =
(numberValue(usage.inputTokens) || 0) + (numberValue(details.cacheReadTokens) || 0);
const completion = numberValue(usage.outputTokens) || 0;
return {
prompt_tokens: prompt,
completion_tokens: completion,
total_tokens: prompt + completion,
};
}
function createStreamResponse(
upstream: Response,
model: string,
signal?: AbortSignal | null
): Response {
const id = `chatcmpl-${randomUUID()}`;
const reader = upstream.body?.getReader();
const decoder = new TextDecoder();
let buffer = "";
let sentRole = false;
let closed = false;
const state: AggregateState = {
content: "",
reasoning: "",
toolCalls: [],
finishReason: "stop",
usage: null,
};
const stream = new ReadableStream<Uint8Array>({
start(controller) {
if (!reader) {
controller.error(new Error("Command Code response missing body"));
return;
}
const abort = () => {
closed = true;
reader.cancel().catch(() => undefined);
controller.error(new DOMException("The operation was aborted", "AbortError"));
};
signal?.addEventListener("abort", abort, { once: true });
const emitEvent = (event: unknown) => {
if (!isRecord(event) || closed) return;
if (!sentRole) {
sentRole = true;
controller.enqueue(sse(chatCompletionChunk(id, model, { role: "assistant" })));
}
switch (event.type) {
case "text-delta": {
const text = stringValue(event.text) || "";
if (text) controller.enqueue(sse(chatCompletionChunk(id, model, { content: text })));
state.content += text;
break;
}
case "reasoning-delta": {
const text = stringValue(event.text) || "";
if (text) {
controller.enqueue(sse(chatCompletionChunk(id, model, { reasoning_content: text })));
state.reasoning += text;
}
break;
}
case "tool-call": {
const index = state.toolCalls.length;
const args = recordOrEmpty(event.input ?? event.args ?? event.arguments);
const toolCall = {
id: stringValue(event.toolCallId) || stringValue(event.id) || randomUUID(),
type: "function",
function: {
name: stringValue(event.toolName) || stringValue(event.name) || "",
arguments: JSON.stringify(args),
},
};
state.toolCalls.push(toolCall);
controller.enqueue(
sse(chatCompletionChunk(id, model, { tool_calls: [{ index, ...toolCall }] }))
);
break;
}
case "reasoning-end":
break;
case "finish": {
state.finishReason = mapFinishReason(event.finishReason);
state.usage = isRecord(event.totalUsage) ? event.totalUsage : null;
controller.enqueue(sse(chatCompletionChunk(id, model, {}, state.finishReason)));
controller.enqueue(encoder.encode("data: [DONE]\n\n"));
closed = true;
controller.close();
reader.cancel().catch(() => undefined);
break;
}
case "error": {
const error = isRecord(event.error) ? event.error : {};
throw new Error(
stringValue(error.message) || stringValue(event.error) || "Command Code stream error"
);
}
}
};
const pump = async () => {
try {
for (;;) {
if (closed) return;
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split("\n");
buffer = lines.pop() || "";
for (const line of lines) emitEvent(parseStreamLine(line));
}
if (buffer.trim()) emitEvent(parseStreamLine(buffer));
if (!closed) {
if (!sentRole)
controller.enqueue(sse(chatCompletionChunk(id, model, { role: "assistant" })));
controller.enqueue(sse(chatCompletionChunk(id, model, {}, state.finishReason)));
controller.enqueue(encoder.encode("data: [DONE]\n\n"));
controller.close();
}
} catch (error) {
controller.error(error);
} finally {
signal?.removeEventListener("abort", abort);
try {
reader.releaseLock();
} catch {
// Reader may already be released/cancelled.
}
}
};
pump();
},
cancel() {
closed = true;
return reader?.cancel();
},
});
return new Response(stream, {
status: 200,
headers: { "Content-Type": "text/event-stream; charset=utf-8", "Cache-Control": "no-cache" },
});
}
async function createJsonResponse(
upstream: Response,
model: string,
signal?: AbortSignal | null
): Promise<Response> {
const reader = upstream.body?.getReader();
if (!reader) throw new Error("Command Code response missing body");
const decoder = new TextDecoder();
let buffer = "";
const state: AggregateState = {
content: "",
reasoning: "",
toolCalls: [],
finishReason: "stop",
usage: null,
};
try {
for (;;) {
if (signal?.aborted) throw new DOMException("The operation was aborted", "AbortError");
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split("\n");
buffer = lines.pop() || "";
for (const line of lines) {
const event = parseStreamLine(line);
if (!isRecord(event)) continue;
applyEventToAggregateOrThrow(event, state);
}
}
if (buffer.trim()) {
const event = parseStreamLine(buffer);
if (isRecord(event)) applyEventToAggregateOrThrow(event, state);
}
} finally {
try {
await reader.cancel();
} catch {
// Reader may already be closed.
}
try {
reader.releaseLock();
} catch {
// Reader may already be released.
}
}
const message: JsonRecord = { role: "assistant", content: state.content };
if (state.reasoning) message.reasoning_content = state.reasoning;
if (state.toolCalls.length > 0) message.tool_calls = state.toolCalls;
const payload: JsonRecord = {
id: `chatcmpl-${randomUUID()}`,
object: "chat.completion",
created: Math.floor(Date.now() / 1000),
model,
choices: [{ index: 0, message, finish_reason: state.finishReason }],
};
const usage = usageFromCommandCode(state.usage);
if (usage) payload.usage = usage;
return new Response(JSON.stringify(payload), {
status: 200,
headers: { "Content-Type": "application/json" },
});
}
export class CommandCodeExecutor extends BaseExecutor {
constructor(provider = "command-code") {
super(provider, REGISTRY["command-code"]);
}
buildUrl() {
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) {
const apiKey = credentials?.apiKey || credentials?.accessToken;
if (!apiKey) throw new Error("Command Code API key required");
const headers: Record<string, string> = {
"Content-Type": "application/json",
Authorization: `Bearer ${apiKey}`,
"x-command-code-version": COMMAND_CODE_VERSION,
"x-cli-environment": "production",
"x-project-slug": "pi-cc",
"x-taste-learning": "false",
"x-co-flag": "false",
"x-session-id": randomUUID(),
};
mergeUpstreamExtraHeaders(headers, upstreamExtraHeaders);
const transformedBody = buildCommandCodeBody(model, body);
const url = this.buildUrl();
const upstream = await fetch(url, {
method: "POST",
headers,
body: JSON.stringify(transformedBody),
signal: signal || undefined,
});
if (!upstream.ok) {
const errorText = await upstream.text().catch(() => "");
return {
response: new Response(errorText || `Command Code API error ${upstream.status}`, {
status: upstream.status,
statusText: upstream.statusText,
headers: upstream.headers,
}),
url,
headers,
transformedBody,
};
}
const response = stream
? createStreamResponse(upstream, model, signal)
: await createJsonResponse(upstream, model, signal);
return { response, url, headers, transformedBody };
}
}

View File

@@ -19,6 +19,7 @@ import { ChatGptWebExecutor } from "./chatgpt-web.ts";
import { BlackboxWebExecutor } from "./blackbox-web.ts"; import { BlackboxWebExecutor } from "./blackbox-web.ts";
import { MuseSparkWebExecutor } from "./muse-spark-web.ts"; import { MuseSparkWebExecutor } from "./muse-spark-web.ts";
import { AzureOpenAIExecutor } from "./azure-openai.ts"; import { AzureOpenAIExecutor } from "./azure-openai.ts";
import { CommandCodeExecutor } from "./commandCode.ts";
import { GitlabExecutor } from "./gitlab.ts"; import { GitlabExecutor } from "./gitlab.ts";
import { NlpCloudExecutor } from "./nlpcloud.ts"; import { NlpCloudExecutor } from "./nlpcloud.ts";
import { PetalsExecutor } from "./petals.ts"; import { PetalsExecutor } from "./petals.ts";
@@ -39,6 +40,8 @@ const executors = {
glmt: new GlmExecutor("glmt"), glmt: new GlmExecutor("glmt"),
cu: new CursorExecutor(), // Alias for cursor cu: new CursorExecutor(), // Alias for cursor
"azure-openai": new AzureOpenAIExecutor(), "azure-openai": new AzureOpenAIExecutor(),
"command-code": new CommandCodeExecutor(),
cmd: new CommandCodeExecutor(), // Alias
gitlab: new GitlabExecutor(), gitlab: new GitlabExecutor(),
"gitlab-duo": new GitlabExecutor("gitlab-duo"), "gitlab-duo": new GitlabExecutor("gitlab-duo"),
nlpcloud: new NlpCloudExecutor(), nlpcloud: new NlpCloudExecutor(),
@@ -105,6 +108,7 @@ export { ChatGptWebExecutor } from "./chatgpt-web.ts";
export { BlackboxWebExecutor } from "./blackbox-web.ts"; export { BlackboxWebExecutor } from "./blackbox-web.ts";
export { MuseSparkWebExecutor } from "./muse-spark-web.ts"; export { MuseSparkWebExecutor } from "./muse-spark-web.ts";
export { AzureOpenAIExecutor } from "./azure-openai.ts"; export { AzureOpenAIExecutor } from "./azure-openai.ts";
export { CommandCodeExecutor } from "./commandCode.ts";
export { GitlabExecutor } from "./gitlab.ts"; export { GitlabExecutor } from "./gitlab.ts";
export { NlpCloudExecutor } from "./nlpcloud.ts"; export { NlpCloudExecutor } from "./nlpcloud.ts";
export { PetalsExecutor } from "./petals.ts"; export { PetalsExecutor } from "./petals.ts";

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="700.000000pt" height="700.000000pt" viewBox="0 0 700.000000 700.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.14, written by Peter Selinger 2001-2017
</metadata>
<g transform="translate(0.000000,700.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M2305 6994 c-371 -13 -682 -39 -893 -74 -598 -103 -963 -350 -1172
-795 -126 -267 -186 -576 -222 -1130 -19 -287 -18 -2669 0 -2950 53 -794 172
-1175 464 -1481 286 -298 672 -437 1367 -489 616 -47 2694 -46 3267 0 685 56
1056 186 1339 470 289 289 424 685 475 1395 22 310 32 1055 27 1915 -6 868
-13 1102 -42 1417 -55 589 -188 950 -448 1216 -305 311 -678 435 -1487 493
-141 10 -2428 21 -2675 13z m33 -1350 c322 -66 580 -324 646 -646 12 -57 16
-136 16 -303 l0 -225 474 0 474 0 5 243 c4 201 8 255 25 318 67 248 222 437
447 545 138 67 195 79 370 79 143 -1 154 -2 245 -33 279 -96 476 -307 552
-587 29 -111 29 -297 -1 -410 -69 -261 -263 -478 -511 -572 -113 -43 -194 -53
-431 -53 l-219 0 0 -474 0 -474 238 -5 c253 -5 310 -14 432 -64 243 -99 438
-327 495 -576 47 -209 17 -419 -88 -607 -57 -102 -205 -250 -307 -307 -433
-242 -960 -71 -1169 379 -63 134 -74 200 -79 466 l-4 232 -474 0 -474 0 0
-219 c0 -149 -5 -243 -14 -294 -60 -312 -299 -565 -611 -649 -112 -30 -298
-30 -410 0 -519 139 -776 708 -534 1185 106 210 301 365 538 429 63 17 117 21
319 25 l242 5 0 474 0 474 -225 0 c-252 0 -329 11 -452 62 -485 201 -664 796
-372 1232 116 174 310 306 514 349 93 20 248 21 343 1z"/>
<path d="M2080 5174 c-187 -50 -302 -241 -256 -425 31 -119 118 -216 231 -256
42 -15 84 -18 260 -18 l210 0 0 210 c0 176 -3 218 -18 260 -39 111 -136 200
-252 230 -72 18 -103 18 -175 -1z"/>
<path d="M4705 5176 c-75 -19 -125 -49 -178 -105 -86 -92 -91 -112 -95 -373
l-3 -228 185 0 c264 0 337 20 429 119 74 79 92 127 92 241 0 83 -3 102 -27
150 -74 150 -249 236 -403 196z"/>
<path d="M3000 3525 l0 -475 475 0 475 0 0 475 0 475 -475 0 -475 0 0 -475z"/>
<path d="M2051 2550 c-59 -22 -68 -27 -129 -84 -178 -167 -127 -463 98 -574
48 -24 67 -27 150 -27 114 0 162 18 241 92 99 92 119 165 119 428 l0 185 -212
0 c-184 -1 -220 -3 -267 -20z"/>
<path d="M4432 2348 l3 -224 33 -66 c38 -77 92 -130 171 -167 48 -22 70 -26
146 -26 82 0 97 3 157 33 77 38 130 92 167 171 22 47 26 70 26 146 0 76 -4 99
-26 146 -37 79 -90 133 -167 171 l-66 33 -224 3 -223 3 3 -223z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -556,6 +556,9 @@ interface AddApiKeyModalProps {
isCompatible?: boolean; isCompatible?: boolean;
isAnthropic?: boolean; isAnthropic?: boolean;
isCcCompatible?: boolean; isCcCompatible?: boolean;
isCommandCode?: boolean;
commandCodeAuthState?: CommandCodeAuthFlowState;
onStartCommandCodeAuth?: () => void;
onSave: (data: { onSave: (data: {
name: string; name: string;
apiKey?: string; apiKey?: string;
@@ -566,6 +569,23 @@ interface AddApiKeyModalProps {
onClose: () => void; onClose: () => void;
} }
type CommandCodeAuthFlowState = {
phase:
| "idle"
| "starting"
| "polling"
| "received"
| "applying"
| "applied"
| "expired"
| "error";
state: string;
authUrl: string;
callbackUrl: string;
expiresAt: string | null;
message?: string;
};
interface EditConnectionModalConnection { interface EditConnectionModalConnection {
id?: string; id?: string;
name?: string; name?: string;
@@ -981,6 +1001,14 @@ export default function ProviderDetailPage() {
const [showOAuthModal, _setShowOAuthModal] = useState(false); const [showOAuthModal, _setShowOAuthModal] = useState(false);
const [reauthConnection, setReauthConnection] = useState<ConnectionRowConnection | null>(null); const [reauthConnection, setReauthConnection] = useState<ConnectionRowConnection | null>(null);
const [showAddApiKeyModal, setShowAddApiKeyModal] = useState(false); const [showAddApiKeyModal, setShowAddApiKeyModal] = useState(false);
const [commandCodeAuthState, setCommandCodeAuthState] = useState<CommandCodeAuthFlowState>({
phase: "idle",
state: "",
authUrl: "",
callbackUrl: "",
expiresAt: null,
message: "",
});
const [showEditModal, setShowEditModal] = useState(false); const [showEditModal, setShowEditModal] = useState(false);
const [showEditNodeModal, setShowEditNodeModal] = useState(false); const [showEditNodeModal, setShowEditNodeModal] = useState(false);
const [selectedConnection, setSelectedConnection] = useState(null); const [selectedConnection, setSelectedConnection] = useState(null);
@@ -1027,8 +1055,11 @@ export default function ProviderDetailPage() {
const [savingCodexGlobalFastServiceTier, setSavingCodexGlobalFastServiceTier] = useState(false); const [savingCodexGlobalFastServiceTier, setSavingCodexGlobalFastServiceTier] = useState(false);
const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set()); const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());
const [batchDeleting, setBatchDeleting] = useState(false); const [batchDeleting, setBatchDeleting] = useState(false);
const commandCodeAuthWindowRef = useRef<Window | null>(null);
const commandCodeAuthTimerRef = useRef<number | null>(null);
const isOpenAICompatible = isOpenAICompatibleProvider(providerId); const isOpenAICompatible = isOpenAICompatibleProvider(providerId);
const isCcCompatible = isClaudeCodeCompatibleProvider(providerId); const isCcCompatible = isClaudeCodeCompatibleProvider(providerId);
const isCommandCode = providerId === "command-code";
const isAnthropicCompatible = const isAnthropicCompatible =
isAnthropicCompatibleProvider(providerId) && !isClaudeCodeCompatibleProvider(providerId); isAnthropicCompatibleProvider(providerId) && !isClaudeCodeCompatibleProvider(providerId);
const isCompatible = isOpenAICompatible || isAnthropicCompatible || isCcCompatible; const isCompatible = isOpenAICompatible || isAnthropicCompatible || isCcCompatible;
@@ -1436,6 +1467,257 @@ export default function ProviderDetailPage() {
setShowAddApiKeyModal(true); setShowAddApiKeyModal(true);
}, [isOAuth]); }, [isOAuth]);
const clearCommandCodeAuthTimer = useCallback(() => {
if (commandCodeAuthTimerRef.current !== null) {
window.clearTimeout(commandCodeAuthTimerRef.current);
commandCodeAuthTimerRef.current = null;
}
}, []);
useEffect(() => {
return () => {
clearCommandCodeAuthTimer();
commandCodeAuthWindowRef.current?.close?.();
};
}, [clearCommandCodeAuthTimer]);
const handleCloseAddApiKeyModal = useCallback(() => {
clearCommandCodeAuthTimer();
commandCodeAuthWindowRef.current?.close?.();
commandCodeAuthWindowRef.current = null;
setCommandCodeAuthState({
phase: "idle",
state: "",
authUrl: "",
callbackUrl: "",
expiresAt: null,
message: "",
});
setShowAddApiKeyModal(false);
}, [clearCommandCodeAuthTimer]);
const handleCommandCodeAuthApply = useCallback(
async (state: string, connectionId?: string, name?: string, setDefault?: boolean) => {
setCommandCodeAuthState((current) => ({
...current,
phase: "applying",
message: "Applying browser-approved key…",
}));
try {
const res = await fetch("/api/providers/command-code/auth/apply", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ state, connectionId, name, setDefault }),
});
const data = await res.json().catch(() => ({}));
if (!res.ok) {
const errorMessage = data.error || "Failed to apply Command Code auth";
setCommandCodeAuthState((current) => ({
...current,
phase: "error",
message: errorMessage,
}));
notify.error(errorMessage);
return false;
}
setCommandCodeAuthState((current) => ({
...current,
phase: "applied",
message: "Command Code connected",
}));
commandCodeAuthWindowRef.current?.close?.();
commandCodeAuthWindowRef.current = null;
await fetchConnections();
handleCloseAddApiKeyModal();
notify.success("Command Code connection added");
return true;
} catch (error) {
console.error("Error applying Command Code auth:", error);
setCommandCodeAuthState((current) => ({
...current,
phase: "error",
message: "Failed to apply Command Code auth",
}));
notify.error("Failed to apply Command Code auth");
return false;
}
},
[fetchConnections, handleCloseAddApiKeyModal, notify]
);
const handleStartCommandCodeAuth = useCallback(async () => {
if (commandCodeAuthState.phase === "starting" || commandCodeAuthState.phase === "polling") {
return;
}
clearCommandCodeAuthTimer();
commandCodeAuthWindowRef.current?.close?.();
const popup = window.open("about:blank", "_blank");
setCommandCodeAuthState({
phase: "starting",
state: "",
authUrl: "",
callbackUrl: "",
expiresAt: null,
message: "Opening Command Code Studio…",
});
try {
const res = await fetch("/api/providers/command-code/auth/start", {
method: "POST",
headers: { "Content-Type": "application/json" },
});
const data = await res.json().catch(() => ({}));
if (!res.ok || !data.state || !data.authUrl) {
const errorMessage = data.error || "Failed to start Command Code auth";
setCommandCodeAuthState((current) => ({
...current,
phase: "error",
message: errorMessage,
}));
notify.error(errorMessage);
popup?.close?.();
return;
}
setCommandCodeAuthState({
phase: "polling",
state: data.state,
authUrl: data.authUrl,
callbackUrl: data.callbackUrl || "",
expiresAt: data.expiresAt || null,
message: "Open the auth URL, approve access, then paste the returned key/JSON/URL below…",
});
if (popup) {
try {
popup.opener = null;
} catch {
// Ignore opener cleanup failures.
}
popup.location.href = data.authUrl;
commandCodeAuthWindowRef.current = popup;
} else {
const fallbackPopup = window.open(data.authUrl, "_blank", "noopener,noreferrer");
if (!fallbackPopup) {
setCommandCodeAuthState((current) => ({
...current,
phase: "error",
message: "Popup blocked. Please allow popups and try Command Code Connect again.",
}));
notify.error("Popup blocked. Please allow popups and try Command Code Connect again.");
return;
}
commandCodeAuthWindowRef.current = fallbackPopup;
}
const deadline = data.expiresAt ? new Date(data.expiresAt).getTime() : Date.now() + 180000;
const poll = async () => {
if (Date.now() >= deadline) {
setCommandCodeAuthState((current) => ({
...current,
phase: "expired",
message: "Command Code link expired",
}));
commandCodeAuthWindowRef.current?.close?.();
commandCodeAuthWindowRef.current = null;
notify.error("Command Code auth expired");
clearCommandCodeAuthTimer();
return;
}
try {
const statusRes = await fetch(
`/api/providers/command-code/auth/status?state=${encodeURIComponent(data.state)}`,
{ method: "GET", cache: "no-store" }
);
const statusData = await statusRes.json().catch(() => ({}));
const status = String(statusData.status || statusData.state || statusData.phase || "")
.toLowerCase()
.trim();
if (status === "expired") {
setCommandCodeAuthState((current) => ({
...current,
phase: "expired",
message: "Command Code link expired",
}));
commandCodeAuthWindowRef.current?.close?.();
commandCodeAuthWindowRef.current = null;
notify.error("Command Code auth expired");
clearCommandCodeAuthTimer();
return;
}
if (status === "applied") {
setCommandCodeAuthState((current) => ({
...current,
phase: "applied",
message: "Command Code connected",
}));
commandCodeAuthWindowRef.current?.close?.();
commandCodeAuthWindowRef.current = null;
await fetchConnections();
handleCloseAddApiKeyModal();
notify.success("Command Code connection added");
clearCommandCodeAuthTimer();
return;
}
if (status === "received") {
setCommandCodeAuthState((current) => ({
...current,
phase: "received",
message: "Browser approved, applying…",
}));
clearCommandCodeAuthTimer();
await handleCommandCodeAuthApply(
data.state,
statusData.connectionId,
statusData.name,
statusData.setDefault
);
return;
}
} catch {
// Keep polling until the contract reports a terminal state or timeout.
}
commandCodeAuthTimerRef.current = window.setTimeout(poll, 2000);
};
commandCodeAuthTimerRef.current = window.setTimeout(poll, 1000);
} catch (error) {
console.error("Error starting Command Code auth:", error);
setCommandCodeAuthState((current) => ({
...current,
phase: "error",
message: "Failed to start Command Code auth",
}));
notify.error("Failed to start Command Code auth");
popup?.close?.();
commandCodeAuthWindowRef.current = null;
clearCommandCodeAuthTimer();
}
}, [
clearCommandCodeAuthTimer,
handleCloseAddApiKeyModal,
commandCodeAuthState.phase,
fetchConnections,
handleCommandCodeAuthApply,
notify,
]);
const handleOpenCommandCodeConnect = useCallback(() => {
setShowAddApiKeyModal(true);
void handleStartCommandCodeAuth();
}, [handleStartCommandCodeAuth]);
const handleSaveApiKey = async (formData) => { const handleSaveApiKey = async (formData) => {
try { try {
const res = await fetch("/api/providers", { const res = await fetch("/api/providers", {
@@ -2950,13 +3232,44 @@ export default function ProviderDetailPage() {
)} )}
{!isCompatible ? ( {!isCompatible ? (
<> <>
<Button size="sm" icon="add" onClick={openPrimaryAddFlow}> {isCommandCode ? (
{providerSupportsPat ? "Add PAT" : t("add")} <>
</Button> <Button
{providerId === "qoder" && ( size="sm"
<Button size="sm" variant="secondary" onClick={() => setShowOAuthModal(true)}> icon="open_in_new"
Experimental OAuth loading={
</Button> commandCodeAuthState.phase === "starting" ||
commandCodeAuthState.phase === "polling" ||
commandCodeAuthState.phase === "applying"
}
onClick={handleOpenCommandCodeConnect}
>
Connect
</Button>
<Button
size="sm"
variant="secondary"
icon="add"
onClick={() => setShowAddApiKeyModal(true)}
>
Manual API key
</Button>
</>
) : (
<>
<Button size="sm" icon="add" onClick={openPrimaryAddFlow}>
{providerSupportsPat ? "Add PAT" : t("add")}
</Button>
{providerId === "qoder" && (
<Button
size="sm"
variant="secondary"
onClick={() => setShowOAuthModal(true)}
>
Experimental OAuth
</Button>
)}
</>
)} )}
</> </>
) : ( ) : (
@@ -2980,13 +3293,38 @@ export default function ProviderDetailPage() {
<p className="text-sm text-text-muted mb-4">{t("addFirstConnectionHint")}</p> <p className="text-sm text-text-muted mb-4">{t("addFirstConnectionHint")}</p>
{!isCompatible && ( {!isCompatible && (
<div className="flex items-center justify-center gap-2"> <div className="flex items-center justify-center gap-2">
<Button icon="add" onClick={openPrimaryAddFlow}> {isCommandCode ? (
{providerSupportsPat ? "Add PAT" : t("addConnection")} <>
</Button> <Button
{providerId === "qoder" && ( icon="open_in_new"
<Button variant="secondary" onClick={() => setShowOAuthModal(true)}> loading={
Experimental OAuth commandCodeAuthState.phase === "starting" ||
</Button> commandCodeAuthState.phase === "polling" ||
commandCodeAuthState.phase === "applying"
}
onClick={handleOpenCommandCodeConnect}
>
Connect
</Button>
<Button
variant="secondary"
icon="add"
onClick={() => setShowAddApiKeyModal(true)}
>
Manual API key
</Button>
</>
) : (
<>
<Button icon="add" onClick={openPrimaryAddFlow}>
{providerSupportsPat ? "Add PAT" : t("addConnection")}
</Button>
{providerId === "qoder" && (
<Button variant="secondary" onClick={() => setShowOAuthModal(true)}>
Experimental OAuth
</Button>
)}
</>
)} )}
</div> </div>
)} )}
@@ -3409,8 +3747,11 @@ export default function ProviderDetailPage() {
isCompatible={isCompatible} isCompatible={isCompatible}
isAnthropic={isAnthropicProtocolCompatible} isAnthropic={isAnthropicProtocolCompatible}
isCcCompatible={isCcCompatible} isCcCompatible={isCcCompatible}
isCommandCode={isCommandCode}
commandCodeAuthState={commandCodeAuthState}
onStartCommandCodeAuth={handleStartCommandCodeAuth}
onSave={handleSaveApiKey} onSave={handleSaveApiKey}
onClose={() => setShowAddApiKeyModal(false)} onClose={handleCloseAddApiKeyModal}
/> />
)} )}
{!isUpstreamProxyProvider && ( {!isUpstreamProxyProvider && (
@@ -5715,6 +6056,52 @@ function formatExcludedModelsInput(value: unknown): string {
.join(", "); .join(", ");
} }
function extractCommandCodeCredentialInput(value: string): string {
const trimmed = value.trim();
if (!trimmed) return "";
try {
const parsed = JSON.parse(trimmed) as unknown;
if (parsed && typeof parsed === "object") {
const record = parsed as Record<string, unknown>;
const direct = record.apiKey || record.api_key || record.key || record.token;
if (typeof direct === "string" && direct.trim()) return direct.trim();
const nested = record.data;
if (nested && typeof nested === "object") {
const nestedRecord = nested as Record<string, unknown>;
const nestedKey = nestedRecord.apiKey || nestedRecord.api_key || nestedRecord.key;
if (typeof nestedKey === "string" && nestedKey.trim()) return nestedKey.trim();
}
}
} catch {
// Not JSON; continue with URL/raw parsing.
}
try {
const url = new URL(trimmed);
const key =
url.searchParams.get("apiKey") ||
url.searchParams.get("api_key") ||
url.searchParams.get("key") ||
url.searchParams.get("token");
if (key?.trim()) return key.trim();
const hash = url.hash.replace(/^#/, "");
if (hash) {
const hashParams = new URLSearchParams(hash);
const hashKey =
hashParams.get("apiKey") ||
hashParams.get("api_key") ||
hashParams.get("key") ||
hashParams.get("token");
if (hashKey?.trim()) return hashKey.trim();
}
} catch {
// Not a URL; use the raw value.
}
return trimmed;
}
function AddApiKeyModal({ function AddApiKeyModal({
isOpen, isOpen,
provider, provider,
@@ -5722,6 +6109,9 @@ function AddApiKeyModal({
isCompatible, isCompatible,
isAnthropic, isAnthropic,
isCcCompatible, isCcCompatible,
isCommandCode,
commandCodeAuthState,
onStartCommandCodeAuth,
onSave, onSave,
onClose, onClose,
}: AddApiKeyModalProps) { }: AddApiKeyModalProps) {
@@ -5744,6 +6134,18 @@ function AddApiKeyModal({
const isWebSessionProvider = isGrokWeb || isPerplexityWeb || isBlackboxWeb || isMuseSparkWeb; const isWebSessionProvider = isGrokWeb || isPerplexityWeb || isBlackboxWeb || isMuseSparkWeb;
const isPetals = provider === "petals"; const isPetals = provider === "petals";
const apiKeyOptional = isSearxng || isPetals || isLocalSelfHostedProvider; const apiKeyOptional = isSearxng || isPetals || isLocalSelfHostedProvider;
const commandCodeAuthPhaseLabel = commandCodeAuthState
? {
idle: "Ready",
starting: "Starting…",
polling: "Waiting for browser…",
received: "Browser approved",
applying: "Applying key…",
applied: "Connected",
expired: "Link expired",
error: "Connection failed",
}[commandCodeAuthState.phase]
: null;
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
name: "", name: "",
@@ -5767,6 +6169,7 @@ function AddApiKeyModal({
const [saving, setSaving] = useState(false); const [saving, setSaving] = useState(false);
const [saveError, setSaveError] = useState<string | null>(null); const [saveError, setSaveError] = useState<string | null>(null);
const [showAdvanced, setShowAdvanced] = useState(false); const [showAdvanced, setShowAdvanced] = useState(false);
const [copiedCommandCodeField, setCopiedCommandCodeField] = useState<string | null>(null);
const apiCredentialLabel = isQoder const apiCredentialLabel = isQoder
? t("personalAccessTokenLabel") ? t("personalAccessTokenLabel")
: isWebSessionProvider : isWebSessionProvider
@@ -5811,12 +6214,15 @@ function AddApiKeyModal({
setValidating(true); setValidating(true);
setSaveError(null); setSaveError(null);
try { try {
const credentialInput = isCommandCode
? extractCommandCodeCredentialInput(formData.apiKey)
: formData.apiKey;
const res = await fetch("/api/providers/validate", { const res = await fetch("/api/providers/validate", {
method: "POST", method: "POST",
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
body: JSON.stringify({ body: JSON.stringify({
provider, provider,
apiKey: formData.apiKey, apiKey: credentialInput,
validationModelId: formData.validationModelId || undefined, validationModelId: formData.validationModelId || undefined,
customUserAgent: formData.customUserAgent.trim() || undefined, customUserAgent: formData.customUserAgent.trim() || undefined,
baseUrl: formData.baseUrl.trim() || undefined, baseUrl: formData.baseUrl.trim() || undefined,
@@ -5832,8 +6238,22 @@ function AddApiKeyModal({
} }
}; };
const copyCommandCodeValue = async (value: string | undefined, key: string) => {
if (!value) return;
try {
await navigator.clipboard.writeText(value);
setCopiedCommandCodeField(key);
window.setTimeout(() => setCopiedCommandCodeField(null), 1500);
} catch {
setSaveError("Copy failed. Select the text and copy it manually.");
}
};
const handleSubmit = async () => { const handleSubmit = async () => {
if (!provider || (!isCompatible && !apiKeyOptional && !formData.apiKey)) return; const credentialInput = isCommandCode
? extractCommandCodeCredentialInput(formData.apiKey)
: formData.apiKey;
if (!provider || (!isCompatible && !apiKeyOptional && !credentialInput)) return;
setSaving(true); setSaving(true);
setSaveError(null); setSaveError(null);
@@ -5863,7 +6283,7 @@ function AddApiKeyModal({
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
body: JSON.stringify({ body: JSON.stringify({
provider, provider,
apiKey: formData.apiKey, apiKey: credentialInput,
validationModelId: formData.validationModelId || undefined, validationModelId: formData.validationModelId || undefined,
customUserAgent: formData.customUserAgent.trim() || undefined, customUserAgent: formData.customUserAgent.trim() || undefined,
baseUrl: formData.baseUrl.trim() || undefined, baseUrl: formData.baseUrl.trim() || undefined,
@@ -5883,7 +6303,7 @@ function AddApiKeyModal({
} }
if (!isValid) { if (!isValid) {
if (apiKeyOptional && !formData.apiKey) { if (apiKeyOptional && !credentialInput) {
// Bypass validation block for local/optional providers when no key is provided // Bypass validation block for local/optional providers when no key is provided
console.debug("Validation failed but apiKey is optional; proceeding to save."); console.debug("Validation failed but apiKey is optional; proceeding to save.");
} else { } else {
@@ -5926,7 +6346,7 @@ function AddApiKeyModal({
const payload = { const payload = {
name: formData.name, name: formData.name,
apiKey: formData.apiKey.trim() || undefined, apiKey: credentialInput.trim() || undefined,
priority: formData.priority, priority: formData.priority,
testStatus: "active", testStatus: "active",
providerSpecificData: providerSpecificData:
@@ -5961,6 +6381,84 @@ function AddApiKeyModal({
</div> </div>
</div> </div>
)} )}
{isCommandCode && onStartCommandCodeAuth && (
<div className="rounded-lg border border-sky-500/20 bg-sky-500/10 px-3 py-3 text-sm">
<div className="flex items-start gap-3">
<span className="material-symbols-outlined mt-0.5 text-[18px] text-sky-500">
open_in_new
</span>
<div className="min-w-0 flex-1">
<p className="font-medium text-text-main">Browser/manual connect</p>
<p className="mt-1 text-xs text-text-muted">
Open Command Code Studio, then paste the returned key/JSON/URL into the API key
field below.
</p>
{commandCodeAuthState?.message && (
<p className="mt-2 text-xs text-text-muted">
{commandCodeAuthPhaseLabel}: {commandCodeAuthState.message}
</p>
)}
{commandCodeAuthState?.authUrl && (
<div className="mt-3 space-y-2">
<div>
<p className="mb-1 text-xs font-medium text-text-main">Auth URL</p>
<div className="flex gap-2">
<Input
value={commandCodeAuthState.authUrl}
readOnly
className="flex-1 font-mono text-xs"
/>
<Button
variant="ghost"
size="sm"
icon={copiedCommandCodeField === "authUrl" ? "check" : "content_copy"}
onClick={() =>
copyCommandCodeValue(commandCodeAuthState.authUrl, "authUrl")
}
/>
</div>
</div>
{commandCodeAuthState.callbackUrl && (
<div>
<p className="mb-1 text-xs font-medium text-text-main">Callback URL</p>
<div className="flex gap-2">
<Input
value={commandCodeAuthState.callbackUrl}
readOnly
className="flex-1 font-mono text-xs"
/>
<Button
variant="ghost"
size="sm"
icon={
copiedCommandCodeField === "callbackUrl" ? "check" : "content_copy"
}
onClick={() =>
copyCommandCodeValue(commandCodeAuthState.callbackUrl, "callbackUrl")
}
/>
</div>
</div>
)}
</div>
)}
</div>
<Button
variant="secondary"
size="sm"
icon="open_in_new"
loading={
commandCodeAuthState?.phase === "starting" ||
commandCodeAuthState?.phase === "polling" ||
commandCodeAuthState?.phase === "applying"
}
onClick={onStartCommandCodeAuth}
>
Connect in browser
</Button>
</div>
</div>
)}
<Input <Input
label={t("nameLabel")} label={t("nameLabel")}
value={formData.name} value={formData.name}

View File

@@ -0,0 +1,101 @@
import { requireManagementAuth } from "@/lib/api/requireManagementAuth";
import { consumeCommandCodeAuthSecret } from "@/lib/db/commandCodeAuth";
import {
createProviderConnection,
getProviderConnectionById,
updateProviderConnection,
} from "@/lib/db/providers";
import { sanitizeProviderSpecificDataForResponse } from "@/lib/providers/requestDefaults";
import { commandCodeApplySchema, noStoreJson, stateHashFromState } from "../shared";
function safeConnection(
connection: Record<string, unknown> | null
): Record<string, unknown> | null {
if (!connection) return null;
const result = { ...connection };
delete result.apiKey;
delete result.accessToken;
delete result.refreshToken;
delete result.idToken;
if (result.providerSpecificData) {
result.providerSpecificData = sanitizeProviderSpecificDataForResponse(
result.providerSpecificData
);
}
return result;
}
export async function POST(request: Request) {
const authError = await requireManagementAuth(request);
if (authError) return authError;
let body: unknown;
try {
body = await request.json();
} catch {
return noStoreJson({ error: "Invalid JSON body" }, { status: 400 });
}
const parsed = commandCodeApplySchema.safeParse(body);
if (!parsed.success) return noStoreJson({ error: "Invalid apply payload" }, { status: 400 });
let existing: Record<string, unknown> | null = null;
if (parsed.data.connectionId) {
existing = (await getProviderConnectionById(parsed.data.connectionId)) as Record<
string,
unknown
> | null;
if (!existing || existing.provider !== "command-code" || existing.authType !== "apikey") {
return noStoreJson({ error: "Command Code API-key connection not found" }, { status: 404 });
}
}
const consumed = consumeCommandCodeAuthSecret(stateHashFromState(parsed.data.state));
if (!consumed) {
return noStoreJson(
{ error: "No received Command Code API key for this state" },
{ status: 409 }
);
}
let connection: Record<string, unknown> | null;
if (parsed.data.connectionId && existing) {
connection = (await updateProviderConnection(parsed.data.connectionId, {
apiKey: consumed.apiKey,
name: parsed.data.name || existing.name || consumed.metadata?.keyName || "Command Code",
isActive: true,
testStatus: "unknown",
providerSpecificData: {
...((existing.providerSpecificData as Record<string, unknown> | null) || {}),
authAssist: {
userId: consumed.metadata?.userId,
userName: consumed.metadata?.userName,
keyName: consumed.metadata?.keyName,
appliedAt: consumed.appliedAt,
},
},
...(parsed.data.setDefault ? { priority: 1 } : {}),
})) as Record<string, unknown> | null;
} else {
connection = (await createProviderConnection({
provider: "command-code",
authType: "apikey",
name: parsed.data.name || consumed.metadata?.keyName || "Command Code",
apiKey: consumed.apiKey,
priority: parsed.data.setDefault ? 1 : undefined,
isActive: true,
testStatus: "unknown",
providerSpecificData: {
authAssist: {
userId: consumed.metadata?.userId,
userName: consumed.metadata?.userName,
keyName: consumed.metadata?.keyName,
appliedAt: consumed.appliedAt,
},
},
})) as Record<string, unknown> | null;
}
return noStoreJson({ connection: safeConnection(connection), status: "applied" });
}

View File

@@ -0,0 +1,67 @@
import { markCommandCodeAuthSessionReceived } from "@/lib/db/commandCodeAuth";
import {
callbackCorsHeaders,
commandCodeCallbackSchema,
MAX_CALLBACK_BODY_BYTES,
noStoreJson,
readJsonBodyWithLimit,
rejectDisallowedCallbackOrigin,
stateHashFromState,
} from "../shared";
export async function OPTIONS(request: Request) {
return new Response(null, { status: 204, headers: callbackCorsHeaders(request) });
}
export async function POST(request: Request) {
const originError = rejectDisallowedCallbackOrigin(request);
if (originError) return originError;
let body: unknown;
try {
body = await readJsonBodyWithLimit(request, MAX_CALLBACK_BODY_BYTES);
} catch (error) {
const isTooLarge = error instanceof Error && error.message === "BODY_TOO_LARGE";
return noStoreJson(
{ success: false, error: isTooLarge ? "Request body too large" : "Invalid JSON body" },
{ status: isTooLarge ? 413 : 400, headers: callbackCorsHeaders(request) }
);
}
const parsed = commandCodeCallbackSchema.safeParse(body);
if (!parsed.success) {
return noStoreJson(
{ success: false, error: "Invalid callback payload" },
{ status: 400, headers: callbackCorsHeaders(request) }
);
}
const session = markCommandCodeAuthSessionReceived({
stateHash: stateHashFromState(parsed.data.state),
apiKey: parsed.data.apiKey,
metadata: {
userId: parsed.data.userId,
userName: parsed.data.userName,
keyName: parsed.data.keyName,
},
});
if (!session || session.status !== "received") {
return noStoreJson(
{ success: false, error: "Invalid or expired state" },
{ status: 400, headers: callbackCorsHeaders(request) }
);
}
return noStoreJson(
{
success: true,
ok: true,
status: session.status,
expiresAt: session.expiresAt,
metadata: session.metadata,
},
{ headers: callbackCorsHeaders(request) }
);
}

View File

@@ -0,0 +1,120 @@
import { Buffer } from "node:buffer";
import { randomBytes } from "crypto";
import { NextResponse } from "next/server";
import { z } from "zod";
import { hashCommandCodeAuthState } from "@/lib/db/commandCodeAuth";
export const COMMAND_CODE_AUTH_TTL_MS = 15 * 60 * 1000;
export const COMMAND_CODE_STUDIO_AUTH_URL = "https://commandcode.ai/studio/auth/cli";
export const MAX_CALLBACK_BODY_BYTES = 10 * 1024;
export const COMMAND_CODE_CLI_CALLBACK_PORTS = [
5959, 5960, 5961, 5962, 5963, 5964, 5965, 5966, 5967, 5968,
] as const;
const LOCAL_CALLBACK_ORIGIN = "http://localhost:3000";
const PRODUCTION_CALLBACK_ORIGINS = ["https://commandcode.ai", "https://staging.commandcode.ai"];
export const commandCodeCallbackSchema = z.object({
apiKey: z.string().trim().min(1).max(4096),
state: z.string().trim().min(32).max(512),
userId: z.string().trim().max(256).optional(),
userName: z.string().trim().max(256).optional(),
keyName: z.string().trim().max(256).optional(),
});
export const commandCodeStateSchema = z.object({
state: z.string().trim().min(32).max(512),
});
export const commandCodeApplySchema = commandCodeStateSchema.extend({
connectionId: z.string().trim().min(1).max(256).optional(),
name: z.string().trim().min(1).max(256).optional(),
setDefault: z.boolean().optional(),
});
export function generateCommandCodeState(): string {
return randomBytes(32).toString("base64url");
}
export function stateHashFromState(state: string): string {
return hashCommandCodeAuthState(state);
}
export function noStoreJson(body: unknown, init: ResponseInit = {}): NextResponse {
return NextResponse.json(body, {
...init,
headers: {
"Cache-Control": "no-store",
...(init.headers || {}),
},
});
}
export function getAllowedCallbackOrigin(origin: string | null): string | null {
const allowed =
process.env.NODE_ENV === "production"
? PRODUCTION_CALLBACK_ORIGINS
: [...PRODUCTION_CALLBACK_ORIGINS, LOCAL_CALLBACK_ORIGIN];
return origin && allowed.includes(origin) ? origin : null;
}
export function callbackCorsHeaders(request: Request): HeadersInit {
const requestHeaders = request.headers.get("access-control-request-headers") || "content-type";
const origin = getAllowedCallbackOrigin(request.headers.get("origin"));
const headers: Record<string, string> = {
"Access-Control-Allow-Methods": "POST, OPTIONS",
"Access-Control-Allow-Headers": requestHeaders,
"Access-Control-Allow-Private-Network": "true",
"Content-Type": "application/json",
"Cache-Control": "no-store",
Vary: "Origin, Access-Control-Request-Headers",
};
if (origin) headers["Access-Control-Allow-Origin"] = origin;
return headers;
}
export function rejectDisallowedCallbackOrigin(request: Request): Response | null {
const origin = request.headers.get("origin");
if (!origin || getAllowedCallbackOrigin(origin)) return null;
return new Response(JSON.stringify({ success: false, error: "Origin not allowed" }), {
status: 403,
headers: callbackCorsHeaders(request),
});
}
export async function readJsonBodyWithLimit(request: Request, maxBytes: number): Promise<unknown> {
const reader = request.body?.getReader();
if (!reader) return request.json();
const chunks: Uint8Array[] = [];
let total = 0;
while (true) {
const { value, done } = await reader.read();
if (done) break;
if (!value) continue;
total += value.byteLength;
if (total > maxBytes) {
await reader.cancel();
throw new Error("BODY_TOO_LARGE");
}
chunks.push(value);
}
const body = new TextDecoder().decode(Buffer.concat(chunks));
return JSON.parse(body);
}
export function buildCommandCodeCliCallbackUrl(): string {
const configuredPort = process.env.COMMAND_CODE_CALLBACK_PORT || "";
const port = /^\d+$/.test(configuredPort)
? Number.parseInt(configuredPort, 10)
: COMMAND_CODE_CLI_CALLBACK_PORTS[0];
const safePort = COMMAND_CODE_CLI_CALLBACK_PORTS.includes(
port as (typeof COMMAND_CODE_CLI_CALLBACK_PORTS)[number]
)
? port
: COMMAND_CODE_CLI_CALLBACK_PORTS[0];
return `http://localhost:${safePort}/callback`;
}

View File

@@ -0,0 +1,28 @@
import { requireManagementAuth } from "@/lib/api/requireManagementAuth";
import { createPendingCommandCodeAuthSession } from "@/lib/db/commandCodeAuth";
import {
buildCommandCodeCliCallbackUrl,
COMMAND_CODE_AUTH_TTL_MS,
COMMAND_CODE_STUDIO_AUTH_URL,
generateCommandCodeState,
noStoreJson,
stateHashFromState,
} from "../shared";
export async function POST(request: Request) {
const authError = await requireManagementAuth(request);
if (authError) return authError;
const state = generateCommandCodeState();
const expiresAt = new Date(Date.now() + COMMAND_CODE_AUTH_TTL_MS).toISOString();
const stateHash = stateHashFromState(state);
createPendingCommandCodeAuthSession({ stateHash, expiresAt });
const callbackUrl = buildCommandCodeCliCallbackUrl();
const authUrl = `${COMMAND_CODE_STUDIO_AUTH_URL}?callback=${encodeURIComponent(
callbackUrl
)}&state=${encodeURIComponent(state)}`;
return noStoreJson({ state, authUrl, callbackUrl, expiresAt, mode: "manual" });
}

View File

@@ -0,0 +1,38 @@
import { requireManagementAuth } from "@/lib/api/requireManagementAuth";
import { getCommandCodeAuthSessionSafeStatus } from "@/lib/db/commandCodeAuth";
import { commandCodeStateSchema, noStoreJson, stateHashFromState } from "../shared";
async function readState(request: Request): Promise<string | null> {
const urlState = new URL(request.url).searchParams.get("state");
if (urlState) return urlState;
try {
const parsed = commandCodeStateSchema.safeParse(await request.json());
return parsed.success ? parsed.data.state : null;
} catch {
return null;
}
}
async function handle(request: Request) {
const authError = await requireManagementAuth(request);
if (authError) return authError;
const state = await readState(request);
const parsed = commandCodeStateSchema.safeParse({ state });
if (!parsed.success) return noStoreJson({ error: "Invalid state" }, { status: 400 });
const session = getCommandCodeAuthSessionSafeStatus(stateHashFromState(parsed.data.state));
if (!session) return noStoreJson({ status: "not_found" }, { status: 404 });
return noStoreJson({
status: session.status,
metadata: session.metadata,
expiresAt: session.expiresAt,
receivedAt: session.receivedAt,
appliedAt: session.appliedAt,
});
}
export const GET = handle;
export const POST = handle;

View File

@@ -0,0 +1,213 @@
import { createHash, randomUUID } from "crypto";
import { getDbInstance, rowToCamel } from "./core";
import { decrypt, encrypt } from "./encryption";
export type CommandCodeAuthStatus = "pending" | "received" | "applied" | "expired";
export interface CommandCodeAuthMetadata {
userId?: string;
userName?: string;
keyName?: string;
receivedAt?: string;
}
export interface CommandCodeAuthSafeStatus {
id: string;
stateHash: string;
status: CommandCodeAuthStatus;
metadata: CommandCodeAuthMetadata | null;
createdAt: string;
expiresAt: string;
receivedAt: string | null;
appliedAt: string | null;
updatedAt: string;
}
export interface ConsumedCommandCodeAuthSecret extends CommandCodeAuthSafeStatus {
apiKey: string;
}
type DbRunResult = { changes?: number };
type DbStatement<TRow = unknown> = {
get: (...params: unknown[]) => TRow | undefined;
all: (...params: unknown[]) => TRow[];
run: (...params: unknown[]) => DbRunResult;
};
type DbLike = {
prepare: <TRow = unknown>(sql: string) => DbStatement<TRow>;
transaction: <T extends (...args: unknown[]) => unknown>(fn: T) => T;
};
type AuthSessionRow = {
id: string;
state_hash: string;
status: CommandCodeAuthStatus;
encrypted_api_key?: string | null;
metadata_json?: string | null;
created_at: string;
expires_at: string;
received_at?: string | null;
applied_at?: string | null;
updated_at: string;
};
function db(): DbLike {
return getDbInstance() as unknown as DbLike;
}
export function hashCommandCodeAuthState(state: string): string {
return createHash("sha256").update(state, "utf8").digest("hex");
}
function nowIso(): string {
return new Date().toISOString();
}
function parseMetadata(value: string | null | undefined): CommandCodeAuthMetadata | null {
if (!value) return null;
try {
const parsed = JSON.parse(value) as CommandCodeAuthMetadata;
return parsed && typeof parsed === "object" ? parsed : null;
} catch {
return null;
}
}
function toSafeStatus(row: AuthSessionRow): CommandCodeAuthSafeStatus {
const camel = rowToCamel(row) as Record<string, unknown>;
return {
id: String(camel.id),
stateHash: String(camel.stateHash),
status: camel.status as CommandCodeAuthStatus,
metadata: parseMetadata(camel.metadataJson as string | null | undefined),
createdAt: String(camel.createdAt),
expiresAt: String(camel.expiresAt),
receivedAt: (camel.receivedAt as string | null | undefined) ?? null,
appliedAt: (camel.appliedAt as string | null | undefined) ?? null,
updatedAt: String(camel.updatedAt),
};
}
function markExpiredForState(stateHash: string, now = nowIso()): void {
db()
.prepare(
`UPDATE command_code_auth_sessions
SET status = 'expired', updated_at = ?
WHERE state_hash = ? AND status IN ('pending', 'received') AND expires_at <= ?`
)
.run(now, stateHash, now);
}
export function createPendingCommandCodeAuthSession(input: {
stateHash: string;
expiresAt: string;
}): CommandCodeAuthSafeStatus {
const id = randomUUID();
const now = nowIso();
db()
.prepare(
`INSERT INTO command_code_auth_sessions (
id, state_hash, status, encrypted_api_key, metadata_json,
created_at, expires_at, received_at, applied_at, updated_at
) VALUES (?, ?, 'pending', NULL, NULL, ?, ?, NULL, NULL, ?)`
)
.run(id, input.stateHash, now, input.expiresAt, now);
const row = db()
.prepare<AuthSessionRow>("SELECT * FROM command_code_auth_sessions WHERE id = ?")
.get(id);
if (!row) throw new Error("Failed to create Command Code auth session");
return toSafeStatus(row);
}
export function markCommandCodeAuthSessionReceived(input: {
stateHash: string;
apiKey: string;
metadata?: CommandCodeAuthMetadata;
}): CommandCodeAuthSafeStatus | null {
const now = nowIso();
markExpiredForState(input.stateHash, now);
const metadata: CommandCodeAuthMetadata = {
...(input.metadata || {}),
receivedAt: now,
};
const encryptedApiKey = encrypt(input.apiKey);
db()
.prepare(
`UPDATE command_code_auth_sessions
SET status = 'received', encrypted_api_key = ?, metadata_json = ?, received_at = ?, updated_at = ?
WHERE state_hash = ? AND status IN ('pending', 'received') AND expires_at > ?`
)
.run(encryptedApiKey, JSON.stringify(metadata), now, now, input.stateHash, now);
return getCommandCodeAuthSessionSafeStatus(input.stateHash);
}
export function getCommandCodeAuthSessionSafeStatus(
stateHash: string
): CommandCodeAuthSafeStatus | null {
markExpiredForState(stateHash);
const row = db()
.prepare<AuthSessionRow>("SELECT * FROM command_code_auth_sessions WHERE state_hash = ?")
.get(stateHash);
return row ? toSafeStatus(row) : null;
}
export function consumeCommandCodeAuthSecret(
stateHash: string
): ConsumedCommandCodeAuthSecret | null {
const database = db();
return database.transaction(() => {
const now = nowIso();
database
.prepare(
`UPDATE command_code_auth_sessions
SET status = 'expired', updated_at = ?
WHERE state_hash = ? AND status IN ('pending', 'received') AND expires_at <= ?`
)
.run(now, stateHash, now);
const row = database
.prepare<AuthSessionRow>(
`SELECT * FROM command_code_auth_sessions
WHERE state_hash = ? AND status = 'received' AND expires_at > ? AND encrypted_api_key IS NOT NULL`
)
.get(stateHash, now);
if (!row?.encrypted_api_key) return null;
const apiKey = decrypt(row.encrypted_api_key);
if (!apiKey) return null;
const result = database
.prepare(
`UPDATE command_code_auth_sessions
SET status = 'applied', encrypted_api_key = NULL, applied_at = ?, updated_at = ?
WHERE id = ? AND status = 'received'`
)
.run(now, now, row.id);
if (!result.changes) return null;
return {
...toSafeStatus({
...row,
status: "applied",
encrypted_api_key: null,
applied_at: now,
updated_at: now,
}),
apiKey,
};
})() as ConsumedCommandCodeAuthSecret | null;
}
export function cleanupExpiredCommandCodeAuthSessions(now = nowIso()): number {
const result = db()
.prepare(
`UPDATE command_code_auth_sessions
SET status = 'expired', updated_at = ?
WHERE status IN ('pending', 'received') AND expires_at <= ?`
)
.run(now, now);
return result.changes ?? 0;
}

View File

@@ -0,0 +1,19 @@
-- Migration 055: Pending browser-assisted Command Code auth sessions
CREATE TABLE IF NOT EXISTS command_code_auth_sessions (
id TEXT PRIMARY KEY,
state_hash TEXT NOT NULL UNIQUE,
status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'received', 'applied', 'expired')),
encrypted_api_key TEXT,
metadata_json TEXT,
created_at TEXT NOT NULL,
expires_at TEXT NOT NULL,
received_at TEXT,
applied_at TEXT,
updated_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_command_code_auth_sessions_state_hash
ON command_code_auth_sessions(state_hash);
CREATE INDEX IF NOT EXISTS idx_command_code_auth_sessions_status_expires
ON command_code_auth_sessions(status, expires_at);

View File

@@ -1,6 +1,7 @@
import { getRegistryEntry } from "@omniroute/open-sse/config/providerRegistry.ts"; import { randomUUID } from "node:crypto";
import { getEmbeddingProvider } from "@omniroute/open-sse/config/embeddingRegistry.ts"; import { getEmbeddingProvider } from "@omniroute/open-sse/config/embeddingRegistry.ts";
import { getRerankProvider } from "@omniroute/open-sse/config/rerankRegistry.ts"; import { getRerankProvider } from "@omniroute/open-sse/config/rerankRegistry.ts";
import { getRegistryEntry } from "@omniroute/open-sse/config/providerRegistry.ts";
import { import {
buildClaudeCodeCompatibleHeaders, buildClaudeCodeCompatibleHeaders,
buildClaudeCodeCompatibleValidationPayload, buildClaudeCodeCompatibleValidationPayload,
@@ -398,6 +399,53 @@ async function validateDirectChatProvider({ url, headers, body, providerSpecific
} }
} }
export async function validateCommandCodeProvider({ apiKey, providerSpecificData = {} }: any) {
const entry = getRegistryEntry("command-code");
const baseUrl = normalizeBaseUrl(entry?.baseUrl || "https://api.commandcode.ai");
const chatPath = entry?.chatPath || "/alpha/generate";
const url = `${baseUrl}${chatPath.startsWith("/") ? chatPath : `/${chatPath}`}`;
return validateDirectChatProvider({
url,
providerSpecificData,
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${apiKey}`,
"x-command-code-version": "0.24.1",
"x-cli-environment": "production",
"x-project-slug": "pi-cc",
"x-taste-learning": "false",
"x-co-flag": "false",
"x-session-id": randomUUID(),
},
body: {
config: {
workingDir: "/workspace",
date: new Date().toISOString().slice(0, 10),
environment: "omniroute-validation",
structure: [],
isGitRepo: false,
currentBranch: "",
mainBranch: "",
gitStatus: "",
recentCommits: [],
},
memory: "",
taste: "",
skills: null,
permissionMode: "standard",
params: {
model: providerSpecificData?.validationModelId || entry?.models?.[0]?.id || "gpt-5.4-mini",
messages: [{ role: "user", content: "test" }],
tools: [],
system: "",
max_tokens: 1,
stream: true,
},
},
});
}
async function validateClarifaiProvider({ apiKey, providerSpecificData = {} }: any) { async function validateClarifaiProvider({ apiKey, providerSpecificData = {} }: any) {
const baseUrl = const baseUrl =
normalizeBaseUrl(providerSpecificData.baseUrl) || "https://api.clarifai.com/v2/ext/openai/v1"; normalizeBaseUrl(providerSpecificData.baseUrl) || "https://api.clarifai.com/v2/ext/openai/v1";
@@ -3005,6 +3053,7 @@ export async function validateProviderApiKey({ provider, apiKey, providerSpecifi
const SPECIALTY_VALIDATORS = { const SPECIALTY_VALIDATORS = {
qoder: ({ apiKey, providerSpecificData }: any) => qoder: ({ apiKey, providerSpecificData }: any) =>
validateQoderCliPat({ apiKey, providerSpecificData }), validateQoderCliPat({ apiKey, providerSpecificData }),
"command-code": validateCommandCodeProvider,
deepgram: validateDeepgramProvider, deepgram: validateDeepgramProvider,
assemblyai: validateAssemblyAIProvider, assemblyai: validateAssemblyAIProvider,
nanobanana: validateNanoBananaProvider, nanobanana: validateNanoBananaProvider,

View File

@@ -77,6 +77,7 @@ const KNOWN_SVGS = new Set([
"brave-search", "brave-search",
"cartesia", "cartesia",
"clarifai", "clarifai",
"command-code",
"docker-model-runner", "docker-model-runner",
"droid", "droid",
"gemini-cli", "gemini-cli",

View File

@@ -184,6 +184,18 @@ export const APIKEY_PROVIDERS = {
freeNote: "$200 free credits on signup - multi-model routing gateway", freeNote: "$200 free credits on signup - multi-model routing gateway",
apiHint: "Get $200 free credits at https://agentrouter.org/register — no credit card required.", apiHint: "Get $200 free credits at https://agentrouter.org/register — no credit card required.",
}, },
"command-code": {
id: "command-code",
alias: "cmd",
name: "Command Code",
icon: "terminal",
color: "#111827",
textIcon: "CC",
website: "https://commandcode.ai/",
authHint:
"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: { openrouter: {
id: "openrouter", id: "openrouter",
alias: "openrouter", alias: "openrouter",

View File

@@ -0,0 +1,231 @@
import test from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
const TEST_DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-command-code-auth-"));
process.env.DATA_DIR = TEST_DATA_DIR;
process.env.STORAGE_ENCRYPTION_KEY = "test-command-code-auth-encryption-key";
delete process.env.INITIAL_PASSWORD;
const core = await import("../../src/lib/db/core.ts");
const startRoute = await import("../../src/app/api/providers/command-code/auth/start/route.ts");
const callbackRoute =
await import("../../src/app/api/providers/command-code/auth/callback/route.ts");
const statusRoute = await import("../../src/app/api/providers/command-code/auth/status/route.ts");
const applyRoute = await import("../../src/app/api/providers/command-code/auth/apply/route.ts");
const providersDb = await import("../../src/lib/db/providers.ts");
function resetDb() {
core.resetDbInstance();
fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true });
fs.mkdirSync(TEST_DATA_DIR, { recursive: true });
}
function jsonRequest(url: string, body: unknown, headers: HeadersInit = {}) {
return new Request(url, {
method: "POST",
headers: { "content-type": "application/json", ...headers },
body: JSON.stringify(body),
});
}
test.beforeEach(() => {
delete process.env.OMNIROUTE_PUBLIC_BASE_URL;
delete process.env.OMNIROUTE_BASE_URL;
delete process.env.BASE_URL;
delete process.env.NEXT_PUBLIC_BASE_URL;
delete process.env.COMMAND_CODE_CALLBACK_PORT;
resetDb();
});
test.after(() => {
core.resetDbInstance();
fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true });
});
test("Command Code auth assist start/callback/status/apply keeps state hash and key private", async () => {
const startResponse = await startRoute.POST(
new Request("http://localhost:20128/api/providers/command-code/auth/start", {
method: "POST",
headers: { origin: "http://localhost:20128" },
})
);
assert.equal(startResponse.status, 200);
assert.equal(startResponse.headers.get("cache-control"), "no-store");
const startBody = await startResponse.json();
assert.equal(typeof startBody.state, "string");
assert.ok(startBody.authUrl.startsWith("https://commandcode.ai/studio/auth/cli?"));
assert.ok(!("stateHash" in startBody));
const authUrl = new URL(startBody.authUrl);
const callbackUrl = authUrl.searchParams.get("callback");
assert.ok(callbackUrl);
assert.equal(callbackUrl, startBody.callbackUrl);
assert.equal(callbackUrl, "http://localhost:5959/callback");
assert.equal(startBody.mode, "manual");
const optionsResponse = await callbackRoute.OPTIONS(
new Request("http://localhost:20128/api/providers/command-code/auth/callback", {
method: "OPTIONS",
headers: {
origin: "https://commandcode.ai",
"access-control-request-headers": "content-type, x-command-code",
},
})
);
assert.equal(optionsResponse.status, 204);
assert.equal(
optionsResponse.headers.get("access-control-allow-origin"),
"https://commandcode.ai"
);
assert.equal(optionsResponse.headers.get("access-control-allow-methods"), "POST, OPTIONS");
assert.equal(optionsResponse.headers.get("access-control-allow-private-network"), "true");
assert.equal(
optionsResponse.headers.get("access-control-allow-headers"),
"content-type, x-command-code"
);
const callbackResponse = await callbackRoute.POST(
jsonRequest(
"http://localhost:20128/api/providers/command-code/auth/callback",
{
apiKey: "cc_test_secret",
state: startBody.state,
userId: "user-1",
userName: "Ada",
keyName: "Studio Key",
},
{ origin: "https://commandcode.ai" }
)
);
assert.equal(callbackResponse.status, 200);
const callbackBody = await callbackResponse.json();
assert.equal(callbackBody.success, true);
const statusResponse = await statusRoute.GET(
new Request(
`http://localhost:20128/api/providers/command-code/auth/status?state=${encodeURIComponent(
startBody.state
)}`
)
);
assert.equal(statusResponse.status, 200);
const statusBody = await statusResponse.json();
assert.equal(statusBody.status, "received");
assert.equal(statusBody.metadata.userName, "Ada");
assert.ok(!JSON.stringify(statusBody).includes("cc_test_secret"));
assert.ok(!("stateHash" in statusBody));
const applyResponse = await applyRoute.POST(
jsonRequest("http://localhost:20128/api/providers/command-code/auth/apply", {
state: startBody.state,
name: "Command Code Studio",
setDefault: true,
})
);
assert.equal(applyResponse.status, 200);
const applyBody = await applyResponse.json();
assert.equal(applyBody.status, "applied");
assert.equal(applyBody.connection.provider, "command-code");
assert.equal(applyBody.connection.authType, "apikey");
assert.ok(!JSON.stringify(applyBody).includes("cc_test_secret"));
assert.ok(!("apiKey" in applyBody.connection));
assert.ok(!("stateHash" in applyBody));
const connections = await providersDb.getProviderConnections({ provider: "command-code" });
assert.equal(connections.length, 1);
assert.equal(connections[0].apiKey, "cc_test_secret");
const secondApplyResponse = await applyRoute.POST(
jsonRequest("http://localhost:20128/api/providers/command-code/auth/apply", {
state: startBody.state,
})
);
assert.equal(secondApplyResponse.status, 409);
});
test("Command Code auth assist keeps auth URL callback on CLI localhost contract", async () => {
process.env.OMNIROUTE_PUBLIC_BASE_URL = "https://omniroute.example.com/base-path";
const startResponse = await startRoute.POST(
new Request("http://localhost:20128/api/providers/command-code/auth/start", {
method: "POST",
headers: { origin: "http://localhost:20128" },
})
);
assert.equal(startResponse.status, 200);
const startBody = await startResponse.json();
const authUrl = new URL(startBody.authUrl);
assert.equal(authUrl.searchParams.get("callback"), "http://localhost:5959/callback");
assert.equal(startBody.callbackUrl, authUrl.searchParams.get("callback"));
});
test("Command Code auth assist allows only configured CLI callback port range", async () => {
process.env.COMMAND_CODE_CALLBACK_PORT = "5962";
const configuredPortResponse = await startRoute.POST(
new Request("http://localhost:20128/api/providers/command-code/auth/start", {
method: "POST",
headers: { origin: "http://localhost:20128" },
})
);
const configuredPortBody = await configuredPortResponse.json();
assert.equal(
new URL(configuredPortBody.authUrl).searchParams.get("callback"),
"http://localhost:5962/callback"
);
resetDb();
process.env.COMMAND_CODE_CALLBACK_PORT = "20128";
const invalidPortResponse = await startRoute.POST(
new Request("http://localhost:20128/api/providers/command-code/auth/start", {
method: "POST",
headers: { origin: "http://localhost:20128" },
})
);
const invalidPortBody = await invalidPortResponse.json();
assert.equal(
new URL(invalidPortBody.authUrl).searchParams.get("callback"),
"http://localhost:5959/callback"
);
resetDb();
process.env.COMMAND_CODE_CALLBACK_PORT = "5962abc";
const partialPortResponse = await startRoute.POST(
new Request("http://localhost:20128/api/providers/command-code/auth/start", {
method: "POST",
headers: { origin: "http://localhost:20128" },
})
);
const partialPortBody = await partialPortResponse.json();
assert.equal(
new URL(partialPortBody.authUrl).searchParams.get("callback"),
"http://localhost:5959/callback"
);
});
test("Command Code callback rejects disallowed origins and oversized bodies", async () => {
const disallowed = await callbackRoute.POST(
jsonRequest(
"http://localhost:20128/api/providers/command-code/auth/callback",
{ apiKey: "secret", state: "x".repeat(32) },
{ origin: "https://evil.example" }
)
);
assert.equal(disallowed.status, 403);
assert.equal((await disallowed.json()).success, false);
assert.equal(disallowed.headers.get("access-control-allow-origin"), null);
const tooLarge = await callbackRoute.POST(
new Request("http://localhost:20128/api/providers/command-code/auth/callback", {
method: "POST",
headers: { "content-type": "application/json", origin: "https://commandcode.ai" },
body: JSON.stringify({ apiKey: "x".repeat(11 * 1024), state: "s".repeat(64) }),
})
);
assert.equal(tooLarge.status, 413);
assert.equal((await tooLarge.json()).success, false);
assert.equal(tooLarge.headers.get("access-control-allow-origin"), "https://commandcode.ai");
});

View File

@@ -0,0 +1,249 @@
import test from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
const TEST_DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-command-code-executor-"));
process.env.DATA_DIR = TEST_DATA_DIR;
const { REGISTRY, getRegistryEntry } = await import("../../open-sse/config/providerRegistry.ts");
const { CommandCodeExecutor } = await import("../../open-sse/executors/commandCode.ts");
const { getExecutor, hasSpecializedExecutor } = await import("../../open-sse/executors/index.ts");
const core = await import("../../src/lib/db/core.ts");
const originalFetch = globalThis.fetch;
const PINNED_COMMAND_CODE_MODELS = [
"claude-opus-4-7",
"claude-opus-4-6",
"claude-sonnet-4-6",
"claude-haiku-4-5-20251001",
"gpt-5.5",
"gpt-5.4",
"gpt-5.3-codex",
"gpt-5.4-mini",
"deepseek/deepseek-v4-pro",
"deepseek/deepseek-v4-flash",
"moonshotai/Kimi-K2.6",
"moonshotai/Kimi-K2.5",
"zai-org/GLM-5.1",
"zai-org/GLM-5",
"MiniMaxAI/MiniMax-M2.7",
"MiniMaxAI/MiniMax-M2.5",
"Qwen/Qwen3.6-Max-Preview",
"Qwen/Qwen3.6-Plus",
];
function commandCodeStream(lines: unknown[], { sse = false } = {}) {
const text = lines
.map((line) => {
const json = JSON.stringify(line);
return sse ? `data: ${json}\n\n` : `${json}\n`;
})
.join("");
return new Response(text, { status: 200, headers: { "Content-Type": "application/x-ndjson" } });
}
function toPlainHeaders(headers: any) {
if (headers instanceof Headers) return Object.fromEntries(headers.entries());
return Object.fromEntries(Object.entries(headers).map(([key, value]) => [key, String(value)]));
}
function parseSsePayloads(sse: string) {
return sse
.split("\n")
.filter((line) => line.startsWith("data: "))
.map((line) => line.slice(6).trim())
.filter((line) => line && line !== "[DONE]")
.map((line) => JSON.parse(line));
}
test.afterEach(() => {
globalThis.fetch = originalFetch;
});
test.after(() => {
globalThis.fetch = originalFetch;
core.resetDbInstance();
fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true });
});
test("Command Code provider catalog has pinned models and alias lookup", () => {
const entry = REGISTRY["command-code"];
assert.ok(entry);
assert.equal(entry.alias, "cmd");
assert.equal(entry.executor, "command-code");
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
);
assert.equal(getRegistryEntry("cmd"), entry);
});
test("getExecutor returns the specialized Command Code executor", () => {
assert.equal(hasSpecializedExecutor("command-code"), true);
assert.ok(getExecutor("command-code") instanceof CommandCodeExecutor);
assert.ok(getExecutor("cmd") instanceof CommandCodeExecutor);
});
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 });
return commandCodeStream([{ type: "text-delta", text: "hello" }, { type: "finish" }]);
};
const executor = getExecutor("command-code");
const { response, url, headers, transformedBody } = await executor.execute({
model: "gpt-5.4-mini",
stream: false,
credentials: { apiKey: "cc_test_key" },
body: {
stream: false,
messages: [
{ role: "system", content: "You are concise." },
{ role: "user", content: "Hi" },
],
tools: [{ type: "function", function: { name: "lookup", parameters: { type: "object" } } }],
max_tokens: 42,
},
});
assert.equal(url, "https://api.commandcode.ai/alpha/generate");
assert.equal(calls.length, 1);
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");
assert.equal(headers["x-cli-environment"], "production");
assert.equal(headers["x-project-slug"], "pi-cc");
assert.equal(headers["x-taste-learning"], "false");
assert.equal(headers["x-co-flag"], "false");
assert.equal(typeof headers["x-session-id"], "string");
const posted = JSON.parse(String(calls[0].init.body));
assert.deepEqual(posted, transformedBody);
for (const key of ["config", "memory", "taste", "skills", "permissionMode", "params"]) {
assert.ok(key in posted, `missing ${key}`);
}
assert.equal(posted.params.model, "gpt-5.4-mini");
assert.equal(posted.params.stream, true);
assert.equal(posted.params.system, "You are concise.");
assert.equal(posted.params.messages[0].role, "user");
assert.equal(posted.params.tools[0].name, "lookup");
const json = await response.json();
assert.equal(json.choices[0].message.content, "hello");
});
test("Command Code raw NDJSON stream becomes OpenAI chat SSE chunks", async () => {
globalThis.fetch = async () =>
commandCodeStream([
{ type: "text-delta", text: "Hello" },
{ type: "reasoning-delta", text: "thinking" },
{ type: "tool-call", toolCallId: "call_1", toolName: "search", input: { q: "docs" } },
{ type: "finish", finishReason: "tool-calls" },
]);
const { response } = await getExecutor("command-code").execute({
model: "gpt-5.4",
stream: true,
credentials: { apiKey: "cc_test_key" },
body: { messages: [{ role: "user", content: "Hi" }] },
});
assert.equal(response.headers.get("Content-Type"), "text/event-stream; charset=utf-8");
const sse = await response.text();
assert.match(sse, /data: \[DONE\]/);
const chunks = parseSsePayloads(sse);
assert.equal(chunks[0].object, "chat.completion.chunk");
assert.deepEqual(chunks[0].choices[0].delta, { role: "assistant" });
assert.equal(chunks[1].choices[0].delta.content, "Hello");
assert.equal(chunks[2].choices[0].delta.reasoning_content, "thinking");
assert.equal(chunks[3].choices[0].delta.tool_calls[0].function.name, "search");
assert.equal(chunks.at(-1).choices[0].finish_reason, "tool_calls");
});
test("Command Code data: SSE lines aggregate into non-stream ChatCompletion JSON", async () => {
globalThis.fetch = async () =>
commandCodeStream(
[
{ type: "text-delta", text: "Hel" },
{ type: "text-delta", text: "lo" },
{ type: "reasoning-delta", text: "because" },
{ type: "tool-call", id: "call_2", name: "lookup", arguments: { id: 7 } },
{
type: "finish",
finishReason: "max_tokens",
totalUsage: {
inputTokens: 3,
inputTokenDetails: { cacheReadTokens: 2 },
outputTokens: 5,
},
},
],
{ sse: true }
);
const { response } = await getExecutor("command-code").execute({
model: "gpt-5.4-mini",
stream: false,
credentials: { apiKey: "cc_test_key" },
body: { messages: [{ role: "user", content: "Hi" }] },
});
assert.equal(response.headers.get("Content-Type"), "application/json");
const json = await response.json();
assert.equal(json.object, "chat.completion");
assert.equal(json.choices[0].message.content, "Hello");
assert.equal(json.choices[0].message.reasoning_content, "because");
assert.equal(json.choices[0].message.tool_calls[0].function.arguments, JSON.stringify({ id: 7 }));
assert.equal(json.choices[0].finish_reason, "length");
assert.deepEqual(json.usage, { prompt_tokens: 5, completion_tokens: 5, total_tokens: 10 });
});
test("Command Code executor surfaces upstream and streamed errors", async () => {
globalThis.fetch = async () =>
new Response("bad key", { status: 401, statusText: "Unauthorized" });
const upstreamFailure = await getExecutor("command-code").execute({
model: "gpt-5.4-mini",
stream: false,
credentials: { apiKey: "cc_test_key" },
body: { messages: [{ role: "user", content: "Hi" }] },
});
assert.equal(upstreamFailure.response.status, 401);
assert.equal(await upstreamFailure.response.text(), "bad key");
globalThis.fetch = async () => commandCodeStream([{ type: "error", error: { message: "boom" } }]);
await assert.rejects(async () => {
await getExecutor("command-code").execute({
model: "gpt-5.4-mini",
stream: false,
credentials: { apiKey: "cc_test_key" },
body: { messages: [{ role: "user", content: "Hi" }] },
});
}, /boom/);
});
test("Command Code non-stream aggregation throws when the final error event lacks a trailing newline", async () => {
globalThis.fetch = async () =>
new Response(
`${JSON.stringify({ type: "text-delta", text: "Hello" })}\n${JSON.stringify({
type: "error",
error: { message: "boom" },
})}`,
{ status: 200, headers: { "Content-Type": "application/x-ndjson" } }
);
await assert.rejects(async () => {
await getExecutor("command-code").execute({
model: "gpt-5.4-mini",
stream: false,
credentials: { apiKey: "cc_test_key" },
body: { messages: [{ role: "user", content: "Hi" }] },
});
}, /boom/);
});

View File

@@ -1,8 +1,11 @@
import test from "node:test"; import test from "node:test";
import assert from "node:assert/strict"; import assert from "node:assert/strict";
const { validateProviderApiKey, validateClaudeCodeCompatibleProvider } = const {
await import("../../src/lib/providers/validation.ts"); validateProviderApiKey,
validateClaudeCodeCompatibleProvider,
validateCommandCodeProvider,
} = await import("../../src/lib/providers/validation.ts");
const originalFetch = globalThis.fetch; const originalFetch = globalThis.fetch;
@@ -10,6 +13,13 @@ test.afterEach(() => {
globalThis.fetch = originalFetch; globalThis.fetch = originalFetch;
}); });
function toPlainHeaders(headers: any) {
if (headers instanceof Headers) return Object.fromEntries(headers.entries());
return Object.fromEntries(
Object.entries(headers || {}).map(([key, value]) => [key, String(value)])
);
}
function metaAiSseText(content: string, streamingState = "DONE") { function metaAiSseText(content: string, streamingState = "DONE") {
return `event: next return `event: next
data: ${JSON.stringify({ data: ${JSON.stringify({
@@ -73,6 +83,28 @@ test("specialty provider validators cover Deepgram, AssemblyAI, NanoBanana, Elev
assert.equal(inworld.valid, true); assert.equal(inworld.valid, true);
}); });
test("validateCommandCodeProvider ignores caller baseUrl and chatPath overrides", async () => {
globalThis.fetch = async (url, init = {}) => {
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));
assert.equal(body.params.model, "command-code-validation-model");
return new Response(JSON.stringify({ ok: true }), { status: 200 });
};
const result = await validateCommandCodeProvider({
apiKey: "cc-key",
providerSpecificData: {
baseUrl: "https://evil.example/api",
chatPath: "/v1/chat/completions",
validationModelId: "command-code-validation-model",
},
});
assert.equal(result.valid, true);
});
test("specialty providers surface network failures and non-auth upstream failures", async () => { test("specialty providers surface network failures and non-auth upstream failures", async () => {
globalThis.fetch = async (url) => { globalThis.fetch = async (url) => {
const target = String(url); const target = String(url);
@@ -1876,3 +1908,63 @@ test("specialty validator rejects invalid Runway credentials", async () => {
assert.equal(runway.error, "Invalid API key"); assert.equal(runway.error, "Invalid API key");
}); });
test("validateCommandCodeProvider sends Command Code probe URL, headers, and wrapper body", async () => {
const calls: any[] = [];
globalThis.fetch = async (url, init = {}) => {
calls.push({
url: String(url),
method: init.method,
headers: toPlainHeaders(init.headers),
body: JSON.parse(String(init.body)),
});
return new Response("", { status: 400 });
};
const result = await validateCommandCodeProvider({
apiKey: "cc_test_key",
providerSpecificData: { validationModelId: "gpt-5.4-mini" },
});
assert.deepEqual(result, { valid: true, error: null });
assert.equal(calls.length, 1);
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");
assert.equal(calls[0].headers["x-command-code-version"], "0.24.1");
assert.equal(calls[0].headers["x-cli-environment"], "production");
assert.equal(calls[0].headers["x-project-slug"], "pi-cc");
assert.equal(calls[0].headers["x-taste-learning"], "false");
assert.equal(calls[0].headers["x-co-flag"], "false");
assert.equal(typeof calls[0].headers["x-session-id"], "string");
assert.equal(calls[0].body.config.environment, "omniroute-validation");
assert.equal(calls[0].body.permissionMode, "standard");
assert.equal(calls[0].body.params.model, "gpt-5.4-mini");
assert.equal(calls[0].body.params.stream, true);
assert.equal(calls[0].body.params.max_tokens, 1);
});
for (const status of [400, 422, 429]) {
test(`validateCommandCodeProvider accepts ${status} as direct validator auth success`, async () => {
globalThis.fetch = async () => new Response("", { status });
assert.deepEqual(await validateCommandCodeProvider({ apiKey: "cc_test_key" }), {
valid: true,
error: null,
});
});
}
test("validateCommandCodeProvider rejects auth failures and provider outages", async () => {
globalThis.fetch = async () => new Response("unauthorized", { status: 401 });
assert.deepEqual(await validateCommandCodeProvider({ apiKey: "bad" }), {
valid: false,
error: "Invalid API key",
});
globalThis.fetch = async () => new Response("server down", { status: 500 });
assert.deepEqual(await validateCommandCodeProvider({ apiKey: "cc_test_key" }), {
valid: false,
error: "Provider unavailable (500)",
});
});

View File

@@ -224,6 +224,45 @@ test("handleResponsesCore transforms upstream OpenAI SSE into Responses API SSE"
assert.match(sse, /data: \[DONE\]/); assert.match(sse, /data: \[DONE\]/);
}); });
test("handleResponsesCore transforms Command Code executor SSE through Responses shim", async () => {
const { call, result } = await invokeResponsesCore({
provider: "command-code",
model: "gpt-5.4-mini",
credentials: { apiKey: "cc_test_key", providerSpecificData: {} },
body: {
model: "gpt-5.4-mini",
input: "hello command code",
},
responseFactory() {
return new Response(
[
`data: ${JSON.stringify({ type: "text-delta", text: "command" })}`,
"",
`data: ${JSON.stringify({ type: "reasoning-delta", text: "thinking" })}`,
"",
`data: ${JSON.stringify({ type: "finish", finishReason: "stop" })}`,
"",
].join("\n"),
{ status: 200, headers: { "Content-Type": "application/x-ndjson" } }
);
},
});
assert.equal(result.success, true);
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");
assert.equal(call.body.params.stream, true);
const sse = await result.response.text();
assert.match(sse, /event: response\.created/);
assert.match(sse, /event: response\.output_text\.delta/);
assert.match(sse, /command/);
assert.match(sse, /event: response\.completed/);
assert.match(sse, /data: \[DONE\]/);
});
test("handleResponsesCore propagates upstream failures from chatCore unchanged", async () => { test("handleResponsesCore propagates upstream failures from chatCore unchanged", async () => {
const { result } = await invokeResponsesCore({ const { result } = await invokeResponsesCore({
body: { body: {