Merge remote-tracking branch 'origin/main'

This commit is contained in:
musistudio
2025-08-12 22:47:13 +08:00
2 changed files with 44 additions and 1 deletions

View File

@@ -47,6 +47,27 @@ The `config.json` file has several key sections:
- **`Router`**: Used to set up routing rules. `default` specifies the default model, which will be used for all requests if no other route is configured.
- **`API_TIMEOUT_MS`**: Specifies the timeout for API calls in milliseconds.
#### Environment Variable Interpolation
Claude Code Router supports environment variable interpolation for secure API key management. You can reference environment variables in your `config.json` using either `$VAR_NAME` or `${VAR_NAME}` syntax:
```json
{
"OPENAI_API_KEY": "$OPENAI_API_KEY",
"GEMINI_API_KEY": "${GEMINI_API_KEY}",
"Providers": [
{
"name": "openai",
"api_base_url": "https://api.openai.com/v1/chat/completions",
"api_key": "$OPENAI_API_KEY",
"models": ["gpt-5", "gpt-5-mini"]
}
]
}
```
This allows you to keep sensitive API keys in environment variables instead of hardcoding them in configuration files. The interpolation works recursively through nested objects and arrays.
Here is a comprehensive example:
```json

View File

@@ -10,6 +10,26 @@ import {
} from "../constants";
import { cleanupLogFiles } from "./logCleanup";
// Function to interpolate environment variables in config values
const interpolateEnvVars = (obj: any): any => {
if (typeof obj === "string") {
// Replace $VAR_NAME or ${VAR_NAME} with environment variable values
return obj.replace(/\$\{([^}]+)\}|\$([A-Z_][A-Z0-9_]*)/g, (match, braced, unbraced) => {
const varName = braced || unbraced;
return process.env[varName] || match; // Keep original if env var doesn't exist
});
} else if (Array.isArray(obj)) {
return obj.map(interpolateEnvVars);
} else if (obj !== null && typeof obj === "object") {
const result: any = {};
for (const [key, value] of Object.entries(obj)) {
result[key] = interpolateEnvVars(value);
}
return result;
}
return obj;
};
const ensureDir = async (dir_path: string) => {
try {
await fs.access(dir_path);
@@ -51,7 +71,9 @@ export const readConfigFile = async () => {
const config = await fs.readFile(CONFIG_FILE, "utf-8");
try {
// Try to parse with JSON5 first (which also supports standard JSON)
return JSON5.parse(config);
const parsedConfig = JSON5.parse(config);
// Interpolate environment variables in the parsed config
return interpolateEnvVars(parsedConfig);
} catch (parseError) {
console.error(`Failed to parse config file at ${CONFIG_FILE}`);
console.error("Error details:", (parseError as Error).message);