@bamboo-ai/codex 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/bin/cli.js +105 -0
  2. package/package.json +46 -0
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
8
+ const core_1 = require("@bamboo-ai/core");
9
+ const path_1 = __importDefault(require("path"));
10
+ const fs_1 = __importDefault(require("fs"));
11
+ const os_1 = __importDefault(require("os"));
12
+ const API_BASE = process.env.BAMBOO_API_BASE || 'https://api.bamboonode.cn';
13
+ const AUTH_URL = process.env.BAMBOO_AUTH_URL || 'https://www.bamboonode.cn';
14
+ const CODEX_HOME = path_1.default.join(os_1.default.homedir(), '.codex');
15
+ const CODEX_AUTH_PATH = path_1.default.join(CODEX_HOME, 'auth.json');
16
+ const CODEX_CONFIG_PATH = path_1.default.join(CODEX_HOME, 'config.toml');
17
+ const PROVIDER_NAME = 'bamboo-proxy';
18
+ /**
19
+ * Sync Bamboo API key into Codex's auth.json so Codex CLI can authenticate.
20
+ * Codex reads auth.json on startup; env vars alone are not enough.
21
+ */
22
+ function syncCodexAuth(apiKey) {
23
+ fs_1.default.mkdirSync(CODEX_HOME, { recursive: true });
24
+ const auth = {
25
+ auth_mode: 'apikey',
26
+ OPENAI_API_KEY: apiKey,
27
+ };
28
+ fs_1.default.writeFileSync(CODEX_AUTH_PATH, JSON.stringify(auth, null, 2), 'utf-8');
29
+ }
30
+ /**
31
+ * Ensure a "bamboo-proxy" model provider block exists in Codex config.toml.
32
+ *
33
+ * Uses the Responses API (/v1/responses) which is the only wire_api
34
+ * supported by Codex CLI v0.101+.
35
+ */
36
+ function ensureCodexProvider(baseUrl) {
37
+ const providerSection = `[model_providers.${PROVIDER_NAME}]`;
38
+ let content = '';
39
+ if (fs_1.default.existsSync(CODEX_CONFIG_PATH)) {
40
+ content = fs_1.default.readFileSync(CODEX_CONFIG_PATH, 'utf-8');
41
+ }
42
+ // Build the provider block — wire_api defaults to "responses"
43
+ const providerBlock = [
44
+ providerSection,
45
+ `name = "Bamboo Proxy"`,
46
+ `base_url = "${baseUrl}"`,
47
+ `env_key = "OPENAI_API_KEY"`,
48
+ ].join('\n');
49
+ if (content.includes(providerSection)) {
50
+ // Replace existing block — find from header to next section or EOF
51
+ const regex = new RegExp(`\\[model_providers\\.${PROVIDER_NAME}\\][\\s\\S]*?(?=\\n\\[|$)`);
52
+ content = content.replace(regex, providerBlock + '\n');
53
+ }
54
+ else {
55
+ // Append provider block
56
+ content = content.trimEnd() + '\n\n' + providerBlock + '\n';
57
+ }
58
+ fs_1.default.writeFileSync(CODEX_CONFIG_PATH, content, 'utf-8');
59
+ }
60
+ async function main() {
61
+ try {
62
+ const authService = new core_1.AuthService(API_BASE, AUTH_URL);
63
+ const configService = new core_1.ConfigService(authService, API_BASE);
64
+ const processManager = new core_1.ProcessManager();
65
+ // 1. Resolve codex binary from PATH
66
+ const codexBin = (0, core_1.resolveBin)('codex', '@openai/codex');
67
+ // 2. Check Login
68
+ let apiKey = await authService.getToken();
69
+ if (!apiKey) {
70
+ console.log('Bamboo: Not logged in. Starting login flow...');
71
+ try {
72
+ apiKey = await authService.login();
73
+ console.log('Bamboo: Login successful!');
74
+ }
75
+ catch (err) {
76
+ console.error(`Bamboo: Login failed — ${err.message || err}`);
77
+ process.exit(1);
78
+ }
79
+ }
80
+ // 3. Get Config
81
+ console.log('Bamboo: Fetching configuration for Codex...');
82
+ const config = await configService.getConfig('codex');
83
+ // 4. Sync credentials and provider into Codex config
84
+ syncCodexAuth(config.apiKey);
85
+ ensureCodexProvider(config.baseUrl);
86
+ // 5. Prepare Environment
87
+ const env = {
88
+ OPENAI_API_KEY: config.apiKey,
89
+ OPENAI_BASE_URL: config.baseUrl,
90
+ NODE_TLS_REJECT_UNAUTHORIZED: '0',
91
+ };
92
+ // 6. Spawn — inject -c model_provider="bamboo-proxy" if user hasn't specified one
93
+ const userArgs = process.argv.slice(2);
94
+ const hasProvider = userArgs.some((a, i) => a.startsWith('model_provider=')
95
+ || (i > 0 && userArgs[i - 1] === '-c' && a.startsWith('model_provider')));
96
+ const extraArgs = hasProvider ? [] : ['-c', `model_provider="${PROVIDER_NAME}"`];
97
+ const args = [...extraArgs, ...userArgs];
98
+ await processManager.run(codexBin, args, env);
99
+ }
100
+ catch (error) {
101
+ console.error(`Bamboo Error: ${error.message || error}`);
102
+ process.exit(1);
103
+ }
104
+ }
105
+ main();
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@bamboo-ai/codex",
3
+ "version": "0.1.0",
4
+ "description": "Bamboo wrapper for OpenAI Codex CLI — auto login, auto config, one command to start",
5
+ "bin": {
6
+ "bamboo-codex": "./dist/bin/cli.js"
7
+ },
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "license": "MIT",
12
+ "engines": {
13
+ "node": ">=20.0.0"
14
+ },
15
+ "keywords": [
16
+ "bamboo",
17
+ "codex",
18
+ "openai",
19
+ "ai",
20
+ "cli"
21
+ ],
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/bamboo-ai/claude-code-router.git",
25
+ "directory": "packages/bamboo-codex"
26
+ },
27
+ "scripts": {
28
+ "build": "tsc",
29
+ "start": "node dist/bin/cli.js"
30
+ },
31
+ "dependencies": {
32
+ "@bamboo-ai/core": "workspace:*"
33
+ },
34
+ "peerDependencies": {
35
+ "@openai/codex": "*"
36
+ },
37
+ "peerDependenciesMeta": {
38
+ "@openai/codex": {
39
+ "optional": true
40
+ }
41
+ },
42
+ "devDependencies": {
43
+ "@types/node": "^20.0.0",
44
+ "typescript": "^5.0.0"
45
+ }
46
+ }