@kikkimo/claude-launcher 2.0.0 → 2.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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,97 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.1.0] - 2025-10-27
9
+
10
+ ### Added
11
+ - **GLM (ZhiPu AI) Provider Support**: Full integration for ZhiPu AI's GLM models with two provider options:
12
+ - `zhipu`: For mainland China users (智谱清言)
13
+ - `zai`: For international users (Z.ai Global)
14
+ - Support for GLM-4.5 and GLM-4.6 models
15
+ - Extended timeout configuration (50 minutes) for large response handling
16
+ - Optimized network traffic settings for better performance
17
+ - **Moonshot Provider Enhancements**: Added extended timeout configuration and traffic optimization for Moonshot AI provider
18
+ - **Enhanced Ctrl+C Interaction**: Comprehensive Ctrl+C handling with four distinct scenarios:
19
+ - Basic trigger with warning message display
20
+ - Auto-cancel after 3-second timeout
21
+ - Double Ctrl+C for immediate exit confirmation
22
+ - Any other key press to cancel warning and continue operation
23
+ - **StdinManager Centralized Control**: New singleton class for unified stdin state management:
24
+ - Scope-based stdin acquisition with automatic cleanup
25
+ - Detach/reattach mechanism for proper scope isolation
26
+ - Suspension API for child process coordination
27
+ - Comprehensive Ctrl+C state tracking and handling
28
+ - **Provider-specific Configuration System**: Dynamic provider configuration framework:
29
+ - Flexible environment variable configuration per provider
30
+ - Provider-specific optimization display with validation
31
+ - Internationalized provider notes and recommendations
32
+ - **Complete i18n Coverage**: Extended internationalization support to all supported languages (English, Simplified Chinese, Traditional Chinese, German, French, Spanish, Italian, Portuguese, Japanese, Korean, Russian):
33
+ - Provider optimization messages (timeout, traffic control, custom variables)
34
+ - Provider-specific notes and recommendations
35
+ - Consistent terminology across all supported languages
36
+ - **Automated Test Suites**: Comprehensive test coverage for stdin management:
37
+ - Interactive test scripts for manual validation
38
+ - Automated test scripts for CI/CD integration
39
+ - Test fixture files for isolated testing
40
+
41
+ ### Changed
42
+ - **Provider Configuration Architecture**: Refactored from hardcoded switch statements to dynamic config lookup system
43
+ - **Stdin Operations**: Migrated all stdin operations to use centralized StdinManager:
44
+ - Menu navigation
45
+ - Interactive tables
46
+ - Prompt inputs
47
+ - Confirmation dialogs
48
+ - Password input
49
+ - **Console Control Handover**: Redesigned parent-child process coordination:
50
+ - Clean console relinquishment before launching Claude Code
51
+ - Suspension-aware SIGINT handling
52
+ - Proper console restoration after child process exit
53
+ - **Error Handling**: Unified error handling with `handleLaunchFailure` function
54
+ - **Ctrl+C Monitoring**: Disabled during Claude Code subprocess launch to prevent interception conflicts
55
+ - **Test Configuration Files**: Renamed test-config.json to test-config.fixture for better semantic clarity
56
+
57
+ ### Fixed
58
+ - **Stdin State Management**: Resolved critical hanging issues in CLI interaction:
59
+ - Fixed Promise deadlocks caused by cross-scope listener interference
60
+ - Eliminated dangerous `removeAllListeners` calls that destroyed active listeners
61
+ - Added proper timeout handling (60 seconds) for user input operations
62
+ - Fixed redundant isPaused check that incorrectly tested both property and method
63
+ - **Listener Conflicts**: Prevented stdin listener conflicts between nested scopes:
64
+ - Implemented scope-aware listener management
65
+ - Added detach/reattach pattern for safe scope transitions
66
+ - Tracked active scope for accurate nested scope handling
67
+ - Fixed waitForKey listener removal bug causing Promise hangs on Ctrl+C
68
+ - **Password Input**: Properly cleanup and reject Promise on Ctrl+C to prevent resource leaks
69
+ - **Input Processing**: Fixed consecutive operation hangs (e.g., API switch followed by deletion)
70
+ - **Ctrl+C Reliability**: Enhanced Ctrl+C responsiveness across all interfaces with proper state tracking
71
+ - **Terminal State Cleanup**: Improved stdin cleanup before and after Claude Code launch
72
+ - **Character Encoding**: Replaced mojibake characters (����, ��) with proper Unicode glyphs (↑↓, →) in menu
73
+ - **ANSI Escape Sequences**: Added TTY checks to prevent ANSI codes from polluting non-TTY output (logs, CI/CD)
74
+ - **Global Signal Handlers**: Removed dangerous `removeAllListeners('SIGINT/SIGTERM')` calls that could break other modules
75
+ - **Timeout Display**: Added validation for API_TIMEOUT_MS parsing to prevent NaN display in provider optimizations
76
+ - **Test File Tracking**: Removed incorrect .gitignore rules that prevented test files from being tracked
77
+ - **Code Quality**: Removed unused variables and dead code from test files
78
+
79
+ ### Security
80
+ - **Enhanced Secret Masking**: Expanded environment variable masking to detect and hide:
81
+ - API tokens, keys, secrets
82
+ - Passwords, credentials, authentication tokens
83
+ - Case-insensitive pattern matching for reliable detection
84
+ - Applied masking to both base and custom provider environment variables
85
+ - **Consistent Security Protection**: Unified secret masking across all environment variable displays
86
+
87
+ ### Refactored
88
+ - **Provider Environment Variables**: Moved from inline switch statements to provider configuration objects
89
+ - **Stdin Management**: Complete migration to centralized StdinManager pattern across all modules
90
+ - **Launch Logic**: Restructured Claude Code launching with clear control handover phases
91
+ - **State Restoration**: Eliminated duplicate state restoration in StdinScope.release() for cleaner control flow
92
+ - **Test Organization**: Improved test file naming conventions and structure
93
+
94
+ ### Documentation
95
+ - **README Updates**: Documented GLM API support in both English and Chinese versions
96
+ - **Provider Documentation**: Added comprehensive provider-specific feature descriptions
97
+ - **Configuration Guide**: Enhanced API configuration documentation with provider-specific details
98
+
8
99
  ## [2.0.0] - 2025-09-21
9
100
 
10
101
  ### Added
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Claude Launcher
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/@kikkimo/claude-launcher.svg?style=flat-square)](https://www.npmjs.com/package/@kikkimo/claude-launcher) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](https://opensource.org/licenses/MIT) [![Node.js Version](https://img.shields.io/badge/node-%3E%3D20.0.0-brightgreen.svg?style=flat-square)](https://nodejs.org/) [![npm downloads](https://img.shields.io/npm/dm/@kikkimo/claude-launcher.svg?style=flat-square)](https://www.npmjs.com/package/@kikkimo/claude-launcher) [![DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/kikkimo/claude-launcher)
4
+
3
5
  An elegant interactive launcher for Claude Code with a beautiful Claude-style interface and comprehensive third-party API management. Launch Claude Code with various configurations through an intuitive multilingual command-line menu.
4
6
 
5
7
  ## 📖 Documentation
@@ -13,7 +15,7 @@ An elegant interactive launcher for Claude Code with a beautiful Claude-style in
13
15
  - Claude-style interface with authentic orange/amber color scheme
14
16
  - Arrow key navigation with smooth menu transitions
15
17
  - Interactive tables for API selection and management
16
- - Multi-language support (8 languages including English, Chinese, German, French, Japanese, Korean, Russian, Spanish)
18
+ - Multi-language support (English, Simplified Chinese, Traditional Chinese, German, French, Spanish, Italian, Portuguese, Japanese, Korean, Russian)
17
19
 
18
20
  ### 🔐 **Advanced Security**
19
21
  - AES-256-CBC encryption for all sensitive data
@@ -23,7 +25,7 @@ An elegant interactive launcher for Claude Code with a beautiful Claude-style in
23
25
  - Strong password requirements and validation
24
26
 
25
27
  ### 🚀 **Third-party API Management**
26
- - Full support for multiple third-party API providers
28
+ - Full support for multiple third-party API providers (OpenAI, Anthropic, DeepSeek, Kimi, GLM (ZhiPu AI), and more)
27
29
  - Interactive API configuration with validation
28
30
  - API usage statistics and tracking
29
31
  - Secure configuration backup and restore
@@ -50,7 +52,7 @@ An elegant interactive launcher for Claude Code with a beautiful Claude-style in
50
52
  ```
51
53
 
52
54
  3. **First-time setup:** The launcher will guide you through:
53
- - Language selection (8 languages available)
55
+ - Language selection (11 languages available)
54
56
  - Security setup (password configuration for import/export)
55
57
  - Third-party API configuration (if desired)
56
58
 
@@ -84,7 +86,7 @@ node claude-launcher
84
86
  3. **Launch Claude Code with Third-party API** - Use configured third-party API
85
87
  4. **Launch Claude Code with Third-party API (Skip Permissions)** - Combine third-party API with permission skipping
86
88
  5. **Third-party API Management** - Configure, switch, remove APIs, view statistics
87
- 6. **Language Settings** - Switch between 8 supported languages
89
+ 6. **Language Settings** - Switch between 11 supported languages
88
90
  7. **Version Update Check** - Check for launcher updates
89
91
  8. **Exit** - Close the launcher
90
92
 
@@ -146,7 +148,7 @@ Claude Launcher 2.0 uses an advanced configuration system:
146
148
 
147
149
  ### First-time Setup Process
148
150
 
149
- 1. **Language Selection**: Choose from 8 supported languages
151
+ 1. **Language Selection**: Choose from 11 supported languages
150
152
  2. **Security Setup**:
151
153
  - Set up password protection for import/export (recommended)
152
154
  - Or skip for basic usage (limited features)
@@ -156,10 +158,11 @@ Claude Launcher 2.0 uses an advanced configuration system:
156
158
 
157
159
  Configure any third-party API provider through the interactive interface:
158
160
 
159
- - **Supported Providers**: OpenAI, Anthropic, Custom APIs, and more
161
+ - **Supported Providers**: OpenAI, Anthropic, DeepSeek, Kimi, GLM (ZhiPu AI), and custom APIs
160
162
  - **Secure Storage**: All API tokens encrypted before storage
161
163
  - **Validation**: Real-time validation of URLs, tokens, and models
162
164
  - **Usage Tracking**: Monitor API usage statistics
165
+ - **Provider-specific Features**: Optimized configuration for each provider with helpful notes and recommendations
163
166
 
164
167
  ### Configuration Import/Export
165
168
 
package/claude-launcher CHANGED
@@ -7,16 +7,26 @@
7
7
 
8
8
  /**
9
9
  * Force complete stdin reset to prevent navigation issues
10
+ * Note: This function should only reset state, not remove listeners
11
+ * that might be used by other modules
10
12
  */
11
13
  function forceStdinCleanup() {
12
14
  try {
13
15
  if (process.stdin.isTTY) {
16
+ // Only reset mode, don't remove listeners that might be in use
14
17
  process.stdin.setRawMode(false);
15
- process.stdin.removeAllListeners('data');
16
- process.stdin.pause();
18
+ // NOTE: Removed removeAllListeners to prevent conflicts
19
+ // Each module should manage its own listeners
20
+ // Only pause if not already paused (isPaused is a method, not a property)
21
+ if (!process.stdin.isPaused()) {
22
+ process.stdin.pause();
23
+ }
17
24
  }
18
25
  } catch (error) {
19
- // Ignore cleanup errors
26
+ // Ignore cleanup errors but log for debugging
27
+ if (process.env.DEBUG_STDIN) {
28
+ console.error('[DEBUG] forceStdinCleanup error:', error.message);
29
+ }
20
30
  }
21
31
  }
22
32
 
@@ -1113,6 +1123,50 @@ process.on('SIGTERM', () => {
1113
1123
  process.exit(0);
1114
1124
  });
1115
1125
 
1126
+ // Global SIGINT handler (Ctrl+C) - fallback for non-raw mode Ctrl+C
1127
+ // In raw mode, Ctrl+C is handled by StdinManager directly
1128
+ // This handler catches Ctrl+C in line mode (e.g., during readline input)
1129
+ const stdinManager = require('./lib/utils/stdin-manager');
1130
+
1131
+ // Flag to prevent re-entrance of SIGINT handler
1132
+ let exiting = false;
1133
+
1134
+ process.on('SIGINT', () => {
1135
+ // During Claude run, ignore in launcher so child handles it
1136
+ // Check this BEFORE setting exiting flag to avoid breaking reentrancy protection
1137
+ if (stdinManager.isSuspended && stdinManager.isSuspended()) {
1138
+ return;
1139
+ }
1140
+
1141
+ // Prevent re-entrance - ensure cleanup runs only once
1142
+ if (exiting) {
1143
+ return;
1144
+ }
1145
+ exiting = true;
1146
+
1147
+ // Try to reset stdin state before handling
1148
+ try {
1149
+ if (process.stdin.isTTY) {
1150
+ process.stdin.setRawMode(false);
1151
+ process.stdin.pause();
1152
+ }
1153
+ } catch (_) {
1154
+ // Ignore errors during emergency cleanup
1155
+ }
1156
+
1157
+ // Use unified Ctrl+C handler from StdinManager (synchronous)
1158
+ try {
1159
+ stdinManager.handleCtrlC();
1160
+ } catch (_) {
1161
+ // Ignore errors during Ctrl+C handling
1162
+ }
1163
+
1164
+ // Exit with standard SIGINT exit code (128 + 2 = 130)
1165
+ // Note: If handleCtrlC() calls process.exit(0) for second Ctrl+C,
1166
+ // this line won't be reached, which is expected behavior
1167
+ process.exit(130);
1168
+ });
1169
+
1116
1170
  // Initialize global menus and start the application
1117
1171
  initializeGlobalMenus();
1118
1172
 
package/docs/README-zh.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Claude Launcher
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/@kikkimo/claude-launcher.svg?style=flat-square)](https://www.npmjs.com/package/@kikkimo/claude-launcher) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](https://opensource.org/licenses/MIT) [![Node.js Version](https://img.shields.io/badge/node-%3E%3D20.0.0-brightgreen.svg?style=flat-square)](https://nodejs.org/) [![npm downloads](https://img.shields.io/npm/dm/@kikkimo/claude-launcher.svg?style=flat-square)](https://www.npmjs.com/package/@kikkimo/claude-launcher) [![DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/kikkimo/claude-launcher)
4
+
3
5
  一个优雅的 Claude Code 交互式启动器,具有美观的 Claude 风格界面和全面的第三方 API 管理功能。通过直观的多语言命令行菜单使用各种配置启动 Claude Code。
4
6
 
5
7
  ## 📖 文档
@@ -13,7 +15,7 @@
13
15
  - Claude 风格界面,采用正宗的橙色/琥珀色配色方案
14
16
  - 方向键导航,流畅的菜单切换
15
17
  - API 选择和管理的交互式表格
16
- - 多语言支持(8种语言包括中文、英文、德文、法文、日文、韩文、俄文、西班牙文)
18
+ - 多语言支持(简体中文、繁体中文、英文、德文、法文、西班牙文、意大利文、葡萄牙文、日文、韩文、俄文)
17
19
 
18
20
  ### 🔐 **高级安全**
19
21
  - 所有敏感数据使用 AES-256-CBC 加密
@@ -23,7 +25,7 @@
23
25
  - 强密码要求和验证
24
26
 
25
27
  ### 🚀 **第三方 API 管理**
26
- - 全面支持多个第三方 API 提供商
28
+ - 全面支持多个第三方 API 提供商(OpenAI、Anthropic、DeepSeek、Kimi、GLM/智谱AI 和自定义 API)
27
29
  - 带验证的交互式 API 配置
28
30
  - API 使用统计和跟踪
29
31
  - 安全的配置备份和恢复
@@ -50,7 +52,7 @@
50
52
  ```
51
53
 
52
54
  3. **首次设置:** 启动器将引导您完成:
53
- - 语言选择(提供8种语言)
55
+ - 语言选择(提供11种语言)
54
56
  - 安全设置(配置导入/导出的密码)
55
57
  - 第三方 API 配置(如果需要)
56
58
 
@@ -84,7 +86,7 @@ node claude-launcher
84
86
  3. **使用第三方 API 启动 Claude Code** - 使用配置的第三方 API
85
87
  4. **使用第三方 API 启动 Claude Code(跳过权限)** - 结合第三方 API 和跳过权限
86
88
  5. **第三方 API 管理** - 配置、切换、删除 API,查看统计信息
87
- 6. **语言设置** - 在8种支持的语言之间切换
89
+ 6. **语言设置** - 在11种支持的语言之间切换
88
90
  7. **版本更新检查** - 检查启动器更新
89
91
  8. **退出** - 关闭启动器
90
92
 
@@ -146,7 +148,7 @@ Claude Launcher 2.0 使用先进的配置系统:
146
148
 
147
149
  ### 首次设置流程
148
150
 
149
- 1. **语言选择**:从8种支持的语言中选择
151
+ 1. **语言选择**:从11种支持的语言中选择
150
152
  2. **安全设置**:
151
153
  - 设置导入/导出的密码保护(推荐)
152
154
  - 或跳过基本使用(功能有限)
@@ -156,10 +158,11 @@ Claude Launcher 2.0 使用先进的配置系统:
156
158
 
157
159
  通过交互界面配置任何第三方 API 提供商:
158
160
 
159
- - **支持的提供商**:OpenAI、Anthropic、自定义 API
161
+ - **支持的提供商**:OpenAI、Anthropic、DeepSeek、Kimi、GLM/智谱AI 和自定义 API
160
162
  - **安全存储**:所有 API 令牌在存储前加密
161
163
  - **验证**:URL、令牌和模型的实时验证
162
164
  - **使用跟踪**:监控 API 使用统计
165
+ - **提供商特定功能**:为每个提供商优化配置,提供有用的注释和建议
163
166
 
164
167
  ### 配置导入/导出
165
168
 
@@ -4,6 +4,7 @@
4
4
  */
5
5
 
6
6
  const readline = require('readline');
7
+ const stdinManager = require('../utils/stdin-manager');
7
8
 
8
9
  /**
9
10
  * Get password input with proper masking (no plaintext display)
@@ -12,105 +13,118 @@ const readline = require('readline');
12
13
  */
13
14
  function getPasswordInput(prompt) {
14
15
  return new Promise((resolve, reject) => {
15
- // Save original stdin state
16
- const originalRawMode = process.stdin.isRaw;
17
- const originalPaused = process.stdin.isPaused();
18
-
19
16
  let password = '';
17
+ let scope = null;
18
+ let cleanedUp = false;
20
19
 
21
- try {
22
- // Display prompt - this is necessary for password input
23
- process.stdout.write(prompt);
24
-
25
- if (!process.stdin.isTTY) {
26
- // Non-TTY environment fallback
27
- const rl = readline.createInterface({
28
- input: process.stdin,
29
- output: process.stdout
30
- });
20
+ // Display prompt - this is necessary for password input
21
+ process.stdout.write(prompt);
31
22
 
32
- rl.question('', (answer) => {
33
- rl.close();
34
- resolve(answer.trim());
23
+ if (!process.stdin.isTTY) {
24
+ // Non-TTY environment fallback - use scope's createReadline
25
+ try {
26
+ scope = stdinManager.acquire('line', {
27
+ id: 'passwordInput_nonTTY',
28
+ allowNested: false
35
29
  });
30
+ } catch (error) {
31
+ reject(new Error(`Failed to acquire stdin for password input: ${error.message}`));
36
32
  return;
37
33
  }
38
34
 
39
- // Set up raw mode for character-by-character input
40
- process.stdin.setRawMode(true);
41
- process.stdin.resume();
42
- process.stdin.setEncoding('utf8');
43
-
44
- const cleanup = () => {
45
- try {
46
- process.stdin.removeListener('data', handleKeyPress);
47
- if (process.stdin.isTTY) {
48
- process.stdin.setRawMode(originalRawMode);
49
- if (originalPaused) {
50
- process.stdin.pause();
51
- }
52
- }
53
- } catch (error) {
54
- // Ignore cleanup errors
55
- }
56
- };
57
-
58
- const handleKeyPress = (data) => {
59
- const key = data.toString();
60
-
61
- // Handle different key combinations
62
- switch (key) {
63
- case '\u0003': // Ctrl+C
64
- cleanup();
65
- reject(new Error('Password input cancelled by user'));
66
- return;
67
-
68
- case '\r': // Enter (CR)
69
- case '\n': // Line Feed (LF)
70
- case '\r\n': // CRLF
71
- process.stdout.write('\n');
72
- cleanup();
73
- resolve(password);
74
- return;
75
-
76
- case '\u007f': // Backspace (DEL)
77
- case '\b': // Backspace (BS)
78
- if (password.length > 0) {
79
- password = password.slice(0, -1);
80
- // Clear the last asterisk
81
- process.stdout.write('\b \b');
82
- }
83
- return;
84
-
85
- case '\u001b': // Escape
86
- cleanup();
87
- reject(new Error('Password input cancelled'));
88
- return;
35
+ const rl = scope.createReadline();
36
+ rl.question('', (answer) => {
37
+ rl.close();
38
+ scope.release();
39
+ resolve(answer.trim());
40
+ });
41
+ return;
42
+ }
89
43
 
90
- default:
91
- // Filter out control characters (except printable ones)
92
- if (key.charCodeAt(0) >= 32 && key.charCodeAt(0) < 127) {
93
- password += key;
94
- process.stdout.write('*');
95
- }
96
- return;
97
- }
98
- };
44
+ // Use StdinManager to acquire raw mode scope
45
+ try {
46
+ scope = stdinManager.acquire('raw', {
47
+ id: 'passwordInput',
48
+ allowNested: false
49
+ });
50
+ } catch (error) {
51
+ reject(new Error(`Failed to acquire stdin for password input: ${error.message}`));
52
+ return;
53
+ }
99
54
 
100
- process.stdin.on('data', handleKeyPress);
55
+ const cleanup = () => {
56
+ if (cleanedUp) return;
57
+ cleanedUp = true;
101
58
 
102
- } catch (error) {
103
- // Restore stdin state on error
104
59
  try {
105
- if (process.stdin.isTTY) {
106
- process.stdin.setRawMode(originalRawMode);
107
- if (originalPaused) {
108
- process.stdin.pause();
109
- }
110
- }
111
- } catch (cleanupError) {
60
+ scope.removeAllListeners('data');
61
+ scope.release();
62
+ } catch (error) {
112
63
  // Ignore cleanup errors
113
64
  }
65
+ };
66
+
67
+ const handleKeyPress = (data) => {
68
+ const key = data.toString();
69
+
70
+ // Handle Ctrl+C - cancel password input immediately
71
+ if (key === '\u0003') {
72
+ cleanup();
73
+ reject(new Error('Password input cancelled by Ctrl+C'));
74
+ return;
75
+ }
76
+
77
+ // If waiting for second Ctrl+C, any other key cancels it
78
+ if (stdinManager.isCtrlCPending()) {
79
+ stdinManager.cancelCtrlC();
80
+ // Continue to process this key normally
81
+ }
82
+
83
+ // Handle different key combinations
84
+ switch (key) {
85
+ case '\r': // Enter (CR)
86
+ case '\n': // Line Feed (LF)
87
+ case '\r\n': // CRLF
88
+ process.stdout.write('\n');
89
+ cleanup();
90
+ resolve(password);
91
+ return;
92
+
93
+ case '\u007f': // Backspace (DEL)
94
+ case '\b': // Backspace (BS)
95
+ if (password.length > 0) {
96
+ password = password.slice(0, -1);
97
+ // Clear the last asterisk
98
+ process.stdout.write('\b \b');
99
+ }
100
+ return;
101
+
102
+ case '\u001b': // Escape
103
+ cleanup();
104
+ reject(new Error('Password input cancelled'));
105
+ return;
106
+
107
+ default:
108
+ // Process each character individually to handle IME batch input
109
+ // When using Chinese IME, multiple chars may come in one event (e.g., "vis")
110
+ for (let i = 0; i < key.length; i++) {
111
+ const char = key[i];
112
+ const charCode = char.charCodeAt(0);
113
+
114
+ // Filter out control characters (only accept ASCII printable)
115
+ if (charCode >= 32 && charCode < 127) {
116
+ password += char;
117
+ process.stdout.write('*');
118
+ }
119
+ }
120
+ return;
121
+ }
122
+ };
123
+
124
+ try {
125
+ scope.on('data', handleKeyPress);
126
+ } catch (error) {
127
+ cleanup();
114
128
  reject(error);
115
129
  }
116
130
  });
@@ -141,4 +155,4 @@ async function getPasswordWithConfirmation(prompt, confirmPrompt = 'Confirm Pass
141
155
  module.exports = {
142
156
  getPasswordInput,
143
157
  getPasswordWithConfirmation
144
- };
158
+ };
@@ -335,10 +335,25 @@ module.exports = {
335
335
  press_key_return: "Drücken Sie eine beliebige Taste, um zum Hauptmenü zurückzukehren...",
336
336
  environment_variables: "Umgebungsvariablen:",
337
337
  using_third_party_api: "Verwende Drittanbieter-API-Konfiguration",
338
+ provider_optimizations_applied: "Anbieter-Optimierungen angewendet",
339
+ extended_timeout_format: "Erweitertes Timeout: {0}s ({1} Minuten)",
340
+ extended_timeout_format_singular: "Erweitertes Timeout: {0}s ({1} Minute)",
341
+ non_essential_traffic_disabled: "Nicht-essentieller Traffic deaktiviert",
342
+ custom_env_var: "{0}={1}",
343
+ // Deprecated - kept for backward compatibility
338
344
  deepseek_optimizations: "DeepSeek-Optimierungen aktiviert:",
339
345
  extended_timeout: "Erweitertes Timeout (600s)",
340
- non_essential_disabled: "Nicht-essentieller Traffic deaktiviert",
341
- press_key_return: "Drücken Sie eine beliebige Taste, um zum Hauptmenü zurückzukehren..."
346
+ non_essential_disabled: "Nicht-essentieller Traffic deaktiviert"
347
+ },
348
+
349
+ // Anbieter-Hinweise
350
+ provider: {
351
+ note_prefix: "Hinweis",
352
+ notes: {
353
+ deepseek: "Erfordert erweitertes Timeout für komplexe Denkaufgaben",
354
+ zhipu: "Erfordert erweitertes Timeout für große Antworten",
355
+ zai: "Erfordert erweitertes Timeout für große Antworten"
356
+ }
342
357
  },
343
358
 
344
359
  // Zusätzliche UI-Nachrichten
@@ -335,10 +335,25 @@ module.exports = {
335
335
  press_key_return: "Press any key to return to main menu...",
336
336
  environment_variables: "Environment variables:",
337
337
  using_third_party_api: "Using Third-party API Configuration",
338
+ provider_optimizations_applied: "Provider Optimizations Applied",
339
+ extended_timeout_format: "Extended timeout: {0}s ({1} minutes)",
340
+ extended_timeout_format_singular: "Extended timeout: {0}s ({1} minute)",
341
+ non_essential_traffic_disabled: "Non-essential traffic disabled",
342
+ custom_env_var: "{0}={1}",
343
+ // Deprecated - kept for backward compatibility
338
344
  deepseek_optimizations: "DeepSeek optimizations enabled:",
339
345
  extended_timeout: "Extended timeout (600s)",
340
- non_essential_disabled: "Non-essential traffic disabled",
341
- press_key_return: "Press any key to return to main menu..."
346
+ non_essential_disabled: "Non-essential traffic disabled"
347
+ },
348
+
349
+ // Provider notes
350
+ provider: {
351
+ note_prefix: "Note",
352
+ notes: {
353
+ deepseek: "Requires extended timeout for complex reasoning tasks",
354
+ zhipu: "Requires extended timeout for large responses",
355
+ zai: "Requires extended timeout for large responses"
356
+ }
342
357
  },
343
358
 
344
359
  // Additional UI messages
@@ -335,10 +335,25 @@ module.exports = {
335
335
  press_key_return: "Presione cualquier tecla para volver al menú principal...",
336
336
  environment_variables: "Variables de entorno:",
337
337
  using_third_party_api: "Usando configuración de API de terceros",
338
+ provider_optimizations_applied: "Optimizaciones del proveedor aplicadas",
339
+ extended_timeout_format: "Tiempo de espera extendido: {0}s ({1} minutos)",
340
+ extended_timeout_format_singular: "Tiempo de espera extendido: {0}s ({1} minuto)",
341
+ non_essential_traffic_disabled: "Tráfico no esencial deshabilitado",
342
+ custom_env_var: "{0}={1}",
343
+ // Deprecated - kept for backward compatibility
338
344
  deepseek_optimizations: "Optimizaciones DeepSeek habilitadas:",
339
345
  extended_timeout: "Tiempo de espera extendido (600s)",
340
- non_essential_disabled: "Tráfico no esencial deshabilitado",
341
- press_key_return: "Presione cualquier tecla para volver al menú principal..."
346
+ non_essential_disabled: "Tráfico no esencial deshabilitado"
347
+ },
348
+
349
+ // Notas del proveedor
350
+ provider: {
351
+ note_prefix: "Nota",
352
+ notes: {
353
+ deepseek: "Requiere tiempo de espera extendido para tareas de razonamiento complejas",
354
+ zhipu: "Requiere tiempo de espera extendido para respuestas grandes",
355
+ zai: "Requiere tiempo de espera extendido para respuestas grandes"
356
+ }
342
357
  },
343
358
 
344
359
  // Mensajes adicionales de interfaz de usuario
@@ -335,10 +335,25 @@ module.exports = {
335
335
  press_key_return: "Appuyez sur n'importe quelle touche pour retourner au menu principal...",
336
336
  environment_variables: "Variables d'environnement :",
337
337
  using_third_party_api: "Utilisation de la configuration d'API tierce",
338
+ provider_optimizations_applied: "Optimisations du fournisseur appliquées",
339
+ extended_timeout_format: "Délai d'expiration étendu : {0}\u00A0s ({1}\u00A0minutes)",
340
+ extended_timeout_format_singular: "Délai d'expiration étendu : {0}\u00A0s ({1}\u00A0minute)",
341
+ non_essential_traffic_disabled: "Trafic non essentiel désactivé",
342
+ custom_env_var: "{0}={1}",
343
+ // Deprecated - kept for backward compatibility
338
344
  deepseek_optimizations: "Optimisations DeepSeek activées :",
339
- extended_timeout: "Délai d'expiration étendu (600s)",
340
- non_essential_disabled: "Trafic non essentiel désactivé",
341
- press_key_return: "Appuyez sur n'importe quelle touche pour retourner au menu principal..."
345
+ extended_timeout: "Délai d'expiration étendu (600\u00A0s)",
346
+ non_essential_disabled: "Trafic non essentiel désactivé"
347
+ },
348
+
349
+ // Notes du fournisseur
350
+ provider: {
351
+ note_prefix: "Note",
352
+ notes: {
353
+ deepseek: "Nécessite un délai d'expiration étendu pour les tâches de raisonnement complexes",
354
+ zhipu: "Nécessite un délai d'expiration étendu pour les grandes réponses",
355
+ zai: "Nécessite un délai d'expiration étendu pour les grandes réponses"
356
+ }
342
357
  },
343
358
 
344
359
  // Messages d'interface utilisateur supplémentaires