fnva 0.0.8 → 0.0.10

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/bin/fnva.js CHANGED
@@ -74,6 +74,99 @@ function buildBinaryPath() {
74
74
  return null;
75
75
  }
76
76
 
77
+ function isEnvironmentSwitchCommand(args) {
78
+ return args.length >= 3 &&
79
+ (args[0] === 'java' || args[0] === 'llm' || args[0] === 'cc') &&
80
+ args[1] === 'use';
81
+ }
82
+
83
+ function hasDirectExecuteFlag(args) {
84
+ return args.includes('--exec') || args.includes('-e');
85
+ }
86
+
87
+ function getShellArg(args) {
88
+ const idx = args.indexOf('--shell');
89
+ if (idx !== -1 && idx + 1 < args.length) {
90
+ return args[idx + 1];
91
+ }
92
+ return null;
93
+ }
94
+
95
+ function detectShell() {
96
+ if (process.platform === 'win32') {
97
+ return 'powershell';
98
+ }
99
+ return 'bash';
100
+ }
101
+
102
+ function hasSessionFlag(args) {
103
+ return args.includes('--session');
104
+ }
105
+
106
+ function parseEnvironmentScript(scriptContent) {
107
+ if (!scriptContent || scriptContent.trim() === '') {
108
+ return {};
109
+ }
110
+
111
+ // 将数组输出转换为字符串
112
+ if (Array.isArray(scriptContent)) {
113
+ scriptContent = scriptContent.join('\n');
114
+ }
115
+
116
+ const envVars = {};
117
+ const lines = scriptContent.split('\n');
118
+
119
+ for (const line of lines) {
120
+ const trimmedLine = line.trim();
121
+
122
+ // 解析 PowerShell 环境变量设置
123
+ if (trimmedLine.startsWith('$env:')) {
124
+ const match = trimmedLine.match(/\$env:(\w+)\s*=\s*"([^"]*)"/);
125
+ if (match) {
126
+ envVars[match[1]] = match[2];
127
+ }
128
+ }
129
+
130
+ // 解析 bash/zsh 环境变量设置
131
+ if (trimmedLine.startsWith('export ')) {
132
+ const match = trimmedLine.match(/export\s+(\w+)\s*=\s*"([^"]*)"/);
133
+ if (match) {
134
+ envVars[match[1]] = match[2];
135
+ }
136
+ }
137
+
138
+ // 解析不带引号的环境变量设置
139
+ const unquotedMatch = trimmedLine.match(/\$env:(\w+)\s*=\s*([^;]+)/);
140
+ if (unquotedMatch) {
141
+ envVars[unquotedMatch[1]] = unquotedMatch[2].trim();
142
+ }
143
+ }
144
+
145
+ return envVars;
146
+ }
147
+
148
+ function applyEnvironmentVariables(envVars) {
149
+ for (const [key, value] of Object.entries(envVars)) {
150
+ process.env[key] = value;
151
+ }
152
+ }
153
+
154
+ function displaySuccessMessage(envType, envName, envVars) {
155
+ console.log(`✅ Switched to ${envType} environment: ${envName}`);
156
+
157
+ if (envVars.JAVA_HOME) {
158
+ console.log(`📁 JAVA_HOME: ${envVars.JAVA_HOME}`);
159
+ }
160
+
161
+ if (envVars.ANTHROPIC_AUTH_TOKEN) {
162
+ console.log(`🔑 ANTHROPIC_AUTH_TOKEN: [已设置]`);
163
+ }
164
+
165
+ if (envVars.OPENAI_API_KEY) {
166
+ console.log(`🔑 OPENAI_API_KEY: [已设置]`);
167
+ }
168
+ }
169
+
77
170
  function run() {
78
171
  const binaryPath = buildBinaryPath();
79
172
 
@@ -87,16 +180,114 @@ function run() {
87
180
  process.exit(1);
88
181
  }
89
182
 
90
- const result = spawnSync(binaryPath, process.argv.slice(2), {
91
- stdio: 'inherit',
92
- });
183
+ const args = process.argv.slice(2);
184
+ const isSwitchCommand = isEnvironmentSwitchCommand(args);
93
185
 
94
- if (result.error) {
95
- console.error(`Failed to execute fnva: ${result.error.message}`);
96
- process.exit(result.status ?? 1);
97
- }
186
+ if (isSwitchCommand) {
187
+ const shellArg = getShellArg(args);
188
+ if (!shellArg || shellArg === 'auto') {
189
+ const detected = detectShell();
190
+ if (shellArg === 'auto') {
191
+ const idx = args.indexOf('--shell');
192
+ if (idx !== -1 && idx + 1 < args.length) {
193
+ args[idx + 1] = detected;
194
+ }
195
+ } else {
196
+ args.push('--shell', detected);
197
+ }
198
+ }
199
+
200
+ const { spawnSync } = require('child_process');
201
+ const result = spawnSync(binaryPath, args, {
202
+ encoding: 'utf8',
203
+ shell: false
204
+ });
205
+
206
+ if (result.error) {
207
+ console.error(`Failed to execute fnva: ${result.error.message}`);
208
+ process.exit(result.status ?? 1);
209
+ }
210
+
211
+ if (result.status !== 0) {
212
+ process.exit(result.status);
213
+ }
214
+
215
+ // 获取环境切换脚本
216
+ const stdout = result.stdout || '';
217
+ if (stdout.includes('JAVA_HOME') || stdout.includes('ANTHROPIC_') || stdout.includes('OPENAI_')) {
218
+ // 将数组输出转换为字符串
219
+ const script = Array.isArray(stdout) ? stdout.join('\n') : stdout;
220
+ const envType = args[0];
221
+ const envName = args[2];
222
+
223
+ // Windows:默认不启动新的会话;可通过 --session 开启旧行为
224
+ if (process.platform === 'win32') {
225
+ if (hasSessionFlag(args)) {
226
+ console.log(`✅ Switched to ${envType} environment: ${envName}`);
227
+ console.log(`🚀 Starting new PowerShell session with ${envName} environment...`);
228
+ console.log(`Type "exit" to return to previous session\n`);
229
+
230
+ try {
231
+ const os = require('os');
232
+ const fs = require('fs');
233
+ const tempScript = os.tmpdir() + '\\fnva_env_' + Date.now() + '.ps1';
234
+ const fullScript = script + '\n';
235
+ fs.writeFileSync(tempScript, fullScript, 'utf8');
236
+ const { spawn } = require('child_process');
237
+ const ps = spawn('powershell', ['-NoExit', '-ExecutionPolicy', 'Bypass', '-File', tempScript], {
238
+ stdio: 'inherit',
239
+ shell: false
240
+ });
241
+ ps.on('exit', () => {
242
+ try { fs.unlinkSync(tempScript); } catch (_) {}
243
+ console.log('👋 Returned to original session');
244
+ });
245
+ return;
246
+ } catch (error) {
247
+ console.error(`Failed to start PowerShell session: ${error.message}`);
248
+ console.log(`📝 Script was: ${script}`);
249
+ }
250
+ } else {
251
+ console.log(`✅ Switched to ${envType} environment: ${envName}`);
252
+ if (process.stdout.isTTY) {
253
+ console.log('');
254
+ console.log('💡 在当前会话应用环境:');
255
+ console.log(` fnva ${envType} use ${envName} --shell powershell | Invoke-Expression`);
256
+ } else {
257
+ process.stdout.write(script);
258
+ }
259
+ }
260
+ } else {
261
+ // Unix-like systems: 显示使用说明
262
+ console.log(`✅ Switched to ${envType} environment: ${envName}`);
263
+ console.log('');
264
+ console.log('💡 To apply this environment, run:');
265
+ console.log(` node bin/fnva.js ${args.join(' ')} | bash`);
266
+ }
267
+ } else {
268
+ // 如果不是环境脚本,直接输出
269
+ console.log(stdout);
270
+ }
98
271
 
99
- process.exit(result.status ?? 0);
272
+ // 如果有 stderr 输出,也显示出来
273
+ if (result.stderr) {
274
+ console.error(result.stderr);
275
+ }
276
+
277
+ process.exit(0);
278
+ } else {
279
+ // 对于其他命令,使用原有的 stdio: 'inherit' 方式
280
+ const result = spawnSync(binaryPath, args, {
281
+ stdio: 'inherit',
282
+ });
283
+
284
+ if (result.error) {
285
+ console.error(`Failed to execute fnva: ${result.error.message}`);
286
+ process.exit(result.status ?? 1);
287
+ }
288
+
289
+ process.exit(result.status ?? 0);
290
+ }
100
291
  }
101
292
 
102
293
  run();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fnva",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
4
4
  "description": "跨平台环境切换工具,支持 Java 和 LLM 环境配置",
5
5
  "author": "protagonistss",
6
6
  "license": "MIT",
package/platforms/fnva CHANGED
Binary file
Binary file
Binary file