aihezu 2.8.1 → 2.8.3

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.
package/README.md CHANGED
@@ -16,7 +16,7 @@
16
16
 
17
17
  - `ccinstall` / `install`:交互式配置 Claude(默认)或 Codex
18
18
  - Claude:默认 `https://cc.aihezu.dev/api`,企业可用 `--api` / `--api-url` 指定独立域名
19
- - Codex:默认 `https://cc.aihezu.dev/openai`,企业可用 `--api` / `--api-url` 指定独立域名;写入 `~/.codex/config.toml` 和 `auth.json`,使用 `AIHEZU_OAI_KEY`
19
+ - Codex:默认 `https://cc.aihezu.dev/openai`,企业可用 `--api` / `--api-url` 指定独立域名;写入 `~/.codex/config.toml` 和 `auth.json`,使用 `OPENAI_API_KEY`
20
20
  - `ccclear`:清理 Claude Code 缓存和配置
21
21
  - `usage`:查看 Claude Code / Codex / Gemini 用量统计(支持 `--key` 指定 API Key)
22
22
 
package/bin/aihezu.js CHANGED
@@ -52,7 +52,7 @@ function showHelp() {
52
52
  console.log(' 环境变量: ANTHROPIC_AUTH_TOKEN, ANTHROPIC_BASE_URL');
53
53
  console.log(' Codex:');
54
54
  console.log(' 配置文件: ~/.codex/config.toml, ~/.codex/auth.json');
55
- console.log(' 环境变量: AIHEZU_OAI_KEY');
55
+ console.log(' 环境变量: OPENAI_API_KEY');
56
56
  console.log(' Google Gemini:');
57
57
  console.log(' 配置文件: ~/.gemini/.env, ~/.gemini/settings.json (可选)');
58
58
  console.log(' 环境变量: GEMINI_API_KEY, GOOGLE_GEMINI_BASE_URL');
package/commands/check.js CHANGED
@@ -113,7 +113,7 @@ function checkCodex() {
113
113
  try {
114
114
  const authData = JSON.parse(fs.readFileSync(authPath, 'utf8'));
115
115
  console.log(' ✅ 文件存在');
116
- console.log(' 📝 AIHEZU_OAI_KEY:', maskSensitive(authData.AIHEZU_OAI_KEY));
116
+ console.log(' 📝 OPENAI_API_KEY:', maskSensitive(authData.OPENAI_API_KEY));
117
117
  } catch (e) {
118
118
  console.log(' ❌ 文件存在但格式错误:', e.message);
119
119
  }
@@ -123,8 +123,8 @@ function checkCodex() {
123
123
 
124
124
  // Check environment variables
125
125
  console.log('\n3️⃣ 环境变量:');
126
- const envKey = process.env.AIHEZU_OAI_KEY;
127
- console.log(' 📝 AIHEZU_OAI_KEY:', maskSensitive(envKey));
126
+ const envKey = process.env.OPENAI_API_KEY;
127
+ console.log(' 📝 OPENAI_API_KEY:', maskSensitive(envKey));
128
128
 
129
129
  // Priority explanation
130
130
  console.log('\n4️⃣ 优先级说明:');
@@ -101,27 +101,40 @@ async function configCommand(service, args = []) {
101
101
  // 3. Extra Options (Service specific)
102
102
  const options = {};
103
103
  if (service.name === 'codex') {
104
+ const knownModels = ['gpt-5-codex', 'gpt-5.3-codex', 'claude-sonnet-4.5'];
104
105
  let defaultModel = cliModel || 'gpt-5-codex';
105
106
 
106
107
  console.log('请选择模型:');
107
108
  console.log(' [1] gpt-5-codex' + (defaultModel === 'gpt-5-codex' ? ' (默认)' : ''));
108
- console.log(' [2] claude-sonnet-4.5' + (defaultModel === 'claude-sonnet-4.5' ? ' (默认)' : ''));
109
- console.log(' [3] 自定义模型名称' + (!['gpt-5-codex', 'claude-sonnet-4.5'].includes(defaultModel) ? ' (默认: ' + defaultModel + ')' : ''));
109
+ console.log(' [2] gpt-5.3-codex' + (defaultModel === 'gpt-5.3-codex' ? ' (默认)' : ''));
110
+ console.log(' [3] claude-sonnet-4.5' + (defaultModel === 'claude-sonnet-4.5' ? ' (默认)' : ''));
111
+ console.log(' [4] 自定义模型名称' + (!knownModels.includes(defaultModel) ? ' (默认: ' + defaultModel + ')' : ''));
110
112
 
111
- const choice = await askQuestion(rl, '请选择 [1/2/3]: ');
113
+ const choice = await askQuestion(rl, '请选择 [1/2/3/4]: ');
112
114
 
113
115
  if (choice === '2') {
114
- options.modelName = 'claude-sonnet-4.5';
116
+ options.modelName = 'gpt-5.3-codex';
115
117
  } else if (choice === '3') {
118
+ options.modelName = 'claude-sonnet-4.5';
119
+ } else if (choice === '4') {
116
120
  const customModel = await askQuestion(rl, '请输入自定义模型名称: ');
117
121
  options.modelName = customModel || defaultModel;
118
122
  } else if (choice === '1' || choice === '') {
119
- // Default choice (Enter or '1')
120
- if (choice === '') {
121
- options.modelName = defaultModel;
122
- } else {
123
- options.modelName = 'gpt-5-codex';
124
- }
123
+ options.modelName = (choice === '') ? defaultModel : 'gpt-5-codex';
124
+ }
125
+
126
+ // Reasoning effort selection
127
+ console.log('');
128
+ console.log('请选择推理能力:');
129
+ console.log(' [1] high (默认)');
130
+ console.log(' [2] xhigh (Extra High)');
131
+
132
+ const effortChoice = await askQuestion(rl, '请选择 [1/2]: ');
133
+
134
+ if (effortChoice === '2') {
135
+ options.reasoningEffort = 'xhigh';
136
+ } else {
137
+ options.reasoningEffort = 'high';
125
138
  }
126
139
  }
127
140
 
@@ -131,6 +144,7 @@ async function configCommand(service, args = []) {
131
144
  console.log('服务类型: ' + service.displayName);
132
145
  console.log('API 地址: ' + apiUrl);
133
146
  if (options.modelName) console.log('模型: ' + options.modelName);
147
+ if (options.reasoningEffort) console.log('推理能力: ' + options.reasoningEffort);
134
148
  console.log('API Key: ' + apiKey.substring(0, 5) + '...');
135
149
 
136
150
  console.log('');
@@ -102,27 +102,40 @@ async function installCommand(service, args = []) {
102
102
  // 3. Extra Options (Service specific)
103
103
  const options = {};
104
104
  if (service.name === 'codex') {
105
+ const knownModels = ['gpt-5-codex', 'gpt-5.3-codex', 'claude-sonnet-4.5'];
105
106
  let defaultModel = cliModel || 'gpt-5-codex';
106
-
107
+
107
108
  console.log('请选择模型:');
108
109
  console.log(' [1] gpt-5-codex' + (defaultModel === 'gpt-5-codex' ? ' (默认)' : ''));
109
- console.log(' [2] claude-sonnet-4.5' + (defaultModel === 'claude-sonnet-4.5' ? ' (默认)' : ''));
110
- console.log(' [3] 自定义模型名称' + (!['gpt-5-codex', 'claude-sonnet-4.5'].includes(defaultModel) ? ' (默认: ' + defaultModel + ')' : ''));
111
-
112
- const choice = await askQuestion(rl, '请选择 [1/2/3]: ');
113
-
110
+ console.log(' [2] gpt-5.3-codex' + (defaultModel === 'gpt-5.3-codex' ? ' (默认)' : ''));
111
+ console.log(' [3] claude-sonnet-4.5' + (defaultModel === 'claude-sonnet-4.5' ? ' (默认)' : ''));
112
+ console.log(' [4] 自定义模型名称' + (!knownModels.includes(defaultModel) ? ' (默认: ' + defaultModel + ')' : ''));
113
+
114
+ const choice = await askQuestion(rl, '请选择 [1/2/3/4]: ');
115
+
114
116
  if (choice === '2') {
115
- options.modelName = 'claude-sonnet-4.5';
117
+ options.modelName = 'gpt-5.3-codex';
116
118
  } else if (choice === '3') {
119
+ options.modelName = 'claude-sonnet-4.5';
120
+ } else if (choice === '4') {
117
121
  const customModel = await askQuestion(rl, '请输入自定义模型名称: ');
118
- options.modelName = customModel || defaultModel;
122
+ options.modelName = customModel || defaultModel;
119
123
  } else if (choice === '1' || choice === '') {
120
- // Default choice (Enter or '1')
121
- if (choice === '') {
122
- options.modelName = defaultModel;
123
- } else {
124
- options.modelName = 'gpt-5-codex';
125
- }
124
+ options.modelName = (choice === '') ? defaultModel : 'gpt-5-codex';
125
+ }
126
+
127
+ // Reasoning effort selection
128
+ console.log('');
129
+ console.log('请选择推理能力:');
130
+ console.log(' [1] high (默认)');
131
+ console.log(' [2] xhigh (Extra High)');
132
+
133
+ const effortChoice = await askQuestion(rl, '请选择 [1/2]: ');
134
+
135
+ if (effortChoice === '2') {
136
+ options.reasoningEffort = 'xhigh';
137
+ } else {
138
+ options.reasoningEffort = 'high';
126
139
  }
127
140
  }
128
141
 
@@ -132,6 +145,7 @@ async function installCommand(service, args = []) {
132
145
  console.log('服务类型: ' + service.displayName);
133
146
  console.log('API 地址: ' + apiUrl);
134
147
  if (options.modelName) console.log('模型: ' + options.modelName);
148
+ if (options.reasoningEffort) console.log('推理能力: ' + options.reasoningEffort);
135
149
  console.log('API Key: ' + apiKey.substring(0, 5) + '...');
136
150
 
137
151
  console.log('');
package/commands/usage.js CHANGED
@@ -133,7 +133,7 @@ function readCodexConfig() {
133
133
  const configs = [];
134
134
 
135
135
  // 读取环境变量
136
- const envAuthToken = process.env.AIHEZU_OAI_KEY || '';
136
+ const envAuthToken = process.env.OPENAI_API_KEY || '';
137
137
 
138
138
  // 读取配置文件中的 base_url
139
139
  let fileBaseUrl = '';
@@ -159,7 +159,7 @@ function readCodexConfig() {
159
159
  try {
160
160
  const content = fs.readFileSync(authPath, 'utf8');
161
161
  const authData = JSON.parse(content);
162
- fileAuthToken = authData.AIHEZU_OAI_KEY || '';
162
+ fileAuthToken = authData.OPENAI_API_KEY || '';
163
163
  } catch (error) {
164
164
  // 忽略错误
165
165
  }
@@ -225,7 +225,7 @@ copy C:\Windows\System32\drivers\etc\hosts.backup-20260130123456 C:\Windows\Syst
225
225
  ```bash
226
226
  echo $ANTHROPIC_BASE_URL
227
227
  echo $ANTHROPIC_AUTH_TOKEN
228
- echo $AIHEZU_OAI_KEY
228
+ echo $OPENAI_API_KEY
229
229
  echo $GEMINI_API_KEY
230
230
  ```
231
231
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aihezu",
3
- "version": "2.8.1",
3
+ "version": "2.8.3",
4
4
  "description": "AI 开发环境配置工具 - 支持 Claude Code, Codex, Google Gemini 的本地化配置、代理设置与缓存清理",
5
5
  "main": "bin/aihezu.js",
6
6
  "bin": {
package/services/codex.js CHANGED
@@ -25,82 +25,29 @@ module.exports = {
25
25
 
26
26
  // Configuration setup logic
27
27
  setupConfig: async (apiKey, apiUrl, options = {}) => {
28
- const { modelName = 'gpt-5-codex' } = options;
28
+ const { modelName = 'gpt-5-codex', reasoningEffort = 'high' } = options;
29
29
 
30
30
  if (!fs.existsSync(configDir)) {
31
31
  console.log('📁 创建 ~/.codex 目录...');
32
32
  fs.mkdirSync(configDir, { recursive: true });
33
33
  }
34
34
 
35
- // Handle config.toml
36
- let configContent = '';
37
- let existingConfig = '';
38
- let providerName = 'aihezu';
39
-
40
- if (fs.existsSync(configPath)) {
41
- existingConfig = fs.readFileSync(configPath, 'utf8');
42
-
43
- const providerMatch = existingConfig.match(/model_provider\s*=\s*"([^"]+)"/);
44
- if (providerMatch) {
45
- providerName = providerMatch[1];
46
- }
47
-
48
- // Update logic (simplified from original)
49
- let newConfig = existingConfig;
50
-
51
- // Update model
52
- const modelPattern = /^model\s*=\s*"[^"]*"/m;
53
- if (modelPattern.test(newConfig)) {
54
- newConfig = newConfig.replace(modelPattern, `model = "${modelName}"`);
55
- }
56
-
57
- // Update base_url
58
- const baseUrlPattern = new RegExp(
59
- `(\[model_providers\.${providerName}\][\s\S]*?base_url\s*=\s*)"[^"]*"`,
60
- 'm'
61
- );
62
-
63
- if (baseUrlPattern.test(newConfig)) {
64
- newConfig = newConfig.replace(baseUrlPattern, `$1"${apiUrl}"`);
65
- } else {
66
- // If provider block exists but no base_url (rare), or provider block missing
67
- const providerSectionPattern = new RegExp(`\[model_providers\.${providerName}\]`, 'm');
68
- if (providerSectionPattern.test(newConfig)) {
69
- newConfig = newConfig.replace(
70
- providerSectionPattern,
71
- `[model_providers.${providerName}]\nbase_url = "${apiUrl}"`
72
- );
73
- } else {
74
- // Append new provider
75
- newConfig = newConfig.trim() + '\n\n' +
76
- `[model_providers.${providerName}]\n` +
77
- `name = "${providerName}"\n` +
78
- `base_url = "${apiUrl}"\n` +
79
- `wire_api = "responses"\n` +
80
- `requires_openai_auth = true\n` +
81
- `env_key = "AIHEZU_OAI_KEY"\n`;
82
- }
83
- }
84
- configContent = newConfig;
85
-
86
- } else {
87
- // New Config
88
- configContent = [
89
- 'model_provider = "aihezu"',
90
- `model = "${modelName}"`,
91
- 'model_reasoning_effort = "high"',
92
- 'disable_response_storage = true',
93
- 'preferred_auth_method = "apikey"',
94
- '',
95
- '[model_providers.aihezu]',
96
- 'name = "aihezu"',
97
- `base_url = "${apiUrl}"`,
98
- 'wire_api = "responses"',
99
- 'requires_openai_auth = true',
100
- 'env_key = "AIHEZU_OAI_KEY"',
101
- ''
102
- ].join('\n');
103
- }
35
+ // Handle config.toml - always regenerate to avoid duplication issues
36
+ const providerName = 'aihezu';
37
+ const configContent = [
38
+ `model_provider = "${providerName}"`,
39
+ `model = "${modelName}"`,
40
+ `model_reasoning_effort = "${reasoningEffort}"`,
41
+ 'disable_response_storage = true',
42
+ 'preferred_auth_method = "apikey"',
43
+ '',
44
+ `[model_providers.${providerName}]`,
45
+ `name = "${providerName}"`,
46
+ `base_url = "${apiUrl}"`,
47
+ 'wire_api = "responses"',
48
+ 'requires_openai_auth = true',
49
+ ''
50
+ ].join('\n');
104
51
 
105
52
  fs.writeFileSync(configPath, configContent, 'utf8');
106
53
 
@@ -113,7 +60,9 @@ module.exports = {
113
60
  authData = {};
114
61
  }
115
62
  }
116
- authData.AIHEZU_OAI_KEY = apiKey;
63
+ // Remove legacy key if present
64
+ delete authData.AIHEZU_OAI_KEY;
65
+ authData.OPENAI_API_KEY = apiKey;
117
66
  fs.writeFileSync(authPath, JSON.stringify(authData, null, 2), 'utf8');
118
67
 
119
68
  // Fix permissions if running with sudo