qwen-api-proxy 1.0.12 → 1.0.13

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
@@ -311,7 +311,7 @@ docker run -d \
311
311
  -v $(pwd)/logs:/app/logs \
312
312
  -v $(pwd)/uploads:/app/uploads \
313
313
  -v $(pwd)/temp:/app/temp \
314
- endykaufman/qwen-api-proxy:1.0.12
314
+ endykaufman/qwen-api-proxy:1.0.13
315
315
 
316
316
  # 3. Смотрим логи
317
317
  docker logs -f qwen-proxy
@@ -320,7 +320,7 @@ docker logs -f qwen-proxy
320
320
  ### Доступные теги
321
321
 
322
322
  - `latest` - последняя стабильная версия
323
- - `1.0.12` - текущая версия
323
+ - `1.0.13` - текущая версия
324
324
  - `1.0.x` - предыдущие версии
325
325
 
326
326
  > **💡 Важно:** Перед первым запуском добавьте аккаунт через `npm run auth` или загрузите сессию через Telegram бота.
@@ -341,7 +341,7 @@ docker logs -f qwen-proxy
341
341
  ```yaml
342
342
  services:
343
343
  qwen-proxy:
344
- image: endykaufman/qwen-api-proxy:1.0.12
344
+ image: endykaufman/qwen-api-proxy:1.0.13
345
345
  container_name: qwen-proxy
346
346
  env_file:
347
347
  - .env
@@ -396,7 +396,7 @@ docker run -d \
396
396
  -v $(pwd)/logs:/app/logs \
397
397
  -v $(pwd)/uploads:/app/uploads \
398
398
  -v $(pwd)/temp:/app/temp \
399
- endykaufman/qwen-api-proxy:1.0.12
399
+ endykaufman/qwen-api-proxy:1.0.13
400
400
  ```
401
401
 
402
402
  Файл `docker-compose.yml`:
@@ -405,7 +405,7 @@ docker run -d \
405
405
  services:
406
406
  qwen-proxy:
407
407
  build: .
408
- image: endykaufman/qwen-api-proxy:1.0.12
408
+ image: endykaufman/qwen-api-proxy:1.0.13
409
409
  container_name: qwen-proxy
410
410
  env_file:
411
411
  - .env # Автоматическая загрузка переменных
@@ -2,7 +2,7 @@
2
2
 
3
3
  /**
4
4
  * qwen-api-proxy - CLI entry point for global installation
5
- *
5
+ *
6
6
  * This script:
7
7
  * 1. Sets up the working directory structure in the current location
8
8
  * 2. Creates necessary directories (session, logs, uploads, temp)
@@ -21,7 +21,7 @@ const WORKING_DIR = process.cwd();
21
21
 
22
22
  // Parse command-line arguments early to get custom directory
23
23
  const args = process.argv.slice(2);
24
- const dirFlag = args.find(arg => arg.startsWith('--dir='));
24
+ const dirFlag = args.find((arg) => arg.startsWith('--dir='));
25
25
  const customDir = dirFlag ? dirFlag.split('=')[1] : null;
26
26
 
27
27
  // Use custom directory if specified
@@ -47,8 +47,8 @@ function setupWorkingDirectory(targetDir = EFFECTIVE_DIR) {
47
47
  ];
48
48
 
49
49
  console.log('📁 Setting up working directory...');
50
-
51
- dirs.forEach(dir => {
50
+
51
+ dirs.forEach((dir) => {
52
52
  const dirPath = path.join(targetDir, dir);
53
53
  if (!fs.existsSync(dirPath)) {
54
54
  fs.mkdirSync(dirPath, { recursive: true });
@@ -71,16 +71,16 @@ function setupWorkingDirectory(targetDir = EFFECTIVE_DIR) {
71
71
  function setupEnvFile(targetDir = EFFECTIVE_DIR) {
72
72
  const envPath = path.join(targetDir, '.env');
73
73
  const envExamplePath = path.join(targetDir, '.env.example');
74
-
74
+
75
75
  if (!fs.existsSync(envPath)) {
76
76
  // Copy .env.example from package if it exists in working dir, otherwise create basic
77
77
  const packageEnvExample = path.join(PACKAGE_ROOT, '.env.example');
78
-
78
+
79
79
  if (fs.existsSync(packageEnvExample)) {
80
80
  fs.copyFileSync(packageEnvExample, envExamplePath);
81
81
  console.log(' ✓ Created .env.example');
82
82
  }
83
-
83
+
84
84
  // Create empty .env if not exists
85
85
  if (!fs.existsSync(envPath)) {
86
86
  fs.writeFileSync(envPath, '# Qwen API Proxy Configuration\n# See .env.example for available options\n\n');
@@ -105,12 +105,12 @@ function setupGitignore(targetDir = EFFECTIVE_DIR) {
105
105
  'session_backup_*'
106
106
  ];
107
107
  const missingEntries = [];
108
-
108
+
109
109
  // Check which entries are missing from .gitignore
110
110
  if (fs.existsSync(gitignorePath)) {
111
111
  const content = fs.readFileSync(gitignorePath, 'utf8');
112
- const lines = content.split('\n').map(line => line.trim());
113
- requiredEntries.forEach(entry => {
112
+ const lines = content.split('\n').map((line) => line.trim());
113
+ requiredEntries.forEach((entry) => {
114
114
  if (!lines.includes(entry)) {
115
115
  missingEntries.push(entry);
116
116
  }
@@ -146,7 +146,7 @@ npm-debug.log*
146
146
  fs.writeFileSync(gitignorePath, gitignoreContent);
147
147
  console.log(' ✓ Created .gitignore');
148
148
  }
149
-
149
+
150
150
  return missingEntries;
151
151
  }
152
152
 
@@ -155,7 +155,7 @@ npm-debug.log*
155
155
  */
156
156
  function checkDependencies() {
157
157
  const isWindows = process.platform === 'win32';
158
-
158
+
159
159
  try {
160
160
  // On Windows, check for zip.exe or 7z.exe
161
161
  if (isWindows) {
@@ -195,19 +195,19 @@ function setup() {
195
195
  console.log('\n╔══════════════════════════════════════════════════════════╗');
196
196
  console.log('║ Qwen API Proxy - Working Directory Setup ║');
197
197
  console.log('╚══════════════════════════════════════════════════════════╝\n');
198
-
198
+
199
199
  console.log(`📍 Working directory: ${EFFECTIVE_DIR}\n`);
200
-
200
+
201
201
  setupWorkingDirectory();
202
202
  console.log();
203
203
  setupEnvFile();
204
204
  console.log();
205
-
205
+
206
206
  const missingGitignoreDirs = setupGitignore();
207
207
  console.log();
208
-
208
+
209
209
  checkDependencies();
210
-
210
+
211
211
  console.log('\n✅ Working directory setup complete!\n');
212
212
  console.log('📝 Next steps for first-time users:');
213
213
  console.log(' 1. Add an account: qwen-api-proxy (or npx qwen-api-proxy)');
@@ -220,11 +220,11 @@ function setup() {
220
220
  console.log(' - Configure TELEGRAM_BOT_TOKEN in .env file');
221
221
  console.log(' - Send session archive to the bot');
222
222
  console.log('\n');
223
-
223
+
224
224
  // Show warnings for missing .gitignore entries
225
225
  if (missingGitignoreDirs.length > 0) {
226
226
  console.warn('⚠️ WARNING: The following entries are not in .gitignore:');
227
- missingGitignoreDirs.forEach(entry => {
227
+ missingGitignoreDirs.forEach((entry) => {
228
228
  console.warn(` - ${entry}`);
229
229
  });
230
230
  console.warn('\n Add them to .gitignore to prevent committing sensitive data!\n');
@@ -235,41 +235,41 @@ function setup() {
235
235
  const needsSetup = args.includes('--setup') || !fs.existsSync(path.join(EFFECTIVE_DIR, 'session'));
236
236
 
237
237
  // Parse command from arguments (already defined args above)
238
- const command = args.find(arg => !arg.startsWith('-'));
238
+ const command = args.find((arg) => !arg.startsWith('-'));
239
239
 
240
240
  // Handle 'init' command - manual setup only
241
241
  if (command === 'init') {
242
242
  console.log('\n╔══════════════════════════════════════════════════════════╗');
243
243
  console.log('║ Qwen API Proxy - Initialize Working Directory ║');
244
244
  console.log('╚══════════════════════════════════════════════════════════╝\n');
245
-
245
+
246
246
  console.log(`📍 Working directory: ${EFFECTIVE_DIR}\n`);
247
-
247
+
248
248
  setupWorkingDirectory(EFFECTIVE_DIR);
249
249
  console.log();
250
250
  setupEnvFile(EFFECTIVE_DIR);
251
251
  console.log();
252
-
252
+
253
253
  const missingGitignoreDirs = setupGitignore(EFFECTIVE_DIR);
254
254
  console.log();
255
-
255
+
256
256
  checkDependencies();
257
-
257
+
258
258
  console.log('\n✅ Working directory initialized successfully!\n');
259
259
  console.log('📝 Next steps:');
260
260
  console.log(' 1. Edit .env file with your configuration');
261
261
  console.log(' 2. Run: qwen-api-proxy');
262
262
  console.log('\n');
263
-
263
+
264
264
  // Show warnings for missing .gitignore entries
265
265
  if (missingGitignoreDirs.length > 0) {
266
266
  console.warn('⚠️ WARNING: The following entries are not in .gitignore:');
267
- missingGitignoreDirs.forEach(entry => {
267
+ missingGitignoreDirs.forEach((entry) => {
268
268
  console.warn(` - ${entry}`);
269
269
  });
270
270
  console.warn('\n Add them to .gitignore to prevent committing sensitive data!\n');
271
271
  }
272
-
272
+
273
273
  process.exit(0);
274
274
  }
275
275
 
@@ -278,11 +278,11 @@ if (command === 'doctor') {
278
278
  console.log('\n╔══════════════════════════════════════════════════════════╗');
279
279
  console.log('║ Qwen API Proxy - System Health Check ║');
280
280
  console.log('╚══════════════════════════════════════════════════════════╝\n');
281
-
281
+
282
282
  const issues = [];
283
283
  const warnings = [];
284
284
  const ok = [];
285
-
285
+
286
286
  // Check Node.js version
287
287
  const nodeVersion = process.version;
288
288
  const majorVersion = parseInt(nodeVersion.slice(1).split('.')[0]);
@@ -291,7 +291,7 @@ if (command === 'doctor') {
291
291
  } else {
292
292
  issues.push(`Node.js ${nodeVersion} (✗ requires >= 18)`);
293
293
  }
294
-
294
+
295
295
  // Check zip command (cross-platform)
296
296
  const isWindows = process.platform === 'win32';
297
297
  let zipAvailable = false;
@@ -315,16 +315,16 @@ if (command === 'doctor') {
315
315
  } catch (error) {
316
316
  // zip not available
317
317
  }
318
-
318
+
319
319
  if (zipAvailable) {
320
320
  ok.push('zip/7z command available');
321
321
  } else {
322
322
  warnings.push('zip/7z command not found (required for archive command)');
323
323
  }
324
-
324
+
325
325
  // Check working directory structure
326
326
  const requiredDirs = ['session', 'session/accounts', 'session/history', 'logs', 'uploads', 'temp'];
327
- requiredDirs.forEach(dir => {
327
+ requiredDirs.forEach((dir) => {
328
328
  const dirPath = path.join(EFFECTIVE_DIR, dir);
329
329
  if (fs.existsSync(dirPath)) {
330
330
  ok.push(`${dir}/ directory exists`);
@@ -332,12 +332,12 @@ if (command === 'doctor') {
332
332
  warnings.push(`${dir}/ directory missing`);
333
333
  }
334
334
  });
335
-
335
+
336
336
  // Check .env file
337
337
  const envPath = path.join(EFFECTIVE_DIR, '.env');
338
338
  if (fs.existsSync(envPath)) {
339
339
  ok.push('.env file exists');
340
-
340
+
341
341
  // Check for common configurations
342
342
  const envContent = fs.readFileSync(envPath, 'utf8');
343
343
  if (envContent.includes('TELEGRAM_BOT_TOKEN=') && !envContent.includes('TELEGRAM_BOT_TOKEN=your_bot_token_here')) {
@@ -348,7 +348,7 @@ if (command === 'doctor') {
348
348
  } else {
349
349
  warnings.push('.env file not found (run "qwen-api-proxy init" to create)');
350
350
  }
351
-
351
+
352
352
  // Check .gitignore file
353
353
  const gitignorePath = path.join(EFFECTIVE_DIR, '.gitignore');
354
354
  const requiredGitignoreEntries = [
@@ -360,16 +360,16 @@ if (command === 'doctor') {
360
360
  'session_backup_*'
361
361
  ];
362
362
  const missingGitignoreEntries = [];
363
-
363
+
364
364
  if (fs.existsSync(gitignorePath)) {
365
365
  const content = fs.readFileSync(gitignorePath, 'utf8');
366
- const lines = content.split('\n').map(line => line.trim());
367
- requiredGitignoreEntries.forEach(entry => {
366
+ const lines = content.split('\n').map((line) => line.trim());
367
+ requiredGitignoreEntries.forEach((entry) => {
368
368
  if (!lines.includes(entry)) {
369
369
  missingGitignoreEntries.push(entry);
370
370
  }
371
371
  });
372
-
372
+
373
373
  if (missingGitignoreEntries.length === 0) {
374
374
  ok.push('.gitignore properly configured');
375
375
  } else {
@@ -378,11 +378,11 @@ if (command === 'doctor') {
378
378
  } else {
379
379
  warnings.push('.gitignore not found (run "qwen-api-proxy init" to create)');
380
380
  }
381
-
381
+
382
382
  // Check permissions
383
383
  const testDirs = ['session', 'logs', 'uploads'];
384
384
  let permissionsOk = true;
385
- testDirs.forEach(dir => {
385
+ testDirs.forEach((dir) => {
386
386
  const dirPath = path.join(EFFECTIVE_DIR, dir);
387
387
  if (fs.existsSync(dirPath)) {
388
388
  try {
@@ -398,7 +398,7 @@ if (command === 'doctor') {
398
398
  if (permissionsOk) {
399
399
  ok.push('Directory permissions OK');
400
400
  }
401
-
401
+
402
402
  // Check session data
403
403
  const tokensPath = path.join(EFFECTIVE_DIR, 'session', 'tokens.json');
404
404
  if (fs.existsSync(tokensPath)) {
@@ -415,7 +415,7 @@ if (command === 'doctor') {
415
415
  } else {
416
416
  warnings.push('No accounts configured yet');
417
417
  }
418
-
418
+
419
419
  // Check disk space (cross-platform)
420
420
  try {
421
421
  if (isWindows) {
@@ -467,21 +467,21 @@ if (command === 'doctor') {
467
467
  } catch (error) {
468
468
  // df/wmic not available, skip
469
469
  }
470
-
470
+
471
471
  // Print results
472
472
  console.log('✅ OK:');
473
- ok.forEach(msg => console.log(` ✓ ${msg}`));
474
-
473
+ ok.forEach((msg) => console.log(` ✓ ${msg}`));
474
+
475
475
  if (warnings.length > 0) {
476
476
  console.log('\n⚠️ Warnings:');
477
- warnings.forEach(msg => console.log(` ⚠ ${msg}`));
477
+ warnings.forEach((msg) => console.log(` ⚠ ${msg}`));
478
478
  }
479
-
479
+
480
480
  if (issues.length > 0) {
481
481
  console.log('\n❌ Issues:');
482
- issues.forEach(msg => console.log(` ✗ ${msg}`));
482
+ issues.forEach((msg) => console.log(` ✗ ${msg}`));
483
483
  }
484
-
484
+
485
485
  console.log('\n' + '='.repeat(60));
486
486
  if (issues.length === 0 && warnings.length === 0) {
487
487
  console.log('🎉 All checks passed! System is healthy.');
@@ -491,7 +491,7 @@ if (command === 'doctor') {
491
491
  console.log(`✗ ${issues.length} issue(s) found - please fix before running`);
492
492
  }
493
493
  console.log('='.repeat(60) + '\n');
494
-
494
+
495
495
  process.exit(issues.length > 0 ? 1 : 0);
496
496
  }
497
497
 
package/index.js CHANGED
@@ -15,7 +15,7 @@ import { checkPermissions } from './src/utils/permissionChecker.js';
15
15
  import fs from 'fs';
16
16
  import path from 'path';
17
17
  import { execSync } from 'child_process';
18
- import { SESSION_DIR } from './src/config.js';
18
+ import { SESSION_DIR, ACCOUNTS_DIR } from './src/config.js';
19
19
 
20
20
  const app = express();
21
21
 
@@ -27,7 +27,7 @@ if (Number.isNaN(port) || port <= 0 || port > 65535) {
27
27
  }
28
28
 
29
29
  function toBoolean(value) {
30
- if (typeof value !== 'string') return false;
30
+ if (typeof value !== 'string') {return false;}
31
31
  return ['1', 'true', 'yes', 'on'].includes(value.trim().toLowerCase());
32
32
  }
33
33
 
@@ -42,7 +42,7 @@ function ensureNonInteractiveTokens() {
42
42
  return false;
43
43
  }
44
44
  const now = Date.now();
45
- const validTokens = tokens.filter(t => (!t.resetAt || new Date(t.resetAt).getTime() <= now) && !t.invalid);
45
+ const validTokens = tokens.filter((t) => (!t.resetAt || new Date(t.resetAt).getTime() <= now) && !t.invalid);
46
46
  if (!validTokens.length) {
47
47
  logWarn('⚠️ Все аккаунты недоступны. Сервер работает в режиме Telegram бота.');
48
48
  logWarn('📦 Отправьте архив с сессиями через Telegram бот для обновления аккаунтов.');
@@ -75,7 +75,7 @@ app.use((req, res, next) => {
75
75
  res.header('Access-Control-Allow-Origin', '*');
76
76
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
77
77
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
78
- if (req.method === 'OPTIONS') return res.sendStatus(200);
78
+ if (req.method === 'OPTIONS') {return res.sendStatus(200);}
79
79
  next();
80
80
  });
81
81
 
@@ -134,10 +134,10 @@ function createSessionArchive() {
134
134
  }
135
135
 
136
136
  // Проверяем, есть ли реальные данные (accounts, tokens.json, и т.д.)
137
- const hasAccounts = fs.existsSync(path.join(sessionPath, 'accounts')) &&
137
+ const hasAccounts = fs.existsSync(path.join(sessionPath, 'accounts')) &&
138
138
  fs.readdirSync(path.join(sessionPath, 'accounts')).length > 0;
139
139
  const hasTokens = fs.existsSync(path.join(sessionPath, 'tokens.json'));
140
-
140
+
141
141
  if (!hasAccounts && !hasTokens) {
142
142
  throw new Error('Папка сессии не содержит данных аккаунтов.');
143
143
  }
@@ -212,29 +212,29 @@ function validateGitignore() {
212
212
  'session_backup',
213
213
  'session_backup_*'
214
214
  ];
215
-
215
+
216
216
  if (!fs.existsSync(gitignorePath)) {
217
217
  logWarn('⚠️ Файл .gitignore не найден в корневой директории');
218
218
  logWarn(' Рекомендуется создать .gitignore для защиты чувствительных данных');
219
219
  return false;
220
220
  }
221
-
221
+
222
222
  const content = fs.readFileSync(gitignorePath, 'utf8');
223
- const lines = content.split('\n').map(line => line.trim());
223
+ const lines = content.split('\n').map((line) => line.trim());
224
224
  const missingEntries = [];
225
-
226
- requiredEntries.forEach(entry => {
225
+
226
+ requiredEntries.forEach((entry) => {
227
227
  if (!lines.includes(entry)) {
228
228
  missingEntries.push(entry);
229
229
  }
230
230
  });
231
-
231
+
232
232
  if (missingEntries.length > 0) {
233
233
  logWarn(`⚠️ .gitignore отсутствует: ${missingEntries.join(', ')}`);
234
234
  logWarn(' Добавьте эти записи в .gitignore для защиты данных');
235
235
  return false;
236
236
  }
237
-
237
+
238
238
  logInfo('✅ .gitignore проверен - все записи на месте');
239
239
  return true;
240
240
  }
@@ -261,9 +261,9 @@ async function handleCLICommand() {
261
261
  // Проверяем, есть ли уже аккаунты
262
262
  const tokensPath = path.join(process.cwd(), SESSION_DIR, 'tokens.json');
263
263
  const accountsPath = path.join(process.cwd(), SESSION_DIR, ACCOUNTS_DIR);
264
-
264
+
265
265
  let hasAccounts = false;
266
-
266
+
267
267
  if (fs.existsSync(tokensPath)) {
268
268
  try {
269
269
  const tokens = JSON.parse(fs.readFileSync(tokensPath, 'utf8'));
@@ -274,24 +274,24 @@ async function handleCLICommand() {
274
274
  // tokens.json corrupted
275
275
  }
276
276
  }
277
-
277
+
278
278
  if (!hasAccounts && fs.existsSync(accountsPath)) {
279
279
  const accounts = fs.readdirSync(accountsPath);
280
280
  if (accounts.length > 0) {
281
281
  hasAccounts = true;
282
282
  }
283
283
  }
284
-
284
+
285
285
  // Если аккаунтов нет, предлагаем добавить
286
286
  if (!hasAccounts) {
287
287
  console.log('📝 Аккаунты не найдены. Необходимо добавить аккаунт перед созданием архива.\n');
288
288
  console.log('🔹 Вариант 1: Добавить аккаунт сейчас (откроется браузер)');
289
289
  console.log('🔹 Вариант 2: Отправить файл сессии через Telegram бота');
290
290
  console.log('🔹 Вариант 3: Выйти и запустить вручную: npx qwen-api-proxy\n');
291
-
291
+
292
292
  const { prompt } = await import('./src/utils/prompt.js');
293
293
  const choice = await prompt('Ваш выбор (1/2/3, Enter = 1): ');
294
-
294
+
295
295
  if (choice === '2') {
296
296
  console.log('\n💡 Для использования Telegram бота:');
297
297
  console.log(' 1. Добавьте TELEGRAM_BOT_TOKEN в .env файл');
@@ -302,23 +302,23 @@ async function handleCLICommand() {
302
302
  console.log('\n👋 Выход. Запустите "npx qwen-api-proxy" для добавления аккаунта.\n');
303
303
  process.exit(0);
304
304
  }
305
-
305
+
306
306
  // choice === '1' или Enter - добавляем аккаунт
307
307
  console.log('\n🔐 Запуск браузера для добавления аккаунта...\n');
308
-
308
+
309
309
  const { addAccountInteractive } = await import('./src/utils/accountSetup.js');
310
310
  const accountId = await addAccountInteractive();
311
-
311
+
312
312
  if (!accountId) {
313
313
  console.log('\n❌ Аккаунт не был добавлен. Архив не создан.\n');
314
314
  process.exit(1);
315
315
  }
316
-
316
+
317
317
  console.log(`\n✅ Аккаунт ${accountId} успешно добавлен!\n`);
318
318
  } else {
319
319
  console.log('✅ Найден существующий аккаунт\n');
320
320
  }
321
-
321
+
322
322
  // Теперь создаем архив
323
323
  const archivePath = createSessionArchive();
324
324
  console.log('\n🎉 ГОТОВО!');
@@ -406,7 +406,7 @@ async function startServer() {
406
406
  console.log('4 - Удалить аккаунт');
407
407
 
408
408
  let choice = await prompt('Ваш выбор (Enter = 3): ');
409
- if (!choice) choice = '3';
409
+ if (!choice) {choice = '3';}
410
410
 
411
411
  if (choice === '1') {
412
412
  await addAccountInteractive();
@@ -414,9 +414,9 @@ async function startServer() {
414
414
  const { reloginAccountInteractive } = await import('./src/utils/accountSetup.js');
415
415
  await reloginAccountInteractive();
416
416
  } else if (choice === '3') {
417
- const hasValidToken = tokens.some(t => {
418
- if (t.invalid) return false;
419
- if (!t.resetAt) return true;
417
+ const hasValidToken = tokens.some((t) => {
418
+ if (t.invalid) {return false;}
419
+ if (!t.resetAt) {return true;}
420
420
  return new Date(t.resetAt).getTime() <= Date.now();
421
421
  });
422
422
  if (!tokens.length || !hasValidToken) {
@@ -508,7 +508,7 @@ async function startServer() {
508
508
  logInfo('🔍 Начинаем загрузку списка моделей...');
509
509
  const apiModels = await fetchModelsFromAPI();
510
510
  logDebug(`fetchModelsFromAPI вернул: ${apiModels ? apiModels.length + ' моделей' : 'null'}`);
511
-
511
+
512
512
  if (apiModels && apiModels.length > 0) {
513
513
  logInfo(`✅ Загружено ${apiModels.length} моделей с Qwen API`);
514
514
  logDebug(`Первые 5 моделей: ${apiModels.slice(0, 5).join(', ')}`);
@@ -519,11 +519,11 @@ async function startServer() {
519
519
  const fileModels = getAvailableModelsFromFile();
520
520
  logDebug(`getAvailableModelsFromFile вернул: ${fileModels ? fileModels.length + ' моделей' : 'null'}`);
521
521
  }
522
-
522
+
523
523
  const defaultModel = getDefaultModel();
524
524
  logInfo(`🎯 Модель по умолчанию: ${defaultModel}`);
525
525
  logDebug(`getDefaultModel() вернул: ${defaultModel}`);
526
-
526
+
527
527
  getApiKeys();
528
528
  });
529
529
  } catch (err) {
@@ -537,10 +537,10 @@ async function startServer() {
537
537
  }
538
538
 
539
539
  // Проверяем CLI команды перед запуском сервера
540
- handleCLICommand().then(hasCommand => {
540
+ handleCLICommand().then((hasCommand) => {
541
541
  if (!hasCommand) {
542
542
  // Нет команды CLI, запускаем сервер как обычно
543
- startServer().catch(async error => {
543
+ startServer().catch(async (error) => {
544
544
  logError('Ошибка при запуске сервера', error);
545
545
  await shutdownBrowser();
546
546
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qwen-api-proxy",
3
- "version": "1.0.12",
3
+ "version": "1.0.13",
4
4
  "description": "Proxy server for accessing Qwen API through browser emulation with OpenAI-compatible API and Telegram bot",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -44,6 +44,8 @@
44
44
  "scripts": {
45
45
  "start": "node index.js",
46
46
  "archive": "node index.js archive",
47
+ "lint": "eslint .",
48
+ "lint:fix": "eslint . --fix",
47
49
  "test": "echo \"Error: no test specified\" && exit 1",
48
50
  "test:cross-platform": "node test-cross-platform.js",
49
51
  "check-permissions": "node scripts/checkPermissions.js",
@@ -82,5 +84,9 @@
82
84
  "puppeteer-extra-plugin-stealth": "^2.11.2",
83
85
  "undici": "^6.21.1",
84
86
  "winston": "^3.17.0"
87
+ },
88
+ "devDependencies": {
89
+ "eslint": "^9.39.4",
90
+ "eslint-plugin-import": "^2.32.0"
85
91
  }
86
- }
92
+ }