FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

feat(proxy): expand model catalog, per-model reasoning effort, opencode variants + production hardening by thaolaptrinh · Pull Request #2 · thaolaptrinh/commandcode-api-proxy · GitHub

2 changes: 1 addition & 1 deletion .env.example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Command Code API key (if not set, reads from ~/.commandcode/auth.json)
# Command Code API key (if not set, reads from ~/.config/commandcode-api-proxy/auth.json)
CC_API_KEY=

# Proxy config
Expand Down
86 changes: 57 additions & 29 deletions README.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,21 @@ commandcode-api-proxy auth logout

Equivalent env vars (lower priority than CLI flags):

| Env var | Description |
| ---------------- | -------------------------------------------- |
| `HOST` | Bind address |
| `PORT` | Port |
| `CC_API_KEY` | Command Code API key |
| `CC_API_BASE` | Upstream API base URL |
| `CC_CLI_VERSION` | CLI version sent upstream |
| `LOG_LEVEL` | Log level (`info`, `debug`, etc.) |
| Env var | Description |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `HOST` | Bind address |
| `PORT` | Port |
| `CC_API_KEY` | Command Code API key |
| `CC_API_BASE` | Upstream API base URL |
| `CC_CLI_VERSION` | CLI version sent upstream |
| `LOG_LEVEL` | Log level (`info`, `debug`, etc.) |
| `CORS_ORIGIN` | `Access-Control-Allow-Origin` value. `*` by default; empty string disables CORS. Restrict before exposing on a network. |

> **Security:** the proxy forwards your paid Command Code key upstream and
> accepts any auth token from clients (`proxy-managed`), so it is designed for
> **localhost** use (`HOST=127.0.0.1`). Do not bind it to `0.0.0.0` on an
> untrusted network without restricting `CORS_ORIGIN` and putting your own auth
> in front.

## Endpoints

Expand Down Expand Up @@ -140,11 +147,11 @@ npx commandcode-api-proxy --setup-claude-code

If a settings file already exists, re-run with `--force` to overwrite it.

| Claude Code tier | Env var | Maps to |
| ---------------- | -------------------------------- | --------------------------- |
| `sonnet` | `ANTHROPIC_DEFAULT_SONNET_MODEL` | `deepseek/deepseek-v4-pro` |
| `opus` | `ANTHROPIC_DEFAULT_OPUS_MODEL` | `deepseek/deepseek-v4-pro` |
| `haiku` | `ANTHROPIC_DEFAULT_HAIKU_MODEL` | `deepseek/deepseek-v4-flash`|
| Claude Code tier | Env var | Maps to |
| ---------------- | -------------------------------- | ---------------------------- |
| `sonnet` | `ANTHROPIC_DEFAULT_SONNET_MODEL` | `deepseek/deepseek-v4-pro` |
| `opus` | `ANTHROPIC_DEFAULT_OPUS_MODEL` | `deepseek/deepseek-v4-pro` |
| `haiku` | `ANTHROPIC_DEFAULT_HAIKU_MODEL` | `deepseek/deepseek-v4-flash` |

Edit those env vars in the settings file to point at other CC models. To force
every `claude-*` request to a single model regardless of tier, set
Expand All @@ -165,25 +172,46 @@ claude-proxy

Short names work in addition to full model IDs:

| Alias | Maps to |
| -------------------------------------------------- | ------------------------------ |
| `deepseek-v4-pro`, `deepseek-v4`, `deepseek-pro` | `deepseek/deepseek-v4-pro` |
| `deepseek-v4-flash`, `deepseek-flash` | `deepseek/deepseek-v4-flash` |
| `kimi-k2.6`, `kimi2.6` | `moonshotai/Kimi-K2.6` |
| `kimi-k2.5`, `kimi2.5` | `moonshotai/Kimi-K2.5` |
| `glm-5.1` | `zai-org/GLM-5.1` |
| `glm-5` | `zai-org/GLM-5` |
| `minimax-m2.7`, `minimax2.7` | `MiniMaxAI/MiniMax-M2.7` |
| `minimax-m2.5`, `minimax2.5` | `MiniMaxAI/MiniMax-M2.5` |
| `qwen3.6-max`, `qwen-3.6-max` | `Qwen/Qwen3.6-Max-Preview` |
| `qwen3.6-plus`, `qwen-3.6-plus` | `Qwen/Qwen3.6-Plus` |
| `qwen3.7-max`, `qwen-3.7-max` | `Qwen/Qwen3.7-Max` |
| `qwen3.7-plus`, `qwen-3.7-plus` | `Qwen/Qwen3.7-Plus` |
| `step3.5`, `step-3.5-flash` | `stepfun/Step-3.5-Flash` |
| `mimo-v2.5`, `mimo2.5` | `xiaomi/mimo-v2.5` |
| Alias | Maps to |
| ------------------------------------------------ | ------------------------------------- |
| `deepseek-v4-pro`, `deepseek-v4`, `deepseek-pro` | `deepseek/deepseek-v4-pro` |
| `deepseek-v4-flash`, `deepseek-flash` | `deepseek/deepseek-v4-flash` |
| `glm-5.2`, `glm5.2` | `zai-org/GLM-5.2` |
| `glm-5.2-fast`, `glm5.2-fast` | `zai-org/GLM-5.2-Fast` |
| `glm-5.1` | `zai-org/GLM-5.1` |
| `glm-5` | `zai-org/GLM-5` |
| `minimax-m3`, `minimax3` | `MiniMaxAI/MiniMax-M3` |
| `minimax-m2.7`, `minimax2.7` | `MiniMaxAI/MiniMax-M2.7` |
| `minimax-m2.5`, `minimax2.5` | `MiniMaxAI/MiniMax-M2.5` |
| `kimi-k3`, `kimi3` | `moonshotai/Kimi-K3` |
| `kimi-k2.7-code`, `kimi-code` | `moonshotai/Kimi-K2.7-Code` |
| `kimi-k2.7-highspeed`, `kimi-highspeed` | `moonshotai/Kimi-K2.7-Code-Highspeed` |
| `kimi-k2.6`, `kimi2.6` | `moonshotai/Kimi-K2.6` |
| `kimi-k2.5`, `kimi2.5` | `moonshotai/Kimi-K2.5` |
| `qwen3.7-max`, `qwen-3.7-max` | `Qwen/Qwen3.7-Max` |
| `qwen3.7-plus`, `qwen-3.7-plus` | `Qwen/Qwen3.7-Plus` |
| `qwen3.6-max`, `qwen-3.6-max` | `Qwen/Qwen3.6-Max-Preview` |
| `qwen3.6-plus`, `qwen-3.6-plus` | `Qwen/Qwen3.6-Plus` |
| `step-3.7-flash`, `step3.7` | `stepfun/Step-3.7-Flash` |
| `step3.5`, `step-3.5-flash` | `stepfun/Step-3.5-Flash` |
| `mimo-v2.5-pro`, `mimo-pro` | `xiaomi/mimo-v2.5-pro` |
| `mimo-v2.5`, `mimo2.5` | `xiaomi/mimo-v2.5` |
| `grok-4.5`, `grok4.5` | `xai/grok-4.5` |
| `nemotron`, `nemotron-3-ultra` | `nvidia/nemotron-3-ultra-550b-a55b` |
| `inkling` | `thinkingmachines/inkling` |
| `hy3` | `tencent/Hy3` |

Any model ID is passed through as-is — the proxy does not validate against a fixed list.

### Reasoning effort

Some models support a `reasoning_effort` (`low` | `medium` | `high` | `xhigh` | `max`), and
each accepts a different subset. The proxy sends the closest valid level for the model
(e.g. `deepseek-v4-pro` supports only `high`/`max`, so `low` is clipped up to `high` and
`max` is reachable). Models without a discrete effort set ignore the value. Pass the
effort via OpenAI's `reasoning_effort`, or Anthropic's `thinking.budget_tokens`
(larger budget → higher effort).

## License

MIT
8 changes: 6 additions & 2 deletions docker-compose.yml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ services:
container_name: commandcode-api-proxy
restart: unless-stopped
ports:
- "8787:8787"
# Bind host-side to localhost only so the proxy (which forwards your paid
# CC key with no real auth) is not exposed to the LAN. Remove the
# 127.0.0.1: prefix only if you intentionally want network access.
- "127.0.0.1:8787:8787"
environment:
- HOST=0.0.0.0
- PORT=8787
- CC_API_KEY=${CC_API_KEY:-}
- LOG_LEVEL=${LOG_LEVEL:-info}
volumes:
- ~/.commandcode:/home/node/.commandcode:ro
# auth.json lives at ~/.config/commandcode-api-proxy/auth.json (see auth.ts).
- ~/.config/commandcode-api-proxy:/home/node/.config/commandcode-api-proxy:ro
6 changes: 5 additions & 1 deletion src/config.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export interface Config {
ccApiBase: string;
ccVersion: string;
logLevel: string;
corsOrigin: string;
}

/**
Expand Down Expand Up @@ -81,6 +82,9 @@ export function loadConfig(): Config {
const ccApiBase = process.env.CC_API_BASE || "https://api.commandcode.ai";
const ccVersion = process.env.CC_CLI_VERSION || cachedVersion || DEFAULT_CC_VERSION;
const logLevel = process.env.LOG_LEVEL || "info";
// `*` is fine for a localhost proxy; restrict (e.g. to an origin or leave
// empty to disable) before exposing the proxy on a network.
const corsOrigin = process.env.CORS_ORIGIN ?? "*";

return { host, port, apiKey, ccApiBase, ccVersion, logLevel };
return { host, port, apiKey, ccApiBase, ccVersion, logLevel, corsOrigin };
}
111 changes: 88 additions & 23 deletions src/models.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -2,79 +2,144 @@
"builtin": [
"deepseek/deepseek-v4-pro",
"deepseek/deepseek-v4-flash",
"MiniMaxAI/MiniMax-M2.7",
"MiniMaxAI/MiniMax-M2.5",
"zai-org/GLM-5.2",
"zai-org/GLM-5.2-Fast",
"zai-org/GLM-5.1",
"zai-org/GLM-5",
"MiniMaxAI/MiniMax-M3",
"MiniMaxAI/MiniMax-M2.7",
"MiniMaxAI/MiniMax-M2.5",
"moonshotai/Kimi-K3",
"moonshotai/Kimi-K2.7-Code",
"moonshotai/Kimi-K2.7-Code-Highspeed",
"moonshotai/Kimi-K2.6",
"moonshotai/Kimi-K2.5",
"Qwen/Qwen3.7-Max",
"Qwen/Qwen3.7-Plus",
"Qwen/Qwen3.6-Max-Preview",
"Qwen/Qwen3.6-Plus",
"stepfun/Step-3.7-Flash",
"stepfun/Step-3.5-Flash",
"xiaomi/mimo-v2.5-pro",
"xiaomi/mimo-v2.5",
"Qwen/Qwen3.7-Max",
"Qwen/Qwen3.7-Plus"
"xai/grok-4.5",
"nvidia/nemotron-3-ultra-550b-a55b",
"thinkingmachines/inkling",
"tencent/Hy3"
],
"shortAliases": {
"deepseek-v4-pro": "deepseek/deepseek-v4-pro",
"deepseek-v4": "deepseek/deepseek-v4-pro",
"deepseek-pro": "deepseek/deepseek-v4-pro",
"deepseek-v4-flash": "deepseek/deepseek-v4-flash",
"deepseek-flash": "deepseek/deepseek-v4-flash",
"kimi-k2.6": "moonshotai/Kimi-K2.6",
"kimi-k2.5": "moonshotai/Kimi-K2.5",
"kimi2.6": "moonshotai/Kimi-K2.6",
"kimi2.5": "moonshotai/Kimi-K2.5",
"glm-5.2": "zai-org/GLM-5.2",
"glm5.2": "zai-org/GLM-5.2",
"glm-5.2-fast": "zai-org/GLM-5.2-Fast",
"glm5.2-fast": "zai-org/GLM-5.2-Fast",
"glm-5.1": "zai-org/GLM-5.1",
"glm-5": "zai-org/GLM-5",
"minimax-m3": "MiniMaxAI/MiniMax-M3",
"minimax3": "MiniMaxAI/MiniMax-M3",
"minimax-m2.7": "MiniMaxAI/MiniMax-M2.7",
"minimax2.7": "MiniMaxAI/MiniMax-M2.7",
"minimax-m2.5": "MiniMaxAI/MiniMax-M2.5",
"minimax2.5": "MiniMaxAI/MiniMax-M2.5",
"kimi-k3": "moonshotai/Kimi-K3",
"kimi3": "moonshotai/Kimi-K3",
"kimi-k2.7-code": "moonshotai/Kimi-K2.7-Code",
"kimi2.7-code": "moonshotai/Kimi-K2.7-Code",
"kimi-code": "moonshotai/Kimi-K2.7-Code",
"kimi-k2.7-highspeed": "moonshotai/Kimi-K2.7-Code-Highspeed",
"kimi-highspeed": "moonshotai/Kimi-K2.7-Code-Highspeed",
"kimi-k2.6": "moonshotai/Kimi-K2.6",
"kimi2.6": "moonshotai/Kimi-K2.6",
"kimi-k2.5": "moonshotai/Kimi-K2.5",
"kimi2.5": "moonshotai/Kimi-K2.5",
"qwen3.7-max": "Qwen/Qwen3.7-Max",
"qwen-3.7-max": "Qwen/Qwen3.7-Max",
"qwen3.7-plus": "Qwen/Qwen3.7-Plus",
"qwen-3.7-plus": "Qwen/Qwen3.7-Plus",
"qwen-3.6-max": "Qwen/Qwen3.6-Max-Preview",
"qwen3.6-max": "Qwen/Qwen3.6-Max-Preview",
"qwen-3.6-plus": "Qwen/Qwen3.6-Plus",
"qwen3.6-plus": "Qwen/Qwen3.6-Plus",
"step-3.7-flash": "stepfun/Step-3.7-Flash",
"step3.7": "stepfun/Step-3.7-Flash",
"step-3.5-flash": "stepfun/Step-3.5-Flash",
"step3.5": "stepfun/Step-3.5-Flash",
"mimo-v2.5-pro": "xiaomi/mimo-v2.5-pro",
"mimo-pro": "xiaomi/mimo-v2.5-pro",
"mimo-v2.5": "xiaomi/mimo-v2.5",
"mimo2.5": "xiaomi/mimo-v2.5",
"qwen3.7-max": "Qwen/Qwen3.7-Max",
"qwen-3.7-max": "Qwen/Qwen3.7-Max",
"qwen3.7-plus": "Qwen/Qwen3.7-Plus",
"qwen-3.7-plus": "Qwen/Qwen3.7-Plus"
"grok-4.5": "xai/grok-4.5",
"grok4.5": "xai/grok-4.5",
"nemotron": "nvidia/nemotron-3-ultra-550b-a55b",
"nemotron-3-ultra": "nvidia/nemotron-3-ultra-550b-a55b",
"inkling": "thinkingmachines/inkling",
"hy3": "tencent/Hy3"
},
"contextWindows": {
"deepseek/deepseek-v4-pro": 1048576,
"deepseek/deepseek-v4-flash": 1048576,
"MiniMaxAI/MiniMax-M2.7": 204800,
"MiniMaxAI/MiniMax-M2.5": 204800,
"zai-org/GLM-5.2": 1048576,
"zai-org/GLM-5.2-Fast": 1048576,
"zai-org/GLM-5.1": 200000,
"zai-org/GLM-5": 200000,
"moonshotai/Kimi-K2.6": 262144,
"moonshotai/Kimi-K2.5": 262144,
"MiniMaxAI/MiniMax-M3": 1048576,
"MiniMaxAI/MiniMax-M2.7": 204800,
"MiniMaxAI/MiniMax-M2.5": 200000,
"moonshotai/Kimi-K3": 1048576,
"moonshotai/Kimi-K2.7-Code": 256000,
"moonshotai/Kimi-K2.7-Code-Highspeed": 262000,
"moonshotai/Kimi-K2.6": 256000,
"moonshotai/Kimi-K2.5": 256000,
"Qwen/Qwen3.7-Max": 1048576,
"Qwen/Qwen3.7-Plus": 1048576,
"Qwen/Qwen3.6-Max-Preview": 262144,
"Qwen/Qwen3.6-Plus": 1048576,
"stepfun/Step-3.5-Flash": 262144,
"stepfun/Step-3.7-Flash": 256000,
"stepfun/Step-3.5-Flash": 1048576,
"xiaomi/mimo-v2.5-pro": 1048576,
"xiaomi/mimo-v2.5": 1048576,
"Qwen/Qwen3.7-Max": 1048576,
"Qwen/Qwen3.7-Plus": 1048576
"xai/grok-4.5": 500000,
"nvidia/nemotron-3-ultra-550b-a55b": 1048576,
"thinkingmachines/inkling": 256000,
"tencent/Hy3": 262144
},
"modelNames": {
"deepseek/deepseek-v4-pro": "DeepSeek V4 Pro",
"deepseek/deepseek-v4-flash": "DeepSeek V4 Flash",
"MiniMaxAI/MiniMax-M2.7": "MiniMax M2.7",
"MiniMaxAI/MiniMax-M2.5": "MiniMax M2.5",
"zai-org/GLM-5.2": "GLM-5.2",
"zai-org/GLM-5.2-Fast": "GLM-5.2 Fast",
"zai-org/GLM-5.1": "GLM-5.1",
"zai-org/GLM-5": "GLM-5",
"MiniMaxAI/MiniMax-M3": "MiniMax M3",
"MiniMaxAI/MiniMax-M2.7": "MiniMax M2.7",
"MiniMaxAI/MiniMax-M2.5": "MiniMax M2.5",
"moonshotai/Kimi-K3": "Kimi K3",
"moonshotai/Kimi-K2.7-Code": "Kimi K2.7 Code",
"moonshotai/Kimi-K2.7-Code-Highspeed": "Kimi K2.7 Code Highspeed",
"moonshotai/Kimi-K2.6": "Kimi K2.6",
"moonshotai/Kimi-K2.5": "Kimi K2.5",
"Qwen/Qwen3.7-Max": "Qwen 3.7 Max",
"Qwen/Qwen3.7-Plus": "Qwen 3.7 Plus",
"Qwen/Qwen3.6-Max-Preview": "Qwen 3.6 Max Preview",
"Qwen/Qwen3.6-Plus": "Qwen 3.6 Plus",
"stepfun/Step-3.7-Flash": "Step 3.7 Flash",
"stepfun/Step-3.5-Flash": "Step 3.5 Flash",
"xiaomi/mimo-v2.5-pro": "MiMo V2.5 Pro",
"xiaomi/mimo-v2.5": "MiMo V2.5",
"Qwen/Qwen3.7-Max": "Qwen 3.7 Max",
"Qwen/Qwen3.7-Plus": "Qwen 3.7 Plus"
"xai/grok-4.5": "Grok 4.5",
"nvidia/nemotron-3-ultra-550b-a55b": "Nemotron 3 Ultra",
"thinkingmachines/inkling": "Inkling",
"tencent/Hy3": "Hy3"
},
"reasoningEfforts": {
"deepseek/deepseek-v4-pro": ["high", "max"],
"deepseek/deepseek-v4-flash": ["high", "max"],
"zai-org/GLM-5.2": ["high", "max"],
"xai/grok-4.5": ["low", "medium", "high"]
},
"maxOutputTokens": {
"deepseek/deepseek-v4-pro": 393216,
Expand Down
24 changes: 19 additions & 5 deletions src/proxy.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,25 @@ server.listen(config.port, config.host, () => {
console.log(" Press Ctrl+C to stop\n");
});

process.on("SIGINT", () => {
console.log("\n Shutting down...");
server.close(() => process.exit(0));
// Never let an unexpected async error crash the proxy silently — log and keep
// serving. (Route handlers already catch their own errors; this is a backstop.)
process.on("unhandledRejection", (reason) => {
logger.error("[fatal] Unhandled promise rejection:", reason);
});
process.on("uncaughtException", (err) => {
logger.error("[fatal] Uncaught exception:", err);
});

process.on("SIGTERM", () => {
const shutdown = (signal: string): void => {
logger.info(`Received ${signal}, shutting down...`);
// Don't hang forever waiting on a stuck streaming connection.
const force = setTimeout(() => {
logger.warn("Forcing shutdown after 10s timeout");
process.exit(1);
}, 10_000);
force.unref();
server.close(() => process.exit(0));
});
};

process.on("SIGINT", () => shutdown("SIGINT"));
process.on("SIGTERM", () => shutdown("SIGTERM"));
Loading
Loading

Back | FazBrowse Home | New Git URL