qwen-api-proxy 1.0.10 → 1.0.11

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
@@ -1,5 +1,10 @@
1
1
  # FreeQwenApi
2
2
 
3
+ [![npm version](https://badge.fury.io/js/qwen-api-proxy.svg)](https://badge.fury.io/js/qwen-api-proxy)
4
+ [![npm downloads](https://img.shields.io/npm/dm/qwen-api-proxy.svg)](https://www.npmjs.com/package/qwen-api-proxy)
5
+ [![Node.js Version](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg)](https://nodejs.org/)
6
+
7
+ > **📦 npm:** `npx qwen-api-proxy` или `npm install -g qwen-api-proxy`
3
8
  > **🐳 Docker Hub:** https://hub.docker.com/r/endykaufman/qwen-api-proxy
4
9
  > **🔧 Форк:** https://github.com/EndyKaufman/FreeQwenApi
5
10
  > **🌐 Оригинал:** https://github.com/y13sint/FreeQwenApi
@@ -109,11 +114,12 @@ curl http://localhost:3264/api/chat/completions \
109
114
  ## Содержание
110
115
 
111
116
  1. [Быстрый старт](#быстрый-старт)
112
- 2. [Docker Hub](#docker-hub) 🆕
113
- 3. [Docker](#docker)
114
- 4. [Управление аккаунтами](#управление-аккаунтами)
115
- 5. [Авторизация API-ключами](#авторизация-api-ключами)
116
- 6. [API Reference](#api-reference)
117
+ 2. [CLI команды](#-cli-команды) 🆕
118
+ 3. [Docker Hub](#docker-hub) 🆕
119
+ 4. [Docker](#docker)
120
+ 5. [Управление аккаунтами](#управление-аккаунтами)
121
+ 6. [Авторизация API-ключами](#авторизация-api-ключами)
122
+ 7. [API Reference](#api-reference)
117
123
  - [POST /api/chat](#post-apichat)
118
124
  - [POST /api/chat/completions](#post-apichatcompletions)
119
125
  - [GET /api/models](#get-apimodels)
@@ -122,19 +128,58 @@ curl http://localhost:3264/api/chat/completions \
122
128
  - [POST /api/files/upload](#post-apifilesupload)
123
129
  - [POST /api/files/getstsToken](#post-apifilesgetststoken)
124
130
  - [POST /api/images/generations](#post-apiimagesgenerations)
125
- 7. [Работа с контекстом (API v2)](#работа-с-контекстом-api-v2)
126
- 8. [Работа с изображениями](#работа-с-изображениями)
127
- 9. [Генерация изображений](#генерация-изображений) 🆕
128
- 10. [OpenAI SDK](#openai-sdk)
129
- 11. [Python](#python-альтернативная-реализация)
130
- 12. [Доступные модели](#доступные-модели)
131
- 13. [Переменные окружения](#переменные-окружения)
132
- 14. [Структура проекта](#структура-проекта)
131
+ 8. [Работа с контекстом (API v2)](#работа-с-контекстом-api-v2)
132
+ 9. [Работа с изображениями](#работа-с-изображениями)
133
+ 10. [Генерация изображений](#генерация-изображений) 🆕
134
+ 11. [OpenAI SDK](#openai-sdk)
135
+ 12. [Python](#python-альтернативная-реализация)
136
+ 13. [Доступные модели](#доступные-модели)
137
+ 14. [Переменные окружения](#переменные-окружения)
138
+ 15. [Структура проекта](#структура-проекта)
133
139
 
134
140
  ---
135
141
 
136
142
  ## Быстрый старт
137
143
 
144
+ ### 🌍 Кросс-платформенная поддержка
145
+
146
+ Этот проект полностью поддерживает работу на:
147
+ - ✅ **Windows** (10/11, Server 2019+)
148
+ - ✅ **Linux** (Ubuntu 18.04+, Debian 10+, CentOS 8+)
149
+ - ✅ **macOS** (10.15+, включая Apple Silicon)
150
+
151
+ **Требования:**
152
+ - Node.js >= 18.0.0 (рекомендуется 20.x или 22.x LTS)
153
+ - Для команды `archive`: `zip` (Linux/macOS) или `zip`/`7-Zip`/PowerShell (Windows)
154
+
155
+ > 📖 **Полное руководство:** [CROSS_PLATFORM.md](CROSS_PLATFORM.md)
156
+
157
+ ### 📦 Через npm (Рекомендуется)
158
+
159
+ **Без установки (npx):**
160
+ ```bash
161
+ # Инициализация директории
162
+ npx qwen-api-proxy init
163
+
164
+ # Запуск сервера
165
+ npx qwen-api-proxy
166
+ ```
167
+
168
+ **Глобальная установка:**
169
+ ```bash
170
+ npm install -g qwen-api-proxy
171
+
172
+ # Инициализация
173
+ qwen-api-proxy init
174
+
175
+ # Запуск сервера
176
+ qwen-api-proxy
177
+ ```
178
+
179
+ > 💡 **Подробнее:** [README_NPM.md](README_NPM.md) - полное руководство по npm пакету
180
+
181
+ ### 💻 Ручная установка
182
+
138
183
  ```bash
139
184
  # Node.js (Основной)
140
185
  git clone https://github.com/y13sint/FreeQwenApi
@@ -186,6 +231,62 @@ python main.py
186
231
 
187
232
  ---
188
233
 
234
+ ## 🛠️ CLI команды
235
+
236
+ Все команды можно запускать через `npx` (без установки) или после глобальной установки:
237
+
238
+ ```bash
239
+ # Без установки (рекомендуется для редкого использования)
240
+ npx qwen-api-proxy <command>
241
+
242
+ # После глобальной установки (для частого использования)
243
+ qwen-api-proxy <command>
244
+ ```
245
+
246
+ ### Основные команды
247
+
248
+ | Команда | Описание |
249
+ |---------|----------|
250
+ | `npx qwen-api-proxy` | Запуск сервера |
251
+ | `npx qwen-api-proxy init` | Инициализация директории (без запуска) |
252
+ | `npx qwen-api-proxy archive` | Создание архива сессии |
253
+ | `npx qwen-api-proxy extend` | Продление сессий |
254
+ | `npx qwen-api-proxy doctor` | Проверка здоровья системы |
255
+
256
+ ### Примеры использования
257
+
258
+ ```bash
259
+ # Инициализация проекта
260
+ npx qwen-api-proxy init
261
+
262
+ # Создание архива сессии для backup
263
+ npx qwen-api-proxy archive
264
+
265
+ # Продление всех сессий
266
+ npx qwen-api-proxy extend
267
+
268
+ # Продление конкретного аккаунта
269
+ npx qwen-api-proxy extend --account-id acc_1234567890
270
+
271
+ # Проверка здоровья системы
272
+ npx qwen-api-proxy doctor
273
+
274
+ # С пользовательской директорией
275
+ npx qwen-api-proxy archive --dir=/path/to/project
276
+ ```
277
+
278
+ ### 🔧 NPM Scripts (для разработчиков)
279
+
280
+ ```bash
281
+ npm start # Запуск сервера
282
+ npm run archive # Создание архива
283
+ npm run auth # Добавить аккаунт
284
+ npm run rebuild-tokens # Перестроить tokens.json
285
+ npm run check-sessions # Проверить сессии
286
+ ```
287
+
288
+ ---
289
+
189
290
  ## Docker Hub
190
291
 
191
292
  Готовый Docker образ доступен на Docker Hub:
@@ -208,7 +309,7 @@ docker run -d \
208
309
  -v $(pwd)/logs:/app/logs \
209
310
  -v $(pwd)/uploads:/app/uploads \
210
311
  -v $(pwd)/temp:/app/temp \
211
- endykaufman/qwen-api-proxy:1.0.10
312
+ endykaufman/qwen-api-proxy:1.0.11
212
313
 
213
314
  # 3. Смотрим логи
214
315
  docker logs -f qwen-proxy
@@ -217,7 +318,7 @@ docker logs -f qwen-proxy
217
318
  ### Доступные теги
218
319
 
219
320
  - `latest` - последняя стабильная версия
220
- - `1.0.10` - текущая версия
321
+ - `1.0.11` - текущая версия
221
322
  - `1.0.x` - предыдущие версии
222
323
 
223
324
  > **💡 Важно:** Перед первым запуском добавьте аккаунт через `npm run auth` или загрузите сессию через Telegram бота.
@@ -238,7 +339,7 @@ docker logs -f qwen-proxy
238
339
  ```yaml
239
340
  services:
240
341
  qwen-proxy:
241
- image: endykaufman/qwen-api-proxy:1.0.10
342
+ image: endykaufman/qwen-api-proxy:1.0.11
242
343
  container_name: qwen-proxy
243
344
  env_file:
244
345
  - .env
@@ -293,7 +394,7 @@ docker run -d \
293
394
  -v $(pwd)/logs:/app/logs \
294
395
  -v $(pwd)/uploads:/app/uploads \
295
396
  -v $(pwd)/temp:/app/temp \
296
- endykaufman/qwen-api-proxy:1.0.10
397
+ endykaufman/qwen-api-proxy:1.0.11
297
398
  ```
298
399
 
299
400
  Файл `docker-compose.yml`:
@@ -302,7 +403,7 @@ docker run -d \
302
403
  services:
303
404
  qwen-proxy:
304
405
  build: .
305
- image: endykaufman/qwen-api-proxy:1.0.10
406
+ image: endykaufman/qwen-api-proxy:1.0.11
306
407
  container_name: qwen-proxy
307
408
  env_file:
308
409
  - .env # Автоматическая загрузка переменных
@@ -10,7 +10,7 @@
10
10
  * 4. Passes control to the main index.js
11
11
  */
12
12
 
13
- import { fileURLToPath } from 'url';
13
+ import { fileURLToPath, pathToFileURL } from 'url';
14
14
  import path from 'path';
15
15
  import fs from 'fs';
16
16
  import { execSync } from 'child_process';
@@ -151,15 +151,40 @@ npm-debug.log*
151
151
  }
152
152
 
153
153
  /**
154
- * Check if zip is available
154
+ * Check if zip is available (cross-platform)
155
155
  */
156
156
  function checkDependencies() {
157
+ const isWindows = process.platform === 'win32';
158
+
157
159
  try {
158
- execSync('zip --version', { stdio: 'ignore' });
159
- console.log(' ✓ zip command available');
160
+ // On Windows, check for zip.exe or 7z.exe
161
+ if (isWindows) {
162
+ try {
163
+ execSync('zip --version', { stdio: 'ignore' });
164
+ console.log(' ✓ zip command available');
165
+ return;
166
+ } catch (e) {
167
+ // Try 7z as alternative
168
+ try {
169
+ execSync('7z --help', { stdio: 'ignore' });
170
+ console.log(' ✓ 7z command available (alternative to zip)');
171
+ return;
172
+ } catch (e2) {
173
+ // Neither available
174
+ }
175
+ }
176
+ console.warn(' ⚠️ zip/7z command not found (required for archive command)');
177
+ console.warn(' Install with: choco install zip or download 7-Zip from 7-zip.org');
178
+ } else {
179
+ // Unix-like systems (Linux, macOS)
180
+ execSync('zip --version', { stdio: 'ignore' });
181
+ console.log(' ✓ zip command available');
182
+ }
160
183
  } catch (error) {
161
- console.warn(' ⚠️ zip command not found (required for archive command)');
162
- console.warn(' Install with: sudo apt install zip (Ubuntu) or brew install zip (macOS)');
184
+ if (!isWindows) {
185
+ console.warn(' ⚠️ zip command not found (required for archive command)');
186
+ console.warn(' Install with: sudo apt install zip (Ubuntu) or brew install zip (macOS)');
187
+ }
163
188
  }
164
189
  }
165
190
 
@@ -256,12 +281,34 @@ if (command === 'doctor') {
256
281
  issues.push(`Node.js ${nodeVersion} (✗ requires >= 18)`);
257
282
  }
258
283
 
259
- // Check zip command
284
+ // Check zip command (cross-platform)
285
+ const isWindows = process.platform === 'win32';
286
+ let zipAvailable = false;
260
287
  try {
261
- execSync('zip --version', { stdio: 'ignore' });
262
- ok.push('zip command available');
288
+ if (isWindows) {
289
+ try {
290
+ execSync('zip --version', { stdio: 'ignore' });
291
+ zipAvailable = true;
292
+ } catch (e) {
293
+ try {
294
+ execSync('7z --help', { stdio: 'ignore' });
295
+ zipAvailable = true; // 7z can work as alternative
296
+ } catch (e2) {
297
+ // Neither available
298
+ }
299
+ }
300
+ } else {
301
+ execSync('zip --version', { stdio: 'ignore' });
302
+ zipAvailable = true;
303
+ }
263
304
  } catch (error) {
264
- warnings.push('zip command not found (required for archive command)');
305
+ // zip not available
306
+ }
307
+
308
+ if (zipAvailable) {
309
+ ok.push('zip/7z command available');
310
+ } else {
311
+ warnings.push('zip/7z command not found (required for archive command)');
265
312
  }
266
313
 
267
314
  // Check working directory structure
@@ -358,22 +405,56 @@ if (command === 'doctor') {
358
405
  warnings.push('No accounts configured yet');
359
406
  }
360
407
 
361
- // Check disk space
408
+ // Check disk space (cross-platform)
362
409
  try {
363
- const dfOutput = execSync('df -k .', { encoding: 'utf8' });
364
- const lines = dfOutput.split('\n');
365
- if (lines.length >= 2) {
366
- const parts = lines[1].split(/\s+/);
367
- const availableKB = parseInt(parts[3]);
368
- const availableGB = (availableKB / 1024 / 1024).toFixed(2);
369
- if (availableGB > 1) {
370
- ok.push(`Disk space: ${availableGB} GB available`);
371
- } else {
372
- warnings.push(`Low disk space: ${availableGB} GB available`);
410
+ if (isWindows) {
411
+ // Use PowerShell or wmic on Windows
412
+ try {
413
+ const wmicOutput = execSync('wmic logicaldisk where "DeviceID=\'C:\'" get FreeSpace /value', { encoding: 'utf8' });
414
+ const match = wmicOutput.match(/FreeSpace=(\d+)/);
415
+ if (match) {
416
+ const availableBytes = parseInt(match[1]);
417
+ const availableGB = (availableBytes / 1024 / 1024 / 1024).toFixed(2);
418
+ if (availableGB > 1) {
419
+ ok.push(`Disk space: ${availableGB} GB available`);
420
+ } else {
421
+ warnings.push(`Low disk space: ${availableGB} GB available`);
422
+ }
423
+ }
424
+ } catch (e) {
425
+ // wmic might not be available, try PowerShell
426
+ try {
427
+ const psOutput = execSync('powershell -Command "(Get-PSDrive C).Free"', { encoding: 'utf8' });
428
+ const freeBytes = parseInt(psOutput.trim());
429
+ if (!isNaN(freeBytes)) {
430
+ const availableGB = (freeBytes / 1024 / 1024 / 1024).toFixed(2);
431
+ if (availableGB > 1) {
432
+ ok.push(`Disk space: ${availableGB} GB available`);
433
+ } else {
434
+ warnings.push(`Low disk space: ${availableGB} GB available`);
435
+ }
436
+ }
437
+ } catch (e2) {
438
+ // Skip disk check on Windows if commands fail
439
+ }
440
+ }
441
+ } else {
442
+ // Unix-like systems
443
+ const dfOutput = execSync('df -k .', { encoding: 'utf8' });
444
+ const lines = dfOutput.split('\n');
445
+ if (lines.length >= 2) {
446
+ const parts = lines[1].split(/\s+/);
447
+ const availableKB = parseInt(parts[3]);
448
+ const availableGB = (availableKB / 1024 / 1024).toFixed(2);
449
+ if (availableGB > 1) {
450
+ ok.push(`Disk space: ${availableGB} GB available`);
451
+ } else {
452
+ warnings.push(`Low disk space: ${availableGB} GB available`);
453
+ }
373
454
  }
374
455
  }
375
456
  } catch (error) {
376
- // df not available, skip
457
+ // df/wmic not available, skip
377
458
  }
378
459
 
379
460
  // Print results
@@ -411,4 +492,7 @@ if (needsSetup) {
411
492
  process.env.QWEN_API_PROXY_GLOBAL = 'true';
412
493
 
413
494
  // Import and run the main application
414
- await import(path.join(PACKAGE_ROOT, 'index.js'));
495
+ // Convert path to file:// URL for cross-platform ESM compatibility
496
+ const indexPath = path.join(PACKAGE_ROOT, 'index.js');
497
+ const indexUrl = pathToFileURL(indexPath).href;
498
+ await import(indexUrl);
package/index.js CHANGED
@@ -108,13 +108,14 @@ async function handleShutdown() {
108
108
  }
109
109
 
110
110
  /**
111
- * Создает ZIP архив папки session/
111
+ * Создает ZIP архив папки session/ (cross-platform)
112
112
  */
113
113
  function createSessionArchive() {
114
114
  const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
115
115
  const archiveName = `session_backup_${timestamp}.zip`;
116
116
  const archivePath = path.resolve(process.cwd(), archiveName);
117
117
  const sessionPath = path.resolve(process.cwd(), SESSION_DIR);
118
+ const isWindows = process.platform === 'win32';
118
119
 
119
120
  console.log('\n📦 Создание архива сессии...');
120
121
  console.log(`📂 Путь к сессии: ${sessionPath}`);
@@ -132,10 +133,28 @@ function createSessionArchive() {
132
133
  throw new Error('Папка сессии пуста. Сначала выполните авторизацию.');
133
134
  }
134
135
 
135
- // Создаем ZIP архив
136
- const command = `cd "${process.cwd()}" && zip -r "${archiveName}" "${SESSION_DIR}/"`;
137
- logInfo(`Выполнение команды: ${command}`);
138
- execSync(command, { stdio: 'inherit' });
136
+ // Создаем ZIP архив (cross-platform)
137
+ let command;
138
+ if (isWindows) {
139
+ // Try zip first, fallback to PowerShell Compress-Archive
140
+ try {
141
+ command = `cd /d "${process.cwd()}" && zip -r "${archiveName}" "${SESSION_DIR}"`;
142
+ logInfo(`Выполнение команды: ${command}`);
143
+ execSync(command, { stdio: 'inherit' });
144
+ } catch (zipError) {
145
+ // Fallback to PowerShell Compress-Archive
146
+ logInfo('zip не найден, используем PowerShell Compress-Archive');
147
+ const psCommand = `Compress-Archive -Path "${sessionPath}" -DestinationPath "${archivePath}" -Force`;
148
+ command = `powershell -Command "${psCommand}"`;
149
+ logInfo(`Выполнение команды: ${command}`);
150
+ execSync(command, { stdio: 'inherit' });
151
+ }
152
+ } else {
153
+ // Unix-like systems (Linux, macOS)
154
+ command = `cd "${process.cwd()}" && zip -r "${archiveName}" "${SESSION_DIR}/"`;
155
+ logInfo(`Выполнение команды: ${command}`);
156
+ execSync(command, { stdio: 'inherit' });
157
+ }
139
158
 
140
159
  // Проверяем создание архива
141
160
  if (!fs.existsSync(archivePath)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qwen-api-proxy",
3
- "version": "1.0.10",
3
+ "version": "1.0.11",
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": {
@@ -45,6 +45,7 @@
45
45
  "start": "node index.js",
46
46
  "archive": "node index.js archive",
47
47
  "test": "echo \"Error: no test specified\" && exit 1",
48
+ "test:cross-platform": "node test-cross-platform.js",
48
49
  "check-permissions": "node scripts/checkPermissions.js",
49
50
  "fix-permissions": "bash fix-permissions.sh",
50
51
  "rebuild-tokens": "node scripts/rebuildTokens.js",