+55
-52
@@ -19,3 +19,6 @@ #!/usr/bin/env node | ||
| function getProxyScript(host, port, hasClaude, hasCodex, hasGemini) { | ||
| function getProxyScript(host, port, claudePath, codexPath, geminiPath) { | ||
| const hasClaude = !!claudePath; | ||
| const hasCodex = !!codexPath; | ||
| const hasGemini = !!geminiPath; | ||
| return `#!/usr/bin/env python3 | ||
@@ -30,2 +33,5 @@ import json, subprocess, time, sys, uuid, shutil | ||
| HAS_GEMINI = ${hasGemini ? 'True' : 'False'} | ||
| CLAUDE_PATH = "${claudePath || ''}" | ||
| CODEX_PATH = "${codexPath || ''}" | ||
| GEMINI_PATH = "${geminiPath || ''}" | ||
@@ -39,3 +45,3 @@ def log(msg): | ||
| log(f"Running claude with prompt: {prompt[:100]}...") | ||
| cmd = ["claude", "--print", "--output-format", "text", "--permission-mode", "bypassPermissions", prompt] | ||
| cmd = [CLAUDE_PATH, "--print", "--output-format", "text", "--permission-mode", "bypassPermissions", prompt] | ||
| p = subprocess.run(cmd, capture_output=True, text=True, timeout=300) | ||
@@ -53,3 +59,3 @@ out = (p.stdout or "").strip() | ||
| log(f"Running codex with prompt: {prompt[:100]}...") | ||
| cmd = ["codex", "--full-auto", "--quiet", prompt] | ||
| cmd = [CODEX_PATH, "--full-auto", "--quiet", prompt] | ||
| p = subprocess.run(cmd, capture_output=True, text=True, timeout=300) | ||
@@ -67,3 +73,3 @@ out = (p.stdout or "").strip() | ||
| log(f"Running gemini with prompt: {prompt[:100]}...") | ||
| cmd = ["gemini", "-p", prompt, "-o", "text", "--yolo"] | ||
| cmd = [GEMINI_PATH, "-p", prompt, "-o", "text", "--yolo"] | ||
| p = subprocess.run(cmd, capture_output=True, text=True, timeout=300) | ||
@@ -478,10 +484,9 @@ out = (p.stdout or "").strip() | ||
| let hasClaude = false; | ||
| let hasCodex = false; | ||
| let hasGemini = false; | ||
| let claudePath = null; | ||
| let codexPath = null; | ||
| let geminiPath = null; | ||
| try { | ||
| run('which claude', { silent: true }); | ||
| console.log(' ✓ 已找到 Claude Code CLI'); | ||
| hasClaude = true; | ||
| claudePath = run('which claude', { silent: true }).trim(); | ||
| console.log(` ✓ 已找到 Claude Code CLI: ${claudePath}`); | ||
| } catch { | ||
@@ -492,5 +497,4 @@ console.log(' ○ 未找到 Claude Code CLI'); | ||
| try { | ||
| run('which codex', { silent: true }); | ||
| console.log(' ✓ 已找到 Codex CLI'); | ||
| hasCodex = true; | ||
| codexPath = run('which codex', { silent: true }).trim(); | ||
| console.log(` ✓ 已找到 Codex CLI: ${codexPath}`); | ||
| } catch { | ||
@@ -501,5 +505,4 @@ console.log(' ○ 未找到 Codex CLI'); | ||
| try { | ||
| run('which gemini', { silent: true }); | ||
| console.log(' ✓ 已找到 Gemini CLI'); | ||
| hasGemini = true; | ||
| geminiPath = run('which gemini', { silent: true }).trim(); | ||
| console.log(` ✓ 已找到 Gemini CLI: ${geminiPath}`); | ||
| } catch { | ||
@@ -509,3 +512,3 @@ console.log(' ○ 未找到 Gemini CLI'); | ||
| if (!hasClaude && !hasCodex && !hasGemini) { | ||
| if (!claudePath && !codexPath && !geminiPath) { | ||
| console.error('\n ✗ 至少需要安装一个 CLI 工具:'); | ||
@@ -557,9 +560,9 @@ console.error(' - Claude Code CLI: npm i -g @anthropic-ai/claude-code'); | ||
| ensureDir(DATA_DIR); | ||
| fs.writeFileSync(PROXY_SCRIPT_PATH, getProxyScript(proxyHost, proxyPort, hasClaude, hasCodex, hasGemini)); | ||
| fs.writeFileSync(PROXY_SCRIPT_PATH, getProxyScript(proxyHost, proxyPort, claudePath, codexPath, geminiPath)); | ||
| fs.chmodSync(PROXY_SCRIPT_PATH, '755'); | ||
| console.log(` ✓ 已安装: ${PROXY_SCRIPT_PATH}`); | ||
| console.log(` ✓ 绑定地址: ${proxyHost}:${proxyPort}`); | ||
| if (hasClaude) console.log(' ✓ Claude Code CLI -> Anthropic API'); | ||
| if (hasCodex) console.log(' ✓ Codex CLI -> OpenAI API'); | ||
| if (hasGemini) console.log(' ✓ Gemini CLI -> OpenAI API (model: gemini-*)'); | ||
| if (claudePath) console.log(' ✓ Claude Code CLI -> Anthropic API'); | ||
| if (codexPath) console.log(' ✓ Codex CLI -> OpenAI API'); | ||
| if (geminiPath) console.log(' ✓ Gemini CLI -> OpenAI API (model: gemini-*)'); | ||
@@ -611,5 +614,5 @@ // Setup systemd service (Linux only) | ||
| config.proxyPort = proxyPort; | ||
| config.hasClaude = hasClaude; | ||
| config.hasCodex = hasCodex; | ||
| config.hasGemini = hasGemini; | ||
| config.claudePath = claudePath; | ||
| config.codexPath = codexPath; | ||
| config.geminiPath = geminiPath; | ||
| saveConfig(config); | ||
@@ -620,9 +623,9 @@ | ||
| console.log(`\n📡 API 端点:`); | ||
| if (hasClaude) { | ||
| if (claudePath) { | ||
| console.log(` Anthropic: http://${displayHost}:${proxyPort}/v1/messages`); | ||
| } | ||
| if (hasCodex || hasGemini) { | ||
| if (codexPath || geminiPath) { | ||
| console.log(` OpenAI: http://${displayHost}:${proxyPort}/v1/chat/completions`); | ||
| if (hasCodex) console.log(' (model: codex, gpt-* -> Codex CLI)'); | ||
| if (hasGemini) console.log(' (model: gemini-* -> Gemini CLI)'); | ||
| if (codexPath) console.log(' (model: codex, gpt-* -> Codex CLI)'); | ||
| if (geminiPath) console.log(' (model: gemini-* -> Gemini CLI)'); | ||
| } | ||
@@ -905,12 +908,12 @@ if (isRemote) { | ||
| // Get CLI availability from config or re-detect | ||
| let hasClaude = config.hasClaude ?? false; | ||
| let hasCodex = config.hasCodex ?? false; | ||
| let hasGemini = config.hasGemini ?? false; | ||
| // Get CLI paths from config or re-detect | ||
| let claudePath = config.claudePath || null; | ||
| let codexPath = config.codexPath || null; | ||
| let geminiPath = config.geminiPath || null; | ||
| // Re-detect if not in config | ||
| if (!config.hasClaude && !config.hasCodex && !config.hasGemini) { | ||
| try { run('which claude', { silent: true }); hasClaude = true; } catch {} | ||
| try { run('which codex', { silent: true }); hasCodex = true; } catch {} | ||
| try { run('which gemini', { silent: true }); hasGemini = true; } catch {} | ||
| if (!claudePath && !codexPath && !geminiPath) { | ||
| try { claudePath = run('which claude', { silent: true }).trim(); } catch {} | ||
| try { codexPath = run('which codex', { silent: true }).trim(); } catch {} | ||
| try { geminiPath = run('which gemini', { silent: true }).trim(); } catch {} | ||
| } | ||
@@ -921,3 +924,3 @@ | ||
| // Update proxy script | ||
| fs.writeFileSync(PROXY_SCRIPT_PATH, getProxyScript(newHost, currentPort, hasClaude, hasCodex, hasGemini)); | ||
| fs.writeFileSync(PROXY_SCRIPT_PATH, getProxyScript(newHost, currentPort, claudePath, codexPath, geminiPath)); | ||
| console.log(` ✓ 已更新代理脚本: ${newHost}`); | ||
@@ -927,5 +930,5 @@ | ||
| config.proxyHost = newHost; | ||
| config.hasClaude = hasClaude; | ||
| config.hasCodex = hasCodex; | ||
| config.hasGemini = hasGemini; | ||
| config.claudePath = claudePath; | ||
| config.codexPath = codexPath; | ||
| config.geminiPath = geminiPath; | ||
| saveConfig(config); | ||
@@ -994,11 +997,11 @@ | ||
| // Get CLI availability from config or re-detect | ||
| let hasClaude = config.hasClaude ?? false; | ||
| let hasCodex = config.hasCodex ?? false; | ||
| let hasGemini = config.hasGemini ?? false; | ||
| // Get CLI paths from config or re-detect | ||
| let claudePath = config.claudePath || null; | ||
| let codexPath = config.codexPath || null; | ||
| let geminiPath = config.geminiPath || null; | ||
| if (!config.hasClaude && !config.hasCodex && !config.hasGemini) { | ||
| try { run('which claude', { silent: true }); hasClaude = true; } catch {} | ||
| try { run('which codex', { silent: true }); hasCodex = true; } catch {} | ||
| try { run('which gemini', { silent: true }); hasGemini = true; } catch {} | ||
| if (!claudePath && !codexPath && !geminiPath) { | ||
| try { claudePath = run('which claude', { silent: true }).trim(); } catch {} | ||
| try { codexPath = run('which codex', { silent: true }).trim(); } catch {} | ||
| try { geminiPath = run('which gemini', { silent: true }).trim(); } catch {} | ||
| } | ||
@@ -1017,3 +1020,3 @@ | ||
| // Update proxy script | ||
| fs.writeFileSync(PROXY_SCRIPT_PATH, getProxyScript(proxyHost, newPort, hasClaude, hasCodex, hasGemini)); | ||
| fs.writeFileSync(PROXY_SCRIPT_PATH, getProxyScript(proxyHost, newPort, claudePath, codexPath, geminiPath)); | ||
| console.log(` ✓ 已更新代理脚本: 端口 ${newPort}`); | ||
@@ -1023,5 +1026,5 @@ | ||
| config.proxyPort = newPort; | ||
| config.hasClaude = hasClaude; | ||
| config.hasCodex = hasCodex; | ||
| config.hasGemini = hasGemini; | ||
| config.claudePath = claudePath; | ||
| config.codexPath = codexPath; | ||
| config.geminiPath = geminiPath; | ||
| saveConfig(config); | ||
@@ -1028,0 +1031,0 @@ |
+1
-1
| { | ||
| "name": "apixcode", | ||
| "version": "1.0.1", | ||
| "version": "1.0.2", | ||
| "description": "One-command setup to proxy Claude Code, Codex, and Gemini CLI as API endpoints", | ||
@@ -5,0 +5,0 @@ "bin": { |
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 3 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 3 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
38257
0.69%934
0.32%