qwenproxy-cli 1.4.0 → 1.4.2
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.pt-BR.md +7 -5
- package/dist/clean-cache.js +167 -68
- package/dist/delete-chats.js +212 -88
- package/dist/index.js +392 -267
- package/dist/login.js +172 -73
- package/dist/reset-cooldowns.js +167 -68
- package/dist/sync-clients.js +136 -126
- package/package.json +8 -6
- package/src/core/config.ts +13 -0
- package/src/core/version.ts +1 -1
- package/src/routes/chat/index.ts +1 -0
- package/src/services/playwright.ts +137 -43
- package/src/services/qwen.ts +47 -19
package/dist/index.js
CHANGED
|
@@ -151,6 +151,8 @@ var init_paths = __esm({
|
|
|
151
151
|
});
|
|
152
152
|
|
|
153
153
|
// src/core/config.ts
|
|
154
|
+
import fs2 from "node:fs";
|
|
155
|
+
import dotenv from "dotenv";
|
|
154
156
|
import { z } from "zod";
|
|
155
157
|
function isStatelessChatMode(mode) {
|
|
156
158
|
if (!mode) return false;
|
|
@@ -200,6 +202,15 @@ var envSchema, env, config;
|
|
|
200
202
|
var init_config = __esm({
|
|
201
203
|
"src/core/config.ts"() {
|
|
202
204
|
"use strict";
|
|
205
|
+
init_paths();
|
|
206
|
+
if (!isRunningUnderNodeTest()) {
|
|
207
|
+
const envPath2 = getEnvFilePath();
|
|
208
|
+
if (fs2.existsSync(envPath2)) {
|
|
209
|
+
dotenv.config({ path: envPath2, quiet: true });
|
|
210
|
+
} else {
|
|
211
|
+
dotenv.config({ quiet: true });
|
|
212
|
+
}
|
|
213
|
+
}
|
|
203
214
|
envSchema = z.object({
|
|
204
215
|
PORT: z.string().regex(/^\d+$/, "PORT must be a number").refine((value) => {
|
|
205
216
|
const port = Number(value);
|
|
@@ -566,7 +577,7 @@ var init_config = __esm({
|
|
|
566
577
|
});
|
|
567
578
|
|
|
568
579
|
// src/tui/settings.ts
|
|
569
|
-
import
|
|
580
|
+
import fs3 from "node:fs";
|
|
570
581
|
import path2 from "node:path";
|
|
571
582
|
function loadTuiSettings() {
|
|
572
583
|
if (cachedSettings) {
|
|
@@ -578,8 +589,8 @@ function loadTuiSettings() {
|
|
|
578
589
|
}
|
|
579
590
|
const filePath = getTuiSettingsPath();
|
|
580
591
|
try {
|
|
581
|
-
if (
|
|
582
|
-
const raw =
|
|
592
|
+
if (fs3.existsSync(filePath)) {
|
|
593
|
+
const raw = fs3.readFileSync(filePath, "utf-8");
|
|
583
594
|
const parsed = JSON.parse(raw);
|
|
584
595
|
const loaded = {
|
|
585
596
|
...defaultSettings,
|
|
@@ -620,10 +631,10 @@ function saveTuiSettings(updates) {
|
|
|
620
631
|
cachedSettings = merged;
|
|
621
632
|
const filePath = getTuiSettingsPath();
|
|
622
633
|
const dir = path2.dirname(filePath);
|
|
623
|
-
if (!
|
|
624
|
-
|
|
634
|
+
if (!fs3.existsSync(dir)) {
|
|
635
|
+
fs3.mkdirSync(dir, { recursive: true });
|
|
625
636
|
}
|
|
626
|
-
|
|
637
|
+
fs3.writeFileSync(filePath, JSON.stringify(merged, null, 2), "utf-8");
|
|
627
638
|
} catch {
|
|
628
639
|
}
|
|
629
640
|
}
|
|
@@ -1379,7 +1390,7 @@ var init_memory_cache = __esm({
|
|
|
1379
1390
|
|
|
1380
1391
|
// src/core/crypto-utils.ts
|
|
1381
1392
|
import crypto2 from "crypto";
|
|
1382
|
-
import
|
|
1393
|
+
import fs4 from "fs";
|
|
1383
1394
|
function getOrCreateKey() {
|
|
1384
1395
|
if (cachedKey) return cachedKey;
|
|
1385
1396
|
const envKey = process.env.ENCRYPTION_KEY;
|
|
@@ -1387,15 +1398,15 @@ function getOrCreateKey() {
|
|
|
1387
1398
|
cachedKey = crypto2.scryptSync(envKey, "qwenproxy-salt", KEY_LENGTH);
|
|
1388
1399
|
return cachedKey;
|
|
1389
1400
|
}
|
|
1390
|
-
if (
|
|
1391
|
-
cachedKey = Buffer.from(
|
|
1401
|
+
if (fs4.existsSync(KEY_PATH)) {
|
|
1402
|
+
cachedKey = Buffer.from(fs4.readFileSync(KEY_PATH, "utf-8"), "hex");
|
|
1392
1403
|
return cachedKey;
|
|
1393
1404
|
}
|
|
1394
|
-
if (!
|
|
1395
|
-
|
|
1405
|
+
if (!fs4.existsSync(DATA_DIR)) {
|
|
1406
|
+
fs4.mkdirSync(DATA_DIR, { recursive: true, mode: 493 });
|
|
1396
1407
|
}
|
|
1397
1408
|
const key = crypto2.randomBytes(KEY_LENGTH);
|
|
1398
|
-
|
|
1409
|
+
fs4.writeFileSync(KEY_PATH, key.toString("hex"), { mode: 384 });
|
|
1399
1410
|
cachedKey = key;
|
|
1400
1411
|
return cachedKey;
|
|
1401
1412
|
}
|
|
@@ -1459,21 +1470,21 @@ __export(database_exports, {
|
|
|
1459
1470
|
});
|
|
1460
1471
|
import Database from "better-sqlite3";
|
|
1461
1472
|
import path3 from "path";
|
|
1462
|
-
import
|
|
1473
|
+
import fs5 from "fs";
|
|
1463
1474
|
function getDatabase() {
|
|
1464
1475
|
if (db) return db;
|
|
1465
1476
|
try {
|
|
1466
|
-
if (!
|
|
1467
|
-
|
|
1477
|
+
if (!fs5.existsSync(DB_DIR)) {
|
|
1478
|
+
fs5.mkdirSync(DB_DIR, { recursive: true, mode: 493 });
|
|
1468
1479
|
}
|
|
1469
1480
|
const migrateLegacyDatabase = (legacyPath, legacyWalPath, legacyShmPath) => {
|
|
1470
|
-
if (
|
|
1471
|
-
|
|
1472
|
-
if (
|
|
1473
|
-
|
|
1481
|
+
if (fs5.existsSync(legacyPath) && !fs5.existsSync(DB_PATH)) {
|
|
1482
|
+
fs5.renameSync(legacyPath, DB_PATH);
|
|
1483
|
+
if (fs5.existsSync(legacyWalPath) && !fs5.existsSync(DB_WAL_PATH)) {
|
|
1484
|
+
fs5.renameSync(legacyWalPath, DB_WAL_PATH);
|
|
1474
1485
|
}
|
|
1475
|
-
if (
|
|
1476
|
-
|
|
1486
|
+
if (fs5.existsSync(legacyShmPath) && !fs5.existsSync(DB_SHM_PATH)) {
|
|
1487
|
+
fs5.renameSync(legacyShmPath, DB_SHM_PATH);
|
|
1477
1488
|
}
|
|
1478
1489
|
console.log(`\u{1F4E6} [Database] Migrated legacy database to ${DB_PATH}`);
|
|
1479
1490
|
}
|
|
@@ -1488,12 +1499,12 @@ function getDatabase() {
|
|
|
1488
1499
|
LEGACY_DB_IN_DIR_WAL_PATH,
|
|
1489
1500
|
LEGACY_DB_IN_DIR_SHM_PATH
|
|
1490
1501
|
);
|
|
1491
|
-
if (
|
|
1492
|
-
|
|
1502
|
+
if (fs5.existsSync(LEGACY_JSON_BAK_PATH) && !fs5.existsSync(DB_JSON_BAK_PATH)) {
|
|
1503
|
+
fs5.renameSync(LEGACY_JSON_BAK_PATH, DB_JSON_BAK_PATH);
|
|
1493
1504
|
}
|
|
1494
1505
|
const testFile = path3.join(DB_DIR, ".write-test");
|
|
1495
|
-
|
|
1496
|
-
|
|
1506
|
+
fs5.writeFileSync(testFile, "");
|
|
1507
|
+
fs5.unlinkSync(testFile);
|
|
1497
1508
|
} catch (err) {
|
|
1498
1509
|
console.error(
|
|
1499
1510
|
`\u274C [Database] Cannot access database directory '${DB_DIR}':`,
|
|
@@ -1633,12 +1644,12 @@ function encryptPlaintextPasswords(db2) {
|
|
|
1633
1644
|
}
|
|
1634
1645
|
function migrateFromJson(db2) {
|
|
1635
1646
|
const jsonPath = LEGACY_JSON_PATH;
|
|
1636
|
-
if (!
|
|
1647
|
+
if (!fs5.existsSync(jsonPath)) return;
|
|
1637
1648
|
try {
|
|
1638
|
-
const raw =
|
|
1649
|
+
const raw = fs5.readFileSync(jsonPath, "utf-8");
|
|
1639
1650
|
const accounts = JSON.parse(raw);
|
|
1640
1651
|
if (!Array.isArray(accounts) || accounts.length === 0) {
|
|
1641
|
-
|
|
1652
|
+
fs5.renameSync(jsonPath, DB_JSON_BAK_PATH);
|
|
1642
1653
|
return;
|
|
1643
1654
|
}
|
|
1644
1655
|
const insert = db2.prepare(`
|
|
@@ -1652,7 +1663,7 @@ function migrateFromJson(db2) {
|
|
|
1652
1663
|
}
|
|
1653
1664
|
});
|
|
1654
1665
|
migrate();
|
|
1655
|
-
|
|
1666
|
+
fs5.renameSync(jsonPath, DB_JSON_BAK_PATH);
|
|
1656
1667
|
console.log(
|
|
1657
1668
|
`[Database] Migrated ${accounts.length} account(s) from accounts.json to SQLite`
|
|
1658
1669
|
);
|
|
@@ -1766,7 +1777,7 @@ var init_database = __esm({
|
|
|
1766
1777
|
|
|
1767
1778
|
// src/core/local-auth.ts
|
|
1768
1779
|
import crypto3 from "node:crypto";
|
|
1769
|
-
import
|
|
1780
|
+
import fs6 from "node:fs";
|
|
1770
1781
|
function isPlaceholderApiKey(key) {
|
|
1771
1782
|
const value = (key || "").trim();
|
|
1772
1783
|
return value.length === 0 || value === PLACEHOLDER_API_KEY;
|
|
@@ -1793,7 +1804,7 @@ function assertBindAllowed(host, apiKey) {
|
|
|
1793
1804
|
}
|
|
1794
1805
|
function updateEnvVariable(key, value, envPath2 = getEnvFilePath()) {
|
|
1795
1806
|
try {
|
|
1796
|
-
const existing =
|
|
1807
|
+
const existing = fs6.existsSync(envPath2) ? fs6.readFileSync(envPath2, "utf-8") : "";
|
|
1797
1808
|
const regex = new RegExp(`^([ \\t]*)${key}[ \\t]*=.*$`, "m");
|
|
1798
1809
|
const assignment = regex.exec(existing);
|
|
1799
1810
|
let updated;
|
|
@@ -1806,7 +1817,7 @@ function updateEnvVariable(key, value, envPath2 = getEnvFilePath()) {
|
|
|
1806
1817
|
const prefix = existing.length === 0 || existing.endsWith("\n") ? "" : lineEnding;
|
|
1807
1818
|
updated = `${existing}${prefix}${key}=${value}${lineEnding}`;
|
|
1808
1819
|
}
|
|
1809
|
-
|
|
1820
|
+
fs6.writeFileSync(envPath2, updated, { encoding: "utf-8", mode: 384 });
|
|
1810
1821
|
} catch (err) {
|
|
1811
1822
|
console.warn(
|
|
1812
1823
|
`\u26A0\uFE0F [Config] Could not update ${key} in .env:`,
|
|
@@ -1824,7 +1835,7 @@ function persistCustomApiKey(apiKey, envPath2 = getEnvFilePath()) {
|
|
|
1824
1835
|
}
|
|
1825
1836
|
function persistApiKey(apiKey, envPath2 = getEnvFilePath()) {
|
|
1826
1837
|
try {
|
|
1827
|
-
const existing =
|
|
1838
|
+
const existing = fs6.existsSync(envPath2) ? fs6.readFileSync(envPath2, "utf-8") : "";
|
|
1828
1839
|
const assignment = /^([ \t]*)API_KEY[ \t]*=[ \t]*(.*)$/m.exec(existing);
|
|
1829
1840
|
if (assignment?.[2].trim()) return;
|
|
1830
1841
|
let updated;
|
|
@@ -1837,7 +1848,7 @@ function persistApiKey(apiKey, envPath2 = getEnvFilePath()) {
|
|
|
1837
1848
|
const prefix = existing.length === 0 || existing.endsWith("\n") ? "" : lineEnding;
|
|
1838
1849
|
updated = `${existing}${prefix}API_KEY=${apiKey}${lineEnding}`;
|
|
1839
1850
|
}
|
|
1840
|
-
|
|
1851
|
+
fs6.writeFileSync(
|
|
1841
1852
|
envPath2,
|
|
1842
1853
|
updated,
|
|
1843
1854
|
{ encoding: "utf-8", mode: 384 }
|
|
@@ -1889,7 +1900,7 @@ __export(accounts_exports, {
|
|
|
1889
1900
|
});
|
|
1890
1901
|
import "dotenv/config";
|
|
1891
1902
|
import crypto4 from "crypto";
|
|
1892
|
-
import
|
|
1903
|
+
import fs7 from "node:fs";
|
|
1893
1904
|
import path4 from "node:path";
|
|
1894
1905
|
function isPlaceholderAccountEmail(email, password) {
|
|
1895
1906
|
if (!email || typeof email !== "string") return false;
|
|
@@ -2136,20 +2147,20 @@ function addAccount(email, password, id) {
|
|
|
2136
2147
|
function wipeAccountSessionFiles(id) {
|
|
2137
2148
|
const profilePath = getAccountProfilePath(id);
|
|
2138
2149
|
try {
|
|
2139
|
-
|
|
2150
|
+
fs7.rmSync(profilePath, { recursive: true, force: true });
|
|
2140
2151
|
} catch (error) {
|
|
2141
2152
|
const message = error instanceof Error ? error.message : String(error ?? "");
|
|
2142
2153
|
if (message.includes("EPERM") || message.includes("EBUSY") || message.includes("Permission denied")) {
|
|
2143
2154
|
try {
|
|
2144
2155
|
const stalePath = `${profilePath}.stale-${Date.now()}`;
|
|
2145
|
-
|
|
2156
|
+
fs7.renameSync(profilePath, stalePath);
|
|
2146
2157
|
} catch {
|
|
2147
2158
|
}
|
|
2148
2159
|
}
|
|
2149
2160
|
}
|
|
2150
2161
|
const siblingState = path4.join(getProfilesDir(), `${id}_state.json`);
|
|
2151
2162
|
try {
|
|
2152
|
-
|
|
2163
|
+
fs7.rmSync(siblingState, { force: true });
|
|
2153
2164
|
} catch {
|
|
2154
2165
|
}
|
|
2155
2166
|
}
|
|
@@ -4050,7 +4061,7 @@ __export(clean_cache_exports, {
|
|
|
4050
4061
|
getDirStats: () => getDirStats
|
|
4051
4062
|
});
|
|
4052
4063
|
import "dotenv/config";
|
|
4053
|
-
import
|
|
4064
|
+
import fs8 from "node:fs";
|
|
4054
4065
|
import path5 from "node:path";
|
|
4055
4066
|
import os3 from "node:os";
|
|
4056
4067
|
import { chromium } from "patchright";
|
|
@@ -4065,14 +4076,14 @@ function getDirStats(dir) {
|
|
|
4065
4076
|
let files = 0;
|
|
4066
4077
|
function walk(d) {
|
|
4067
4078
|
try {
|
|
4068
|
-
const entries =
|
|
4079
|
+
const entries = fs8.readdirSync(d, { withFileTypes: true });
|
|
4069
4080
|
for (const e of entries) {
|
|
4070
4081
|
const full = path5.join(d, e.name);
|
|
4071
4082
|
if (e.isDirectory()) {
|
|
4072
4083
|
walk(full);
|
|
4073
4084
|
} else if (e.isFile()) {
|
|
4074
4085
|
try {
|
|
4075
|
-
bytes +=
|
|
4086
|
+
bytes += fs8.statSync(full).size;
|
|
4076
4087
|
files++;
|
|
4077
4088
|
} catch {
|
|
4078
4089
|
}
|
|
@@ -4101,17 +4112,17 @@ async function cleanPlaywrightBrowsers(cleanUnused) {
|
|
|
4101
4112
|
}
|
|
4102
4113
|
} catch {
|
|
4103
4114
|
}
|
|
4104
|
-
if (!msPlaywrightDir || !
|
|
4115
|
+
if (!msPlaywrightDir || !fs8.existsSync(msPlaywrightDir)) {
|
|
4105
4116
|
const defaultPlaywrightDir = process.env.PLAYWRIGHT_BROWSERS_PATH || (process.platform === "win32" ? path5.join(os3.homedir(), "AppData", "Local", "ms-playwright") : process.platform === "darwin" ? path5.join(os3.homedir(), "Library", "Caches", "ms-playwright") : path5.join(os3.homedir(), ".cache", "ms-playwright"));
|
|
4106
|
-
if (
|
|
4117
|
+
if (fs8.existsSync(defaultPlaywrightDir)) {
|
|
4107
4118
|
msPlaywrightDir = defaultPlaywrightDir;
|
|
4108
4119
|
}
|
|
4109
4120
|
}
|
|
4110
4121
|
const unusedDirs = [];
|
|
4111
4122
|
let freedBytes = 0;
|
|
4112
|
-
if (msPlaywrightDir &&
|
|
4123
|
+
if (msPlaywrightDir && fs8.existsSync(msPlaywrightDir)) {
|
|
4113
4124
|
try {
|
|
4114
|
-
const entries =
|
|
4125
|
+
const entries = fs8.readdirSync(msPlaywrightDir, { withFileTypes: true });
|
|
4115
4126
|
for (const entry of entries) {
|
|
4116
4127
|
if (!entry.isDirectory()) continue;
|
|
4117
4128
|
const folderName = entry.name;
|
|
@@ -4134,7 +4145,7 @@ async function cleanPlaywrightBrowsers(cleanUnused) {
|
|
|
4134
4145
|
if (cleanUnused && unusedDirs.length > 0) {
|
|
4135
4146
|
for (const item of unusedDirs) {
|
|
4136
4147
|
try {
|
|
4137
|
-
|
|
4148
|
+
fs8.rmSync(item.path, { recursive: true, force: true });
|
|
4138
4149
|
freedBytes += item.bytes;
|
|
4139
4150
|
} catch (err) {
|
|
4140
4151
|
console.warn(`[CleanCache] Warning: could not remove ${item.name}:`, err);
|
|
@@ -4270,7 +4281,7 @@ __export(playwright_exports, {
|
|
|
4270
4281
|
});
|
|
4271
4282
|
import { chromium as chromium2 } from "patchright";
|
|
4272
4283
|
import path6 from "path";
|
|
4273
|
-
import
|
|
4284
|
+
import fs9 from "fs";
|
|
4274
4285
|
import crypto5 from "crypto";
|
|
4275
4286
|
import { spawnSync } from "child_process";
|
|
4276
4287
|
import { createRequire } from "module";
|
|
@@ -4284,7 +4295,7 @@ function autoInstallPlaywrightChromium() {
|
|
|
4284
4295
|
try {
|
|
4285
4296
|
const patchrightEntry = requireLocal.resolve("patchright");
|
|
4286
4297
|
const cliPath = path6.join(path6.dirname(patchrightEntry), "cli.js");
|
|
4287
|
-
if (
|
|
4298
|
+
if (fs9.existsSync(cliPath)) {
|
|
4288
4299
|
console.log("\u23F3 [Playwright] Navegador Chromium n\xE3o encontrado. Instalando automaticamente...");
|
|
4289
4300
|
const res2 = spawnSync(process.execPath, [cliPath, "install", "chromium"], {
|
|
4290
4301
|
stdio: "inherit",
|
|
@@ -4420,10 +4431,10 @@ function getStorageStatePath(accountId) {
|
|
|
4420
4431
|
function loadStorageState(accountId) {
|
|
4421
4432
|
const p1 = getStorageStatePath(accountId);
|
|
4422
4433
|
const p2 = path6.join(path6.dirname(p1), `${accountId}_state.json`);
|
|
4423
|
-
const chosenPath =
|
|
4434
|
+
const chosenPath = fs9.existsSync(p1) ? p1 : fs9.existsSync(p2) ? p2 : void 0;
|
|
4424
4435
|
if (!chosenPath) return void 0;
|
|
4425
4436
|
try {
|
|
4426
|
-
const raw =
|
|
4437
|
+
const raw = fs9.readFileSync(chosenPath, "utf8");
|
|
4427
4438
|
const state = JSON.parse(raw);
|
|
4428
4439
|
if (!state || typeof state !== "object" || !Array.isArray(state.cookies)) {
|
|
4429
4440
|
return void 0;
|
|
@@ -4437,8 +4448,8 @@ async function saveStorageState(context, accountId, timeoutMs = 5e3) {
|
|
|
4437
4448
|
try {
|
|
4438
4449
|
const stateFile = getStorageStatePath(accountId);
|
|
4439
4450
|
const dir = path6.dirname(stateFile);
|
|
4440
|
-
if (!
|
|
4441
|
-
|
|
4451
|
+
if (!fs9.existsSync(dir)) {
|
|
4452
|
+
fs9.mkdirSync(dir, { recursive: true });
|
|
4442
4453
|
}
|
|
4443
4454
|
await withTimeout(
|
|
4444
4455
|
context.storageState({ path: stateFile }),
|
|
@@ -4547,7 +4558,7 @@ async function isPageLoggedIn(page, timeoutMs = SESSION_PROBE_NAVIGATION_TIMEOUT
|
|
|
4547
4558
|
return false;
|
|
4548
4559
|
}
|
|
4549
4560
|
}
|
|
4550
|
-
async function getOrLaunchSharedBrowser(browserType = "chromium", headless =
|
|
4561
|
+
async function getOrLaunchSharedBrowser(browserType = "chromium", headless = config.playwright.headless) {
|
|
4551
4562
|
if (sharedBrowser && sharedBrowser.isConnected()) {
|
|
4552
4563
|
return sharedBrowser;
|
|
4553
4564
|
}
|
|
@@ -4607,13 +4618,40 @@ async function getOrLaunchSharedBrowser(browserType = "chromium", headless = tru
|
|
|
4607
4618
|
}
|
|
4608
4619
|
}
|
|
4609
4620
|
async function clearVisibleChallenge(page) {
|
|
4610
|
-
if (
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4621
|
+
if (page.isClosed()) return;
|
|
4622
|
+
if (config.captcha.enabled) {
|
|
4623
|
+
await solveBaxiaCaptcha(page, {
|
|
4624
|
+
waitForMs: 0,
|
|
4625
|
+
maxAttempts: config.captcha.maxAttempts,
|
|
4626
|
+
retryDelayMs: config.captcha.retryDelayMs,
|
|
4627
|
+
settleMs: config.captcha.settleMs
|
|
4628
|
+
}).catch(() => false);
|
|
4629
|
+
}
|
|
4630
|
+
try {
|
|
4631
|
+
const modalCloseSelectors = [
|
|
4632
|
+
".ant-modal-close",
|
|
4633
|
+
".ant-modal-close-x",
|
|
4634
|
+
"button.ant-modal-close",
|
|
4635
|
+
"button[aria-label*='Close' i]",
|
|
4636
|
+
"button[aria-label*='Fechar' i]",
|
|
4637
|
+
".index-module__whats-new-modal-close",
|
|
4638
|
+
"button:has-text('Cancel')",
|
|
4639
|
+
"button:has-text('Cancelar')",
|
|
4640
|
+
"button:has-text('I understand')",
|
|
4641
|
+
"button:has-text('Entendi')",
|
|
4642
|
+
"button:has-text('OK')"
|
|
4643
|
+
];
|
|
4644
|
+
for (const sel of modalCloseSelectors) {
|
|
4645
|
+
if (page.isClosed()) return;
|
|
4646
|
+
const btn = page.locator(sel).first();
|
|
4647
|
+
if (await btn.isVisible({ timeout: 150 }).catch(() => false)) {
|
|
4648
|
+
await btn.click({ timeout: 500 }).catch(() => {
|
|
4649
|
+
});
|
|
4650
|
+
await sleep2(200);
|
|
4651
|
+
}
|
|
4652
|
+
}
|
|
4653
|
+
} catch {
|
|
4654
|
+
}
|
|
4617
4655
|
}
|
|
4618
4656
|
function getErrorMessage(error) {
|
|
4619
4657
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -5041,6 +5079,21 @@ function getStealthScript(profile) {
|
|
|
5041
5079
|
spoofedFunctions.add(window.performance.getEntriesByType);
|
|
5042
5080
|
}
|
|
5043
5081
|
} catch(e) {}
|
|
5082
|
+
|
|
5083
|
+
// --- Auto-resolve birthday compliance & eliminate false logout markers ---
|
|
5084
|
+
try {
|
|
5085
|
+
localStorage.removeItem("qwen_token_logged_out_marker");
|
|
5086
|
+
const b = localStorage.getItem("qwen_account_birthday");
|
|
5087
|
+
if (b) {
|
|
5088
|
+
try {
|
|
5089
|
+
const parsed = JSON.parse(b);
|
|
5090
|
+
if (!parsed.birthday) {
|
|
5091
|
+
parsed.birthday = "1995-06-15";
|
|
5092
|
+
localStorage.setItem("qwen_account_birthday", JSON.stringify(parsed));
|
|
5093
|
+
}
|
|
5094
|
+
} catch {}
|
|
5095
|
+
}
|
|
5096
|
+
} catch(e) {}
|
|
5044
5097
|
})();
|
|
5045
5098
|
`;
|
|
5046
5099
|
}
|
|
@@ -5339,7 +5392,7 @@ async function resolveAccountCredentials(account) {
|
|
|
5339
5392
|
}
|
|
5340
5393
|
return account;
|
|
5341
5394
|
}
|
|
5342
|
-
async function initPlaywrightForAccount(rawAccount, headless =
|
|
5395
|
+
async function initPlaywrightForAccount(rawAccount, headless = config.playwright.headless, browserType = "chromium", options = {}) {
|
|
5343
5396
|
const account = await resolveAccountCredentials(rawAccount);
|
|
5344
5397
|
if (accountPages.has(account.id)) {
|
|
5345
5398
|
console.log(
|
|
@@ -5465,7 +5518,7 @@ async function initPlaywrightForAccount(rawAccount, headless = true, browserType
|
|
|
5465
5518
|
const storageState = loadStorageState(account.id);
|
|
5466
5519
|
if (storageState) {
|
|
5467
5520
|
try {
|
|
5468
|
-
const raw =
|
|
5521
|
+
const raw = fs9.readFileSync(storageState, "utf8");
|
|
5469
5522
|
const parsed = JSON.parse(raw);
|
|
5470
5523
|
if (Array.isArray(parsed.cookies) && parsed.cookies.length > 0) {
|
|
5471
5524
|
const currentCookies = await acctContext.cookies();
|
|
@@ -5552,11 +5605,19 @@ async function initPlaywrightForAccount(rawAccount, headless = true, browserType
|
|
|
5552
5605
|
}
|
|
5553
5606
|
if (restoredFromDb) {
|
|
5554
5607
|
if (!acctPage.isClosed() && (acctPage.url() === "about:blank" || !acctPage.url().startsWith(qwenOrigin()))) {
|
|
5555
|
-
|
|
5556
|
-
|
|
5557
|
-
|
|
5558
|
-
|
|
5559
|
-
|
|
5608
|
+
try {
|
|
5609
|
+
await acctPage.goto(qwenUrl("/"), {
|
|
5610
|
+
waitUntil: "domcontentloaded",
|
|
5611
|
+
timeout: config.timeouts.navigation
|
|
5612
|
+
});
|
|
5613
|
+
await sleep2(300);
|
|
5614
|
+
} catch (err) {
|
|
5615
|
+
if (!err?.message?.includes("ERR_ABORTED")) {
|
|
5616
|
+
console.warn(
|
|
5617
|
+
`\u26A0\uFE0F [Playwright] Background navigation warning for ${maskEmail(account.email)}: ${err.message}`
|
|
5618
|
+
);
|
|
5619
|
+
}
|
|
5620
|
+
}
|
|
5560
5621
|
}
|
|
5561
5622
|
return;
|
|
5562
5623
|
}
|
|
@@ -5677,7 +5738,7 @@ async function validateAccountLogin(rawAccount, headless = true, browserType = "
|
|
|
5677
5738
|
const storageState = loadStorageState(account.id);
|
|
5678
5739
|
if (storageState) {
|
|
5679
5740
|
try {
|
|
5680
|
-
const raw =
|
|
5741
|
+
const raw = fs9.readFileSync(storageState, "utf8");
|
|
5681
5742
|
const parsed = JSON.parse(raw);
|
|
5682
5743
|
if (Array.isArray(parsed.cookies) && parsed.cookies.length > 0) {
|
|
5683
5744
|
const currentCookies = await acctContext.cookies();
|
|
@@ -5796,18 +5857,34 @@ async function loginToQwen(accountId, email, password) {
|
|
|
5796
5857
|
const apiResult = await loginViaApi(page, email, password);
|
|
5797
5858
|
if (apiResult.success) {
|
|
5798
5859
|
cookieCaches.delete(accountId);
|
|
5799
|
-
|
|
5800
|
-
if (cache3) {
|
|
5801
|
-
cache3.headers = {};
|
|
5802
|
-
cache3.lastRefresh = 0;
|
|
5803
|
-
}
|
|
5804
|
-
unmarkAccountHeadersReady(accountId);
|
|
5860
|
+
await saveStorageState(page.context(), accountId);
|
|
5805
5861
|
try {
|
|
5806
|
-
const
|
|
5807
|
-
|
|
5862
|
+
const liveCookies = await page.context().cookies();
|
|
5863
|
+
const tokenCookie = liveCookies.find((c) => c.name === "token");
|
|
5864
|
+
if (tokenCookie) {
|
|
5865
|
+
const cookieStr = liveCookies.map((c) => `${c.name}=${c.value}`).join("; ");
|
|
5866
|
+
const cache3 = getHeaderCache(accountId);
|
|
5867
|
+
cache3.headers.cookie = cookieStr;
|
|
5868
|
+
cache3.lastRefresh = Date.now();
|
|
5869
|
+
markAccountHeadersReady(accountId);
|
|
5870
|
+
const { saveAuthSession: saveAuthSession2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
5871
|
+
const exp = parseJwtExpiry(tokenCookie.value);
|
|
5872
|
+
saveAuthSession2(accountId, {
|
|
5873
|
+
cookie: cookieStr,
|
|
5874
|
+
userAgent: cache3.headers["user-agent"] || "",
|
|
5875
|
+
bxV: cache3.headers["bx-v"] || "2.5.37",
|
|
5876
|
+
bxUa: cache3.headers["bx-ua"] || "",
|
|
5877
|
+
bxUmidtoken: cache3.headers["bx-umidtoken"] || "",
|
|
5878
|
+
secChUa: cache3.headers["sec-ch-ua"] || void 0,
|
|
5879
|
+
secChUaMobile: cache3.headers["sec-ch-ua-mobile"] || void 0,
|
|
5880
|
+
secChUaPlatform: cache3.headers["sec-ch-ua-platform"] || void 0,
|
|
5881
|
+
version: cache3.headers["version"] || void 0,
|
|
5882
|
+
tokenExpiresAt: exp || void 0,
|
|
5883
|
+
capturedAt: Date.now()
|
|
5884
|
+
});
|
|
5885
|
+
}
|
|
5808
5886
|
} catch {
|
|
5809
5887
|
}
|
|
5810
|
-
await saveStorageState(page.context(), accountId);
|
|
5811
5888
|
return true;
|
|
5812
5889
|
}
|
|
5813
5890
|
if (apiResult.permanentFailure) {
|
|
@@ -5824,18 +5901,34 @@ async function loginToQwen(accountId, email, password) {
|
|
|
5824
5901
|
const uiResult = await loginViaUi(page, email, password);
|
|
5825
5902
|
if (uiResult.success) {
|
|
5826
5903
|
cookieCaches.delete(accountId);
|
|
5827
|
-
|
|
5828
|
-
if (cache3) {
|
|
5829
|
-
cache3.headers = {};
|
|
5830
|
-
cache3.lastRefresh = 0;
|
|
5831
|
-
}
|
|
5832
|
-
unmarkAccountHeadersReady(accountId);
|
|
5904
|
+
await saveStorageState(page.context(), accountId);
|
|
5833
5905
|
try {
|
|
5834
|
-
const
|
|
5835
|
-
|
|
5906
|
+
const liveCookies = await page.context().cookies();
|
|
5907
|
+
const tokenCookie = liveCookies.find((c) => c.name === "token");
|
|
5908
|
+
if (tokenCookie) {
|
|
5909
|
+
const cookieStr = liveCookies.map((c) => `${c.name}=${c.value}`).join("; ");
|
|
5910
|
+
const cache3 = getHeaderCache(accountId);
|
|
5911
|
+
cache3.headers.cookie = cookieStr;
|
|
5912
|
+
cache3.lastRefresh = Date.now();
|
|
5913
|
+
markAccountHeadersReady(accountId);
|
|
5914
|
+
const { saveAuthSession: saveAuthSession2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
5915
|
+
const exp = parseJwtExpiry(tokenCookie.value);
|
|
5916
|
+
saveAuthSession2(accountId, {
|
|
5917
|
+
cookie: cookieStr,
|
|
5918
|
+
userAgent: cache3.headers["user-agent"] || "",
|
|
5919
|
+
bxV: cache3.headers["bx-v"] || "2.5.37",
|
|
5920
|
+
bxUa: cache3.headers["bx-ua"] || "",
|
|
5921
|
+
bxUmidtoken: cache3.headers["bx-umidtoken"] || "",
|
|
5922
|
+
secChUa: cache3.headers["sec-ch-ua"] || void 0,
|
|
5923
|
+
secChUaMobile: cache3.headers["sec-ch-ua-mobile"] || void 0,
|
|
5924
|
+
secChUaPlatform: cache3.headers["sec-ch-ua-platform"] || void 0,
|
|
5925
|
+
version: cache3.headers["version"] || void 0,
|
|
5926
|
+
tokenExpiresAt: exp || void 0,
|
|
5927
|
+
capturedAt: Date.now()
|
|
5928
|
+
});
|
|
5929
|
+
}
|
|
5836
5930
|
} catch {
|
|
5837
5931
|
}
|
|
5838
|
-
await saveStorageState(page.context(), accountId);
|
|
5839
5932
|
return true;
|
|
5840
5933
|
}
|
|
5841
5934
|
if (uiResult.permanentFailure) {
|
|
@@ -6034,10 +6127,16 @@ async function loginViaUi(page, email, password) {
|
|
|
6034
6127
|
);
|
|
6035
6128
|
return { success: false, reason: "Campo de e-mail n\xE3o encontrado (poss\xEDvel captcha)" };
|
|
6036
6129
|
}
|
|
6130
|
+
await clearVisibleChallenge(page);
|
|
6131
|
+
const findPasswordModeButton = () => {
|
|
6132
|
+
return page.locator('button, [role="button"], a, div').filter({
|
|
6133
|
+
hasText: /(?:log\s*in\s*with\s*(?:a\s*)?password|fazer\s*login\s*com\s*senha|entrar\s*com\s*(?:uma\s*)?senha|iniciar\s*sesi[oó]n\s*con\s*contrase[nñ]a|密码登录)/i
|
|
6134
|
+
}).first();
|
|
6135
|
+
};
|
|
6037
6136
|
try {
|
|
6038
|
-
const pwdModeBtn =
|
|
6039
|
-
if (await pwdModeBtn.isVisible({ timeout:
|
|
6040
|
-
await pwdModeBtn.click().catch(() => {
|
|
6137
|
+
const pwdModeBtn = findPasswordModeButton();
|
|
6138
|
+
if (await pwdModeBtn.isVisible({ timeout: 2e3 }).catch(() => false)) {
|
|
6139
|
+
await pwdModeBtn.click({ timeout: 2e3 }).catch(() => {
|
|
6041
6140
|
});
|
|
6042
6141
|
await sleep2(500);
|
|
6043
6142
|
}
|
|
@@ -6046,9 +6145,9 @@ async function loginViaUi(page, email, password) {
|
|
|
6046
6145
|
await page.fill(emailSelector, email);
|
|
6047
6146
|
await sleep2(300);
|
|
6048
6147
|
try {
|
|
6049
|
-
const pwdModeBtn =
|
|
6050
|
-
if (await pwdModeBtn.isVisible({ timeout:
|
|
6051
|
-
await pwdModeBtn.click().catch(() => {
|
|
6148
|
+
const pwdModeBtn = findPasswordModeButton();
|
|
6149
|
+
if (await pwdModeBtn.isVisible({ timeout: 1500 }).catch(() => false)) {
|
|
6150
|
+
await pwdModeBtn.click({ timeout: 2e3 }).catch(() => {
|
|
6052
6151
|
});
|
|
6053
6152
|
await sleep2(500);
|
|
6054
6153
|
}
|
|
@@ -6073,7 +6172,7 @@ async function loginViaUi(page, email, password) {
|
|
|
6073
6172
|
}
|
|
6074
6173
|
await page.fill(passwordSelector, password);
|
|
6075
6174
|
await sleep2(500);
|
|
6076
|
-
const submitSelector = 'button.qwenchat-auth-pc-submit-button, button[type="submit"], button:has-text("Log in"), button:has-text("Sign in")';
|
|
6175
|
+
const submitSelector = 'button.qwenchat-auth-pc-submit-button, button[type="submit"], button:has-text("Log in"), button:has-text("Sign in"), button:has-text("Fazer login"), button:has-text("Entrar"), button:has-text("Iniciar sesi\xF3n"), button:has-text("\u767B\u5F55")';
|
|
6077
6176
|
const submitButton = page.locator(submitSelector).first();
|
|
6078
6177
|
try {
|
|
6079
6178
|
await page.waitForSelector('button[type="submit"]:not([disabled])', {
|
|
@@ -6678,7 +6777,7 @@ async function refreshHeadersInternal(accountId, timeoutMs = config.timeouts.hea
|
|
|
6678
6777
|
await executeReauth();
|
|
6679
6778
|
}
|
|
6680
6779
|
}
|
|
6681
|
-
if (
|
|
6780
|
+
if (hasRequiredQwenHeaders(cache3.headers)) {
|
|
6682
6781
|
const liveCookies = await page.context().cookies();
|
|
6683
6782
|
if (liveCookies.some((c) => c.name === "token")) {
|
|
6684
6783
|
const cookieStr = liveCookies.map((c) => `${c.name}=${c.value}`).join("; ");
|
|
@@ -6794,12 +6893,12 @@ async function resetPlaywrightProfileLocked(accountId) {
|
|
|
6794
6893
|
removePlaywrightProfile(profilePath);
|
|
6795
6894
|
const stateFile2 = path6.join(path6.dirname(profilePath), `${accountId}_state.json`);
|
|
6796
6895
|
try {
|
|
6797
|
-
|
|
6896
|
+
fs9.rmSync(stateFile2, { force: true });
|
|
6798
6897
|
} catch {
|
|
6799
6898
|
}
|
|
6800
6899
|
}
|
|
6801
6900
|
function removePlaywrightProfile(profilePath, rmSyncOverride) {
|
|
6802
|
-
const doRemove = rmSyncOverride ?? ((p, opts) =>
|
|
6901
|
+
const doRemove = rmSyncOverride ?? ((p, opts) => fs9.rmSync(p, opts));
|
|
6803
6902
|
try {
|
|
6804
6903
|
doRemove(profilePath, { recursive: true, force: true });
|
|
6805
6904
|
} catch (error) {
|
|
@@ -6808,7 +6907,7 @@ function removePlaywrightProfile(profilePath, rmSyncOverride) {
|
|
|
6808
6907
|
if (message.includes("EPERM") || message.includes("EBUSY") || message.includes("Permission denied")) {
|
|
6809
6908
|
try {
|
|
6810
6909
|
const stalePath = `${profilePath}.stale-${Date.now()}`;
|
|
6811
|
-
|
|
6910
|
+
fs9.renameSync(profilePath, stalePath);
|
|
6812
6911
|
} catch {
|
|
6813
6912
|
}
|
|
6814
6913
|
return;
|
|
@@ -6831,23 +6930,23 @@ function prunePlaywrightProfileCaches(profilePath) {
|
|
|
6831
6930
|
let freedFiles = 0;
|
|
6832
6931
|
try {
|
|
6833
6932
|
const defaultDir = path6.join(profilePath, "Default");
|
|
6834
|
-
if (!
|
|
6933
|
+
if (!fs9.existsSync(defaultDir)) {
|
|
6835
6934
|
return { freedBytes, freedFiles };
|
|
6836
6935
|
}
|
|
6837
6936
|
for (const dirName of transientDirNames) {
|
|
6838
6937
|
const targetDir = path6.join(defaultDir, dirName);
|
|
6839
|
-
if (
|
|
6938
|
+
if (fs9.existsSync(targetDir)) {
|
|
6840
6939
|
try {
|
|
6841
6940
|
const countAndRemove = (d) => {
|
|
6842
6941
|
try {
|
|
6843
|
-
const entries =
|
|
6942
|
+
const entries = fs9.readdirSync(d, { withFileTypes: true });
|
|
6844
6943
|
for (const e of entries) {
|
|
6845
6944
|
const full = path6.join(d, e.name);
|
|
6846
6945
|
if (e.isDirectory()) {
|
|
6847
6946
|
countAndRemove(full);
|
|
6848
6947
|
} else if (e.isFile()) {
|
|
6849
6948
|
try {
|
|
6850
|
-
freedBytes +=
|
|
6949
|
+
freedBytes += fs9.statSync(full).size;
|
|
6851
6950
|
freedFiles++;
|
|
6852
6951
|
} catch {
|
|
6853
6952
|
}
|
|
@@ -6857,7 +6956,7 @@ function prunePlaywrightProfileCaches(profilePath) {
|
|
|
6857
6956
|
}
|
|
6858
6957
|
};
|
|
6859
6958
|
countAndRemove(targetDir);
|
|
6860
|
-
|
|
6959
|
+
fs9.rmSync(targetDir, { recursive: true, force: true });
|
|
6861
6960
|
} catch {
|
|
6862
6961
|
}
|
|
6863
6962
|
}
|
|
@@ -6871,10 +6970,10 @@ function pruneAllPlaywrightProfiles(baseDir = getProfilesDir()) {
|
|
|
6871
6970
|
let totalFreedFiles = 0;
|
|
6872
6971
|
let profilesCleaned = 0;
|
|
6873
6972
|
try {
|
|
6874
|
-
if (!
|
|
6973
|
+
if (!fs9.existsSync(baseDir)) {
|
|
6875
6974
|
return { totalFreedBytes, totalFreedFiles, profilesCleaned };
|
|
6876
6975
|
}
|
|
6877
|
-
const entries =
|
|
6976
|
+
const entries = fs9.readdirSync(baseDir, { withFileTypes: true });
|
|
6878
6977
|
for (const entry of entries) {
|
|
6879
6978
|
if (entry.isDirectory()) {
|
|
6880
6979
|
const profilePath = path6.join(baseDir, entry.name);
|
|
@@ -6894,11 +6993,11 @@ function cleanupOrphanProfiles(baseDir = getProfilesDir(), activeAccountIds) {
|
|
|
6894
6993
|
let removedCount = 0;
|
|
6895
6994
|
let freedBytes = 0;
|
|
6896
6995
|
try {
|
|
6897
|
-
if (!
|
|
6996
|
+
if (!fs9.existsSync(baseDir)) {
|
|
6898
6997
|
return { removedCount, freedBytes };
|
|
6899
6998
|
}
|
|
6900
6999
|
const activeIds = activeAccountIds ?? new Set(loadAccounts().map((a) => a.id));
|
|
6901
|
-
const entries =
|
|
7000
|
+
const entries = fs9.readdirSync(baseDir, { withFileTypes: true });
|
|
6902
7001
|
for (const entry of entries) {
|
|
6903
7002
|
if (!entry.isDirectory()) continue;
|
|
6904
7003
|
const isStale = entry.name.includes(".stale-");
|
|
@@ -6909,13 +7008,13 @@ function cleanupOrphanProfiles(baseDir = getProfilesDir(), activeAccountIds) {
|
|
|
6909
7008
|
let bytes = 0;
|
|
6910
7009
|
const countSize = (d) => {
|
|
6911
7010
|
try {
|
|
6912
|
-
const subEntries =
|
|
7011
|
+
const subEntries = fs9.readdirSync(d, { withFileTypes: true });
|
|
6913
7012
|
for (const e of subEntries) {
|
|
6914
7013
|
const full = path6.join(d, e.name);
|
|
6915
7014
|
if (e.isDirectory()) countSize(full);
|
|
6916
7015
|
else if (e.isFile()) {
|
|
6917
7016
|
try {
|
|
6918
|
-
bytes +=
|
|
7017
|
+
bytes += fs9.statSync(full).size;
|
|
6919
7018
|
} catch {
|
|
6920
7019
|
}
|
|
6921
7020
|
}
|
|
@@ -6925,7 +7024,7 @@ function cleanupOrphanProfiles(baseDir = getProfilesDir(), activeAccountIds) {
|
|
|
6925
7024
|
};
|
|
6926
7025
|
countSize(targetPath);
|
|
6927
7026
|
removePlaywrightProfile(targetPath);
|
|
6928
|
-
if (!
|
|
7027
|
+
if (!fs9.existsSync(targetPath)) {
|
|
6929
7028
|
removedCount++;
|
|
6930
7029
|
freedBytes += bytes;
|
|
6931
7030
|
}
|
|
@@ -11083,10 +11182,17 @@ async function withQwenBrowserPage(accountId, fn, targetPath, operationTimeoutMs
|
|
|
11083
11182
|
}
|
|
11084
11183
|
const needsNavigation = currentOrigin !== targetOrigin || normalizedTargetPath !== null && currentPath !== normalizedTargetPath;
|
|
11085
11184
|
if (needsNavigation) {
|
|
11086
|
-
|
|
11087
|
-
|
|
11088
|
-
|
|
11089
|
-
|
|
11185
|
+
try {
|
|
11186
|
+
await page.goto(targetUrl, {
|
|
11187
|
+
waitUntil: "domcontentloaded",
|
|
11188
|
+
timeout: Math.min(config.timeouts.navigation, operationTimeoutMs)
|
|
11189
|
+
});
|
|
11190
|
+
} catch (err) {
|
|
11191
|
+
if (err?.message?.includes("ERR_ABORTED") && page.url().startsWith(targetOrigin)) {
|
|
11192
|
+
} else {
|
|
11193
|
+
throw err;
|
|
11194
|
+
}
|
|
11195
|
+
}
|
|
11090
11196
|
}
|
|
11091
11197
|
return fn(page);
|
|
11092
11198
|
},
|
|
@@ -11138,7 +11244,7 @@ async function requestQwenTextInBrowser(accountId, method, path21, headers, body
|
|
|
11138
11244
|
const controller = new AbortController();
|
|
11139
11245
|
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
11140
11246
|
try {
|
|
11141
|
-
|
|
11247
|
+
let response2 = await fetch(url2, {
|
|
11142
11248
|
method: method2,
|
|
11143
11249
|
credentials: "include",
|
|
11144
11250
|
headers: headers2,
|
|
@@ -11146,6 +11252,36 @@ async function requestQwenTextInBrowser(accountId, method, path21, headers, body
|
|
|
11146
11252
|
signal: controller.signal,
|
|
11147
11253
|
...referrer ? { referrer } : {}
|
|
11148
11254
|
});
|
|
11255
|
+
if (response2.status === 401) {
|
|
11256
|
+
try {
|
|
11257
|
+
const refreshRes = await fetch("https://auth.qwen.ai/api/v2/auths/refresh", {
|
|
11258
|
+
method: "GET",
|
|
11259
|
+
credentials: "include",
|
|
11260
|
+
signal: AbortSignal.timeout(3e3)
|
|
11261
|
+
});
|
|
11262
|
+
if (refreshRes.status === 200) {
|
|
11263
|
+
const refreshJson = await refreshRes.json().catch(() => null);
|
|
11264
|
+
if (refreshJson && refreshJson.success === true && refreshJson.data?.token) {
|
|
11265
|
+
const freshTok = refreshJson.data.token;
|
|
11266
|
+
localStorage.setItem("token", freshTok);
|
|
11267
|
+
document.cookie = `token=${encodeURIComponent(freshTok)}; path=/; domain=.qwen.ai; max-age=31536000`;
|
|
11268
|
+
if (headers2["authorization"] || headers2["Authorization"]) {
|
|
11269
|
+
headers2["authorization"] = `Bearer ${freshTok}`;
|
|
11270
|
+
headers2["Authorization"] = `Bearer ${freshTok}`;
|
|
11271
|
+
}
|
|
11272
|
+
response2 = await fetch(url2, {
|
|
11273
|
+
method: method2,
|
|
11274
|
+
credentials: "include",
|
|
11275
|
+
headers: headers2,
|
|
11276
|
+
body: body2,
|
|
11277
|
+
signal: controller.signal,
|
|
11278
|
+
...referrer ? { referrer } : {}
|
|
11279
|
+
});
|
|
11280
|
+
}
|
|
11281
|
+
}
|
|
11282
|
+
} catch {
|
|
11283
|
+
}
|
|
11284
|
+
}
|
|
11149
11285
|
return {
|
|
11150
11286
|
status: response2.status,
|
|
11151
11287
|
contentType: response2.headers.get("content-type") || "",
|
|
@@ -11247,18 +11383,6 @@ async function requestQwenSettingsDirectFetch(accountId, method, path21, headers
|
|
|
11247
11383
|
}
|
|
11248
11384
|
}
|
|
11249
11385
|
async function requestQwenPersonalizationInBrowser(accountId, method, path21, headers, payload) {
|
|
11250
|
-
if (!config.qwen.browserOnlyFetch && !isAuthMockEnabled()) {
|
|
11251
|
-
const direct = await requestQwenSettingsDirectFetch(
|
|
11252
|
-
accountId,
|
|
11253
|
-
method,
|
|
11254
|
-
path21,
|
|
11255
|
-
headers,
|
|
11256
|
-
payload
|
|
11257
|
-
);
|
|
11258
|
-
if (direct) {
|
|
11259
|
-
return direct;
|
|
11260
|
-
}
|
|
11261
|
-
}
|
|
11262
11386
|
const response = await requestQwenTextInBrowser(
|
|
11263
11387
|
accountId,
|
|
11264
11388
|
method,
|
|
@@ -21907,6 +22031,7 @@ async function chatCompletions(c) {
|
|
|
21907
22031
|
)) {
|
|
21908
22032
|
c.header(name, value);
|
|
21909
22033
|
}
|
|
22034
|
+
c.header("X-QwenProxy-Account", streamResult.activeAccountLabel);
|
|
21910
22035
|
const replayed = streamResult.replayedFullContext === true;
|
|
21911
22036
|
console.log(
|
|
21912
22037
|
`\u{1F4E4} [${routeLabel}] Request | req=${reqId} | ${streamResult.activeAccountLabel} | ${body.model} | ${replayed ? parsed.messageCount : msgCount} msg(s) | ${replayed ? fullPromptForRequest.length : finalPrompt.length} chars${replayed ? " | full-replay" : ""} | chat=${streamResult.uiSessionId.substring(0, 12)}${declaredTools.length ? ` | ${declaredTools.length} tool(s)` : ""}${files.length ? ` | ${files.length} file(s)` : ""} | +${Date.now() - reqStartedAt}ms`
|
|
@@ -25160,18 +25285,18 @@ var init_theme = __esm({
|
|
|
25160
25285
|
});
|
|
25161
25286
|
|
|
25162
25287
|
// src/core/server-log-buffer.ts
|
|
25163
|
-
import
|
|
25288
|
+
import fs10 from "node:fs";
|
|
25164
25289
|
function appendServerLogToFile(time, level, message) {
|
|
25165
25290
|
if (isRunningUnderNodeTest()) return;
|
|
25166
25291
|
try {
|
|
25167
25292
|
const filePath = getServerLogFilePath();
|
|
25168
|
-
if (
|
|
25169
|
-
const stats =
|
|
25293
|
+
if (fs10.existsSync(filePath)) {
|
|
25294
|
+
const stats = fs10.statSync(filePath);
|
|
25170
25295
|
if (stats.size > 20 * 1024 * 1024) {
|
|
25171
25296
|
const oldPath = filePath + ".old";
|
|
25172
25297
|
try {
|
|
25173
|
-
if (
|
|
25174
|
-
|
|
25298
|
+
if (fs10.existsSync(oldPath)) fs10.unlinkSync(oldPath);
|
|
25299
|
+
fs10.renameSync(filePath, oldPath);
|
|
25175
25300
|
} catch {
|
|
25176
25301
|
}
|
|
25177
25302
|
}
|
|
@@ -25181,7 +25306,7 @@ function appendServerLogToFile(time, level, message) {
|
|
|
25181
25306
|
const dateStr = (/* @__PURE__ */ new Date()).toLocaleDateString("pt-BR");
|
|
25182
25307
|
const line = `[${dateStr} ${time}] [${level}] ${message}
|
|
25183
25308
|
`;
|
|
25184
|
-
|
|
25309
|
+
fs10.appendFileSync(filePath, line, "utf-8");
|
|
25185
25310
|
} catch {
|
|
25186
25311
|
}
|
|
25187
25312
|
}
|
|
@@ -25356,7 +25481,7 @@ var version_exports = {};
|
|
|
25356
25481
|
__export(version_exports, {
|
|
25357
25482
|
getAppVersion: () => getAppVersion
|
|
25358
25483
|
});
|
|
25359
|
-
import
|
|
25484
|
+
import fs11 from "node:fs";
|
|
25360
25485
|
import path7 from "node:path";
|
|
25361
25486
|
import { fileURLToPath } from "node:url";
|
|
25362
25487
|
function getAppVersion() {
|
|
@@ -25364,8 +25489,8 @@ function getAppVersion() {
|
|
|
25364
25489
|
try {
|
|
25365
25490
|
const currentDir = path7.dirname(fileURLToPath(import.meta.url));
|
|
25366
25491
|
const pkgPath = path7.resolve(currentDir, "../../package.json");
|
|
25367
|
-
if (
|
|
25368
|
-
const pkg = JSON.parse(
|
|
25492
|
+
if (fs11.existsSync(pkgPath)) {
|
|
25493
|
+
const pkg = JSON.parse(fs11.readFileSync(pkgPath, "utf-8"));
|
|
25369
25494
|
if (pkg.version) {
|
|
25370
25495
|
cachedVersion = `v${pkg.version}`;
|
|
25371
25496
|
return cachedVersion;
|
|
@@ -25373,7 +25498,7 @@ function getAppVersion() {
|
|
|
25373
25498
|
}
|
|
25374
25499
|
} catch {
|
|
25375
25500
|
}
|
|
25376
|
-
cachedVersion = "v1.4.
|
|
25501
|
+
cachedVersion = "v1.4.2";
|
|
25377
25502
|
return cachedVersion;
|
|
25378
25503
|
}
|
|
25379
25504
|
var cachedVersion;
|
|
@@ -26486,7 +26611,7 @@ var init_server_manager = __esm({
|
|
|
26486
26611
|
|
|
26487
26612
|
// src/tui/screen.ts
|
|
26488
26613
|
import readline from "node:readline";
|
|
26489
|
-
import
|
|
26614
|
+
import fs12 from "node:fs";
|
|
26490
26615
|
var Screen;
|
|
26491
26616
|
var init_screen = __esm({
|
|
26492
26617
|
"src/tui/screen.ts"() {
|
|
@@ -26706,7 +26831,7 @@ var init_screen = __esm({
|
|
|
26706
26831
|
this.lastHoverTime = 0;
|
|
26707
26832
|
const restoreSeq = ANSI.disableMouse + ANSI.exitAltScreen + ANSI.showCursor + ANSI.reset;
|
|
26708
26833
|
try {
|
|
26709
|
-
|
|
26834
|
+
fs12.writeSync(1, restoreSeq);
|
|
26710
26835
|
} catch {
|
|
26711
26836
|
try {
|
|
26712
26837
|
ServerManager.getInstance().withTuiRendering(() => {
|
|
@@ -29151,7 +29276,7 @@ var init_chat_view = __esm({
|
|
|
29151
29276
|
});
|
|
29152
29277
|
|
|
29153
29278
|
// src/sync/utils.ts
|
|
29154
|
-
import
|
|
29279
|
+
import fs13 from "node:fs";
|
|
29155
29280
|
import path8 from "node:path";
|
|
29156
29281
|
function createTimestampBackup(filePath) {
|
|
29157
29282
|
const dir = path8.dirname(filePath);
|
|
@@ -29161,19 +29286,19 @@ function createTimestampBackup(filePath) {
|
|
|
29161
29286
|
const pad2 = (n) => String(n).padStart(2, "0");
|
|
29162
29287
|
const timestamp = `${now.getFullYear()}${pad2(now.getMonth() + 1)}${pad2(now.getDate())}_${pad2(now.getHours())}${pad2(now.getMinutes())}${pad2(now.getSeconds())}`;
|
|
29163
29288
|
const backupPath = path8.join(dir, `${base}.qwenproxy.${timestamp}${ext}.bak`);
|
|
29164
|
-
|
|
29289
|
+
fs13.copyFileSync(filePath, backupPath);
|
|
29165
29290
|
return backupPath;
|
|
29166
29291
|
}
|
|
29167
29292
|
function findLatestBackup(filePath) {
|
|
29168
29293
|
const dir = path8.dirname(filePath);
|
|
29169
29294
|
const ext = path8.extname(filePath);
|
|
29170
29295
|
const base = path8.basename(filePath, ext);
|
|
29171
|
-
if (!
|
|
29296
|
+
if (!fs13.existsSync(dir)) return void 0;
|
|
29172
29297
|
try {
|
|
29173
|
-
const files =
|
|
29298
|
+
const files = fs13.readdirSync(dir);
|
|
29174
29299
|
const candidates = files.filter((f) => f.startsWith(base) && f.includes("qwenproxy") && f.endsWith(".bak")).map((f) => path8.join(dir, f)).sort((a, b) => {
|
|
29175
29300
|
try {
|
|
29176
|
-
return
|
|
29301
|
+
return fs13.statSync(b).mtimeMs - fs13.statSync(a).mtimeMs;
|
|
29177
29302
|
} catch {
|
|
29178
29303
|
return 0;
|
|
29179
29304
|
}
|
|
@@ -29184,13 +29309,13 @@ function findLatestBackup(filePath) {
|
|
|
29184
29309
|
}
|
|
29185
29310
|
}
|
|
29186
29311
|
function restoreFromBackup(filePath, backupPath) {
|
|
29187
|
-
const targetBackup = backupPath &&
|
|
29188
|
-
if (!targetBackup || !
|
|
29312
|
+
const targetBackup = backupPath && fs13.existsSync(backupPath) ? backupPath : findLatestBackup(filePath);
|
|
29313
|
+
if (!targetBackup || !fs13.existsSync(targetBackup)) {
|
|
29189
29314
|
return false;
|
|
29190
29315
|
}
|
|
29191
|
-
|
|
29316
|
+
fs13.copyFileSync(targetBackup, filePath);
|
|
29192
29317
|
try {
|
|
29193
|
-
|
|
29318
|
+
fs13.unlinkSync(targetBackup);
|
|
29194
29319
|
} catch {
|
|
29195
29320
|
}
|
|
29196
29321
|
return true;
|
|
@@ -29209,18 +29334,18 @@ var init_utils = __esm({
|
|
|
29209
29334
|
});
|
|
29210
29335
|
|
|
29211
29336
|
// src/sync/claude-code.ts
|
|
29212
|
-
import
|
|
29337
|
+
import fs14 from "node:fs";
|
|
29213
29338
|
import path9 from "node:path";
|
|
29214
29339
|
function syncClaudeCode(options) {
|
|
29215
29340
|
const { filePath, apiKey, baseUrl, model = "qwen3.8-max" } = options;
|
|
29216
29341
|
try {
|
|
29217
|
-
|
|
29342
|
+
fs14.mkdirSync(path9.dirname(filePath), { recursive: true });
|
|
29218
29343
|
let backupPath;
|
|
29219
29344
|
let existingSettings = {};
|
|
29220
|
-
if (
|
|
29345
|
+
if (fs14.existsSync(filePath)) {
|
|
29221
29346
|
backupPath = createTimestampBackup(filePath);
|
|
29222
29347
|
try {
|
|
29223
|
-
const content =
|
|
29348
|
+
const content = fs14.readFileSync(filePath, "utf-8");
|
|
29224
29349
|
existingSettings = JSON.parse(content);
|
|
29225
29350
|
} catch {
|
|
29226
29351
|
existingSettings = {};
|
|
@@ -29246,7 +29371,7 @@ function syncClaudeCode(options) {
|
|
|
29246
29371
|
model,
|
|
29247
29372
|
enableArtifact: false
|
|
29248
29373
|
};
|
|
29249
|
-
|
|
29374
|
+
fs14.writeFileSync(filePath, JSON.stringify(updatedSettings, null, 2) + "\n", "utf-8");
|
|
29250
29375
|
return {
|
|
29251
29376
|
client: "claude-code",
|
|
29252
29377
|
filePath,
|
|
@@ -29268,9 +29393,9 @@ function syncClaudeCode(options) {
|
|
|
29268
29393
|
function restoreClaudeCode(filePath, backupPath) {
|
|
29269
29394
|
const restoredFromBackup = restoreFromBackup(filePath, backupPath);
|
|
29270
29395
|
let manuallyCleaned = false;
|
|
29271
|
-
if (
|
|
29396
|
+
if (fs14.existsSync(filePath)) {
|
|
29272
29397
|
try {
|
|
29273
|
-
const data = JSON.parse(
|
|
29398
|
+
const data = JSON.parse(fs14.readFileSync(filePath, "utf-8"));
|
|
29274
29399
|
if (data.env && (data.env.ANTHROPIC_BASE_URL?.includes("7936") || data.env.ANTHROPIC_AUTH_TOKEN === "sk-qwenproxy-local" || data.env.ANTHROPIC_MODEL?.includes("qwen"))) {
|
|
29275
29400
|
delete data.env.ANTHROPIC_BASE_URL;
|
|
29276
29401
|
delete data.env.ANTHROPIC_AUTH_TOKEN;
|
|
@@ -29290,7 +29415,7 @@ function restoreClaudeCode(filePath, backupPath) {
|
|
|
29290
29415
|
if (Object.keys(data.env).length === 0) {
|
|
29291
29416
|
delete data.env;
|
|
29292
29417
|
}
|
|
29293
|
-
|
|
29418
|
+
fs14.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
29294
29419
|
manuallyCleaned = true;
|
|
29295
29420
|
}
|
|
29296
29421
|
} catch {
|
|
@@ -29314,7 +29439,7 @@ var init_claude_code = __esm({
|
|
|
29314
29439
|
});
|
|
29315
29440
|
|
|
29316
29441
|
// src/sync/codex.ts
|
|
29317
|
-
import
|
|
29442
|
+
import fs15 from "node:fs";
|
|
29318
29443
|
import path10 from "node:path";
|
|
29319
29444
|
import os4 from "node:os";
|
|
29320
29445
|
function removeTomlSection(content, sectionHeader) {
|
|
@@ -29355,12 +29480,12 @@ function updateTopLevelKey(content, key, value) {
|
|
|
29355
29480
|
return newTopPart + restPart;
|
|
29356
29481
|
}
|
|
29357
29482
|
function syncCodexSingleFile(targetPath, options) {
|
|
29358
|
-
|
|
29483
|
+
fs15.mkdirSync(path10.dirname(targetPath), { recursive: true });
|
|
29359
29484
|
let backupPath;
|
|
29360
29485
|
let content = "";
|
|
29361
|
-
if (
|
|
29486
|
+
if (fs15.existsSync(targetPath)) {
|
|
29362
29487
|
backupPath = createTimestampBackup(targetPath);
|
|
29363
|
-
content =
|
|
29488
|
+
content = fs15.readFileSync(targetPath, "utf-8");
|
|
29364
29489
|
}
|
|
29365
29490
|
const { apiKey, baseUrl, model = "qwen3.8-max", setActive = true } = options;
|
|
29366
29491
|
const providerBlock = `[model_providers.qwenproxy]
|
|
@@ -29381,8 +29506,8 @@ experimental_bearer_token = "${apiKey}"
|
|
|
29381
29506
|
try {
|
|
29382
29507
|
const rawCatalogPath = catalogMatch[1];
|
|
29383
29508
|
const catalogPath = path10.isAbsolute(rawCatalogPath) ? rawCatalogPath : path10.resolve(path10.dirname(targetPath), rawCatalogPath);
|
|
29384
|
-
if (
|
|
29385
|
-
const catalog = JSON.parse(
|
|
29509
|
+
if (fs15.existsSync(catalogPath)) {
|
|
29510
|
+
const catalog = JSON.parse(fs15.readFileSync(catalogPath, "utf-8"));
|
|
29386
29511
|
if (Array.isArray(catalog.models)) {
|
|
29387
29512
|
const hasModel = catalog.models.some((m) => m?.slug === model);
|
|
29388
29513
|
if (!hasModel) {
|
|
@@ -29395,14 +29520,14 @@ experimental_bearer_token = "${apiKey}"
|
|
|
29395
29520
|
context_window: 1e6,
|
|
29396
29521
|
max_context_window: 1e6
|
|
29397
29522
|
});
|
|
29398
|
-
|
|
29523
|
+
fs15.writeFileSync(catalogPath, JSON.stringify(catalog, null, 2), "utf-8");
|
|
29399
29524
|
}
|
|
29400
29525
|
}
|
|
29401
29526
|
}
|
|
29402
29527
|
} catch {
|
|
29403
29528
|
}
|
|
29404
29529
|
}
|
|
29405
|
-
|
|
29530
|
+
fs15.writeFileSync(targetPath, content.trimEnd() + "\n", "utf-8");
|
|
29406
29531
|
return { backupPath };
|
|
29407
29532
|
}
|
|
29408
29533
|
function syncCodex(options) {
|
|
@@ -29418,7 +29543,7 @@ function syncCodex(options) {
|
|
|
29418
29543
|
const alternatePath = isStandard ? codexHomePath : standardPath;
|
|
29419
29544
|
if (alternatePath && path10.resolve(alternatePath).toLowerCase() !== path10.resolve(filePath).toLowerCase()) {
|
|
29420
29545
|
try {
|
|
29421
|
-
if (
|
|
29546
|
+
if (fs15.existsSync(alternatePath) || fs15.existsSync(path10.dirname(alternatePath))) {
|
|
29422
29547
|
syncCodexSingleFile(alternatePath, options);
|
|
29423
29548
|
}
|
|
29424
29549
|
} catch {
|
|
@@ -29447,16 +29572,16 @@ function restoreCodex(filePath, backupPath) {
|
|
|
29447
29572
|
const restoredFromBackup = restoreFromBackup(filePath, backupPath);
|
|
29448
29573
|
let manuallyCleaned = false;
|
|
29449
29574
|
const cleanSingleFile = (p) => {
|
|
29450
|
-
if (
|
|
29575
|
+
if (fs15.existsSync(p)) {
|
|
29451
29576
|
try {
|
|
29452
|
-
let content =
|
|
29577
|
+
let content = fs15.readFileSync(p, "utf-8");
|
|
29453
29578
|
if (content.includes("[model_providers.qwenproxy]") || /^model_provider\s*=\s*["']qwenproxy["']/m.test(content)) {
|
|
29454
29579
|
content = removeTomlSection(content, "model_providers.qwenproxy");
|
|
29455
29580
|
content = content.replace(/^model_provider\s*=\s*["']qwenproxy["']\r?\n?/m, "");
|
|
29456
29581
|
if (/^model\s*=\s*["']qwen/m.test(content)) {
|
|
29457
29582
|
content = content.replace(/^model\s*=\s*["']qwen[^"']*["']\r?\n?/m, "");
|
|
29458
29583
|
}
|
|
29459
|
-
|
|
29584
|
+
fs15.writeFileSync(p, content.trimEnd() + "\n", "utf-8");
|
|
29460
29585
|
manuallyCleaned = true;
|
|
29461
29586
|
}
|
|
29462
29587
|
} catch {
|
|
@@ -29494,7 +29619,7 @@ var init_codex = __esm({
|
|
|
29494
29619
|
});
|
|
29495
29620
|
|
|
29496
29621
|
// src/sync/opencode.ts
|
|
29497
|
-
import
|
|
29622
|
+
import fs16 from "node:fs";
|
|
29498
29623
|
import path11 from "node:path";
|
|
29499
29624
|
function buildOpenCodeProviderObject(baseUrl, apiKey, primaryModel = "qwen3.8-max", models) {
|
|
29500
29625
|
const modelsObj = {};
|
|
@@ -29620,12 +29745,12 @@ function syncOpenCode(options) {
|
|
|
29620
29745
|
setActive = true
|
|
29621
29746
|
} = options;
|
|
29622
29747
|
try {
|
|
29623
|
-
|
|
29748
|
+
fs16.mkdirSync(path11.dirname(filePath), { recursive: true });
|
|
29624
29749
|
let backupPath;
|
|
29625
29750
|
let content = "";
|
|
29626
|
-
if (
|
|
29751
|
+
if (fs16.existsSync(filePath)) {
|
|
29627
29752
|
backupPath = createTimestampBackup(filePath);
|
|
29628
|
-
content =
|
|
29753
|
+
content = fs16.readFileSync(filePath, "utf-8");
|
|
29629
29754
|
}
|
|
29630
29755
|
const providerObj = buildOpenCodeProviderObject(baseUrl, apiKey, model, models);
|
|
29631
29756
|
const providerJson = JSON.stringify(providerObj, null, 6).split("\n").map((line, idx) => idx === 0 ? line : ` ${line}`).join("\n");
|
|
@@ -29640,7 +29765,7 @@ function syncOpenCode(options) {
|
|
|
29640
29765
|
initial.provider = {
|
|
29641
29766
|
qwenproxy: providerObj
|
|
29642
29767
|
};
|
|
29643
|
-
|
|
29768
|
+
fs16.writeFileSync(filePath, JSON.stringify(initial, null, 2) + "\n", "utf-8");
|
|
29644
29769
|
} else {
|
|
29645
29770
|
const existingSpan = findKeyObjectSpan(content, "qwenproxy");
|
|
29646
29771
|
if (existingSpan) {
|
|
@@ -29664,7 +29789,7 @@ ${qwenEntry}
|
|
|
29664
29789
|
}
|
|
29665
29790
|
}
|
|
29666
29791
|
}
|
|
29667
|
-
|
|
29792
|
+
fs16.writeFileSync(
|
|
29668
29793
|
filePath,
|
|
29669
29794
|
applyOpenCodeActiveModel(content, model, setActive),
|
|
29670
29795
|
"utf-8"
|
|
@@ -29691,9 +29816,9 @@ ${qwenEntry}
|
|
|
29691
29816
|
function restoreOpenCode(filePath, backupPath) {
|
|
29692
29817
|
const restoredFromBackup = restoreFromBackup(filePath, backupPath);
|
|
29693
29818
|
let manuallyCleaned = false;
|
|
29694
|
-
if (
|
|
29819
|
+
if (fs16.existsSync(filePath)) {
|
|
29695
29820
|
try {
|
|
29696
|
-
const data = JSON.parse(
|
|
29821
|
+
const data = JSON.parse(fs16.readFileSync(filePath, "utf-8"));
|
|
29697
29822
|
if (data.provider && data.provider.qwenproxy) {
|
|
29698
29823
|
delete data.provider.qwenproxy;
|
|
29699
29824
|
if (data.model && data.model.includes("qwen")) {
|
|
@@ -29702,7 +29827,7 @@ function restoreOpenCode(filePath, backupPath) {
|
|
|
29702
29827
|
if (Object.keys(data.provider).length === 0) {
|
|
29703
29828
|
delete data.provider;
|
|
29704
29829
|
}
|
|
29705
|
-
|
|
29830
|
+
fs16.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
29706
29831
|
manuallyCleaned = true;
|
|
29707
29832
|
}
|
|
29708
29833
|
} catch {
|
|
@@ -29726,7 +29851,7 @@ var init_opencode = __esm({
|
|
|
29726
29851
|
});
|
|
29727
29852
|
|
|
29728
29853
|
// src/sync/omp.ts
|
|
29729
|
-
import
|
|
29854
|
+
import fs17 from "node:fs";
|
|
29730
29855
|
import path12 from "node:path";
|
|
29731
29856
|
function buildOmpProviderYaml(baseUrl, apiKey, primaryModel = "qwen3.8-max", models) {
|
|
29732
29857
|
const modelList = Array.from(
|
|
@@ -29758,12 +29883,12 @@ ${formattedModels}
|
|
|
29758
29883
|
function syncOmp(options) {
|
|
29759
29884
|
const { filePath, apiKey, baseUrl, model = "qwen3.8-max", models } = options;
|
|
29760
29885
|
try {
|
|
29761
|
-
|
|
29886
|
+
fs17.mkdirSync(path12.dirname(filePath), { recursive: true });
|
|
29762
29887
|
let backupPath;
|
|
29763
29888
|
let content = "";
|
|
29764
|
-
if (
|
|
29889
|
+
if (fs17.existsSync(filePath)) {
|
|
29765
29890
|
backupPath = createTimestampBackup(filePath);
|
|
29766
|
-
content =
|
|
29891
|
+
content = fs17.readFileSync(filePath, "utf-8");
|
|
29767
29892
|
}
|
|
29768
29893
|
const providerBlock = buildOmpProviderYaml(baseUrl, apiKey, model, models);
|
|
29769
29894
|
if (!content.trim()) {
|
|
@@ -29783,7 +29908,7 @@ ${providerBlock}`;
|
|
|
29783
29908
|
}
|
|
29784
29909
|
}
|
|
29785
29910
|
}
|
|
29786
|
-
|
|
29911
|
+
fs17.writeFileSync(filePath, content.trimEnd() + "\n", "utf-8");
|
|
29787
29912
|
return {
|
|
29788
29913
|
client: "omp",
|
|
29789
29914
|
filePath,
|
|
@@ -29805,13 +29930,13 @@ ${providerBlock}`;
|
|
|
29805
29930
|
function restoreOmp(filePath, backupPath) {
|
|
29806
29931
|
const restoredFromBackup = restoreFromBackup(filePath, backupPath);
|
|
29807
29932
|
let manuallyCleaned = false;
|
|
29808
|
-
if (
|
|
29933
|
+
if (fs17.existsSync(filePath)) {
|
|
29809
29934
|
try {
|
|
29810
|
-
let content =
|
|
29935
|
+
let content = fs17.readFileSync(filePath, "utf-8");
|
|
29811
29936
|
if (content.includes("qwenproxy:")) {
|
|
29812
29937
|
const regex = /^\s*qwenproxy:\s*\r?\n(?:^[ \t].*\r?\n?)*/m;
|
|
29813
29938
|
content = content.replace(regex, "");
|
|
29814
|
-
|
|
29939
|
+
fs17.writeFileSync(filePath, content, "utf-8");
|
|
29815
29940
|
manuallyCleaned = true;
|
|
29816
29941
|
}
|
|
29817
29942
|
} catch {
|
|
@@ -29835,7 +29960,7 @@ var init_omp = __esm({
|
|
|
29835
29960
|
});
|
|
29836
29961
|
|
|
29837
29962
|
// src/sync/hermes.ts
|
|
29838
|
-
import
|
|
29963
|
+
import fs18 from "node:fs";
|
|
29839
29964
|
import path13 from "node:path";
|
|
29840
29965
|
function buildHermesModelBlock(baseUrl, apiKey, model = "qwen3.8-max", reasoningEffort = "high") {
|
|
29841
29966
|
return `model:
|
|
@@ -29859,12 +29984,12 @@ function buildHermesProviderBlock(baseUrl, apiKey) {
|
|
|
29859
29984
|
function syncHermes(options) {
|
|
29860
29985
|
const { filePath, apiKey, baseUrl, model = "qwen3.8-max", reasoningEffort = "high" } = options;
|
|
29861
29986
|
try {
|
|
29862
|
-
|
|
29987
|
+
fs18.mkdirSync(path13.dirname(filePath), { recursive: true });
|
|
29863
29988
|
let backupPath;
|
|
29864
29989
|
let content = "";
|
|
29865
|
-
if (
|
|
29990
|
+
if (fs18.existsSync(filePath)) {
|
|
29866
29991
|
backupPath = createTimestampBackup(filePath);
|
|
29867
|
-
content =
|
|
29992
|
+
content = fs18.readFileSync(filePath, "utf-8");
|
|
29868
29993
|
}
|
|
29869
29994
|
const modelBlock = buildHermesModelBlock(baseUrl, apiKey, model, reasoningEffort);
|
|
29870
29995
|
const providerBlock = buildHermesProviderBlock(baseUrl, apiKey);
|
|
@@ -29890,7 +30015,7 @@ function syncHermes(options) {
|
|
|
29890
30015
|
}
|
|
29891
30016
|
}
|
|
29892
30017
|
}
|
|
29893
|
-
|
|
30018
|
+
fs18.writeFileSync(filePath, content.trimEnd() + "\n", "utf-8");
|
|
29894
30019
|
return {
|
|
29895
30020
|
client: "hermes",
|
|
29896
30021
|
filePath,
|
|
@@ -29928,7 +30053,7 @@ var init_hermes = __esm({
|
|
|
29928
30053
|
});
|
|
29929
30054
|
|
|
29930
30055
|
// src/sync/openclaw.ts
|
|
29931
|
-
import
|
|
30056
|
+
import fs19 from "node:fs";
|
|
29932
30057
|
import path14 from "node:path";
|
|
29933
30058
|
function findKeyObjectSpan2(content, key) {
|
|
29934
30059
|
const regex = new RegExp(`"${key}"\\s*:\\s*\\{`);
|
|
@@ -30027,12 +30152,12 @@ function buildOpenClawProviderObject(baseUrl, apiKey, model = "qwen3.8-max", mod
|
|
|
30027
30152
|
function syncOpenClaw(options) {
|
|
30028
30153
|
const { filePath, apiKey, baseUrl, model = "qwen3.8-max", models, reasoningEffort = "high" } = options;
|
|
30029
30154
|
try {
|
|
30030
|
-
|
|
30155
|
+
fs19.mkdirSync(path14.dirname(filePath), { recursive: true });
|
|
30031
30156
|
let backupPath;
|
|
30032
30157
|
let content = "";
|
|
30033
|
-
if (
|
|
30158
|
+
if (fs19.existsSync(filePath)) {
|
|
30034
30159
|
backupPath = createTimestampBackup(filePath);
|
|
30035
|
-
content =
|
|
30160
|
+
content = fs19.readFileSync(filePath, "utf-8");
|
|
30036
30161
|
}
|
|
30037
30162
|
const providerObj = buildOpenClawProviderObject(baseUrl, apiKey, model, models);
|
|
30038
30163
|
const providerJson = JSON.stringify(providerObj, null, 6).split("\n").map((line, idx) => idx === 0 ? line : ` ${line}`).join("\n");
|
|
@@ -30056,7 +30181,7 @@ function syncOpenClaw(options) {
|
|
|
30056
30181
|
}
|
|
30057
30182
|
}
|
|
30058
30183
|
};
|
|
30059
|
-
|
|
30184
|
+
fs19.writeFileSync(filePath, JSON.stringify(initial, null, 2) + "\n", "utf-8");
|
|
30060
30185
|
} else {
|
|
30061
30186
|
const existingSpan = findKeyObjectSpan2(content, "qwenproxy");
|
|
30062
30187
|
if (existingSpan) {
|
|
@@ -30093,7 +30218,7 @@ ${qwenEntry}
|
|
|
30093
30218
|
}
|
|
30094
30219
|
}
|
|
30095
30220
|
}
|
|
30096
|
-
|
|
30221
|
+
fs19.writeFileSync(filePath, content, "utf-8");
|
|
30097
30222
|
}
|
|
30098
30223
|
return {
|
|
30099
30224
|
client: "openclaw",
|
|
@@ -30132,7 +30257,7 @@ var init_openclaw = __esm({
|
|
|
30132
30257
|
});
|
|
30133
30258
|
|
|
30134
30259
|
// src/sync/kilo.ts
|
|
30135
|
-
import
|
|
30260
|
+
import fs20 from "node:fs";
|
|
30136
30261
|
import path15 from "node:path";
|
|
30137
30262
|
function findKeyObjectSpan3(content, key) {
|
|
30138
30263
|
const regex = new RegExp(`"${key}"\\s*:\\s*\\{`);
|
|
@@ -30239,12 +30364,12 @@ function buildKiloProviderObject(baseUrl, apiKey, primaryModel = "qwen3.8-max",
|
|
|
30239
30364
|
function syncKilo(options) {
|
|
30240
30365
|
const { filePath, apiKey, baseUrl, model = "qwen3.8-max", models, setActive = true } = options;
|
|
30241
30366
|
try {
|
|
30242
|
-
|
|
30367
|
+
fs20.mkdirSync(path15.dirname(filePath), { recursive: true });
|
|
30243
30368
|
let backupPath;
|
|
30244
30369
|
let content = "";
|
|
30245
|
-
if (
|
|
30370
|
+
if (fs20.existsSync(filePath)) {
|
|
30246
30371
|
backupPath = createTimestampBackup(filePath);
|
|
30247
|
-
content =
|
|
30372
|
+
content = fs20.readFileSync(filePath, "utf-8");
|
|
30248
30373
|
}
|
|
30249
30374
|
const providerObj = buildKiloProviderObject(baseUrl, apiKey, model, models);
|
|
30250
30375
|
const providerJson = JSON.stringify(providerObj, null, 6).split("\n").map((line, idx) => idx === 0 ? line : ` ${line}`).join("\n");
|
|
@@ -30259,7 +30384,7 @@ function syncKilo(options) {
|
|
|
30259
30384
|
if (setActive) {
|
|
30260
30385
|
initial.model = `qwenproxy/${model}`;
|
|
30261
30386
|
}
|
|
30262
|
-
|
|
30387
|
+
fs20.writeFileSync(filePath, JSON.stringify(initial, null, 2) + "\n", "utf-8");
|
|
30263
30388
|
} else {
|
|
30264
30389
|
const existingSpan = findKeyObjectSpan3(content, "qwenproxy");
|
|
30265
30390
|
if (existingSpan) {
|
|
@@ -30289,7 +30414,7 @@ ${qwenEntry}
|
|
|
30289
30414
|
content = content.replace(modelRegex, `"model": "qwenproxy/${model}"`);
|
|
30290
30415
|
}
|
|
30291
30416
|
}
|
|
30292
|
-
|
|
30417
|
+
fs20.writeFileSync(filePath, content, "utf-8");
|
|
30293
30418
|
}
|
|
30294
30419
|
return {
|
|
30295
30420
|
client: "kilo",
|
|
@@ -30328,15 +30453,15 @@ var init_kilo = __esm({
|
|
|
30328
30453
|
});
|
|
30329
30454
|
|
|
30330
30455
|
// src/sync/cline.ts
|
|
30331
|
-
import
|
|
30456
|
+
import fs21 from "node:fs";
|
|
30332
30457
|
import path16 from "node:path";
|
|
30333
30458
|
import Database2 from "better-sqlite3";
|
|
30334
30459
|
function syncCline(options) {
|
|
30335
30460
|
const { filePath, baseUrl, model = "qwen3.8-max", reasoningEffort = "high" } = options;
|
|
30336
30461
|
try {
|
|
30337
|
-
|
|
30462
|
+
fs21.mkdirSync(path16.dirname(filePath), { recursive: true });
|
|
30338
30463
|
let backupPath;
|
|
30339
|
-
if (
|
|
30464
|
+
if (fs21.existsSync(filePath)) {
|
|
30340
30465
|
backupPath = createTimestampBackup(filePath);
|
|
30341
30466
|
}
|
|
30342
30467
|
const db2 = new Database2(filePath);
|
|
@@ -30408,7 +30533,7 @@ function syncCline(options) {
|
|
|
30408
30533
|
function restoreCline(filePath, backupPath) {
|
|
30409
30534
|
const restoredFromBackup = restoreFromBackup(filePath, backupPath);
|
|
30410
30535
|
let manuallyCleaned = false;
|
|
30411
|
-
if (
|
|
30536
|
+
if (fs21.existsSync(filePath)) {
|
|
30412
30537
|
try {
|
|
30413
30538
|
const db2 = new Database2(filePath);
|
|
30414
30539
|
const rows = db2.prepare("SELECT key, value FROM ItemTable WHERE key = 'saoudrizwan.claude-dev' OR key = 'ZooCodeOrganization.zoo-code'").all();
|
|
@@ -30453,7 +30578,7 @@ var init_cline = __esm({
|
|
|
30453
30578
|
});
|
|
30454
30579
|
|
|
30455
30580
|
// src/sync/zed.ts
|
|
30456
|
-
import
|
|
30581
|
+
import fs22 from "node:fs";
|
|
30457
30582
|
import path17 from "node:path";
|
|
30458
30583
|
function parseJsonWithComments(raw) {
|
|
30459
30584
|
let result = "";
|
|
@@ -30567,13 +30692,13 @@ function buildZedAvailableModels(primaryModel = "qwen3.8-max", models) {
|
|
|
30567
30692
|
function syncZed(options) {
|
|
30568
30693
|
const { filePath, baseUrl, model = "qwen3.8-max", models, setActive = true } = options;
|
|
30569
30694
|
try {
|
|
30570
|
-
|
|
30695
|
+
fs22.mkdirSync(path17.dirname(filePath), { recursive: true });
|
|
30571
30696
|
let backupPath;
|
|
30572
30697
|
let existingSettings = {};
|
|
30573
|
-
if (
|
|
30698
|
+
if (fs22.existsSync(filePath)) {
|
|
30574
30699
|
backupPath = createTimestampBackup(filePath);
|
|
30575
30700
|
try {
|
|
30576
|
-
const content =
|
|
30701
|
+
const content = fs22.readFileSync(filePath, "utf-8");
|
|
30577
30702
|
existingSettings = parseJsonWithComments(content);
|
|
30578
30703
|
} catch {
|
|
30579
30704
|
existingSettings = {};
|
|
@@ -30603,7 +30728,7 @@ function syncZed(options) {
|
|
|
30603
30728
|
}
|
|
30604
30729
|
};
|
|
30605
30730
|
}
|
|
30606
|
-
|
|
30731
|
+
fs22.writeFileSync(filePath, JSON.stringify(updatedSettings, null, 2) + "\n", "utf-8");
|
|
30607
30732
|
return {
|
|
30608
30733
|
client: "zed",
|
|
30609
30734
|
filePath,
|
|
@@ -30625,9 +30750,9 @@ function syncZed(options) {
|
|
|
30625
30750
|
function restoreZed(filePath, backupPath) {
|
|
30626
30751
|
const restoredFromBackup = restoreFromBackup(filePath, backupPath);
|
|
30627
30752
|
let manuallyCleaned = false;
|
|
30628
|
-
if (
|
|
30753
|
+
if (fs22.existsSync(filePath)) {
|
|
30629
30754
|
try {
|
|
30630
|
-
let content =
|
|
30755
|
+
let content = fs22.readFileSync(filePath, "utf-8");
|
|
30631
30756
|
if (content.includes("127.0.0.1:7936") || content.includes("qwen3.8-max")) {
|
|
30632
30757
|
const data = parseJsonWithComments(content);
|
|
30633
30758
|
if (data.language_models?.openai?.api_url?.includes("7936")) {
|
|
@@ -30635,7 +30760,7 @@ function restoreZed(filePath, backupPath) {
|
|
|
30635
30760
|
if (Object.keys(data.language_models).length === 0) {
|
|
30636
30761
|
delete data.language_models;
|
|
30637
30762
|
}
|
|
30638
|
-
|
|
30763
|
+
fs22.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
30639
30764
|
manuallyCleaned = true;
|
|
30640
30765
|
}
|
|
30641
30766
|
}
|
|
@@ -30660,7 +30785,7 @@ var init_zed = __esm({
|
|
|
30660
30785
|
});
|
|
30661
30786
|
|
|
30662
30787
|
// src/sync/aider.ts
|
|
30663
|
-
import
|
|
30788
|
+
import fs23 from "node:fs";
|
|
30664
30789
|
import path18 from "node:path";
|
|
30665
30790
|
function updateYamlKeyValue(content, key, value) {
|
|
30666
30791
|
const regex = new RegExp(`^${key}:.*$`, "m");
|
|
@@ -30680,12 +30805,12 @@ function syncAider(options) {
|
|
|
30680
30805
|
modelSettingsPath
|
|
30681
30806
|
} = options;
|
|
30682
30807
|
try {
|
|
30683
|
-
|
|
30808
|
+
fs23.mkdirSync(path18.dirname(filePath), { recursive: true });
|
|
30684
30809
|
let backupPath;
|
|
30685
30810
|
let confContent = "";
|
|
30686
|
-
if (
|
|
30811
|
+
if (fs23.existsSync(filePath)) {
|
|
30687
30812
|
backupPath = createTimestampBackup(filePath);
|
|
30688
|
-
confContent =
|
|
30813
|
+
confContent = fs23.readFileSync(filePath, "utf-8");
|
|
30689
30814
|
}
|
|
30690
30815
|
const fullModelName = model.startsWith("openai/") ? model : `openai/${model}`;
|
|
30691
30816
|
const weakModelName = "openai/qwen3.7-plus";
|
|
@@ -30694,15 +30819,15 @@ function syncAider(options) {
|
|
|
30694
30819
|
confContent = updateYamlKeyValue(confContent, "model", fullModelName);
|
|
30695
30820
|
confContent = updateYamlKeyValue(confContent, "editor-model", fullModelName);
|
|
30696
30821
|
confContent = updateYamlKeyValue(confContent, "weak-model", weakModelName);
|
|
30697
|
-
|
|
30822
|
+
fs23.writeFileSync(filePath, confContent.trimEnd() + "\n", "utf-8");
|
|
30698
30823
|
let extraBackupPath;
|
|
30699
30824
|
const resolvedSettingsPath = modelSettingsPath || path18.join(path18.dirname(filePath), ".aider.model.settings.yml");
|
|
30700
30825
|
if (resolvedSettingsPath) {
|
|
30701
|
-
|
|
30826
|
+
fs23.mkdirSync(path18.dirname(resolvedSettingsPath), { recursive: true });
|
|
30702
30827
|
let settingsContent = "";
|
|
30703
|
-
if (
|
|
30828
|
+
if (fs23.existsSync(resolvedSettingsPath)) {
|
|
30704
30829
|
extraBackupPath = createTimestampBackup(resolvedSettingsPath);
|
|
30705
|
-
settingsContent =
|
|
30830
|
+
settingsContent = fs23.readFileSync(resolvedSettingsPath, "utf-8");
|
|
30706
30831
|
}
|
|
30707
30832
|
const modelBlock = `- name: ${fullModelName}
|
|
30708
30833
|
extra_params:
|
|
@@ -30716,7 +30841,7 @@ function syncAider(options) {
|
|
|
30716
30841
|
} else {
|
|
30717
30842
|
settingsContent = settingsContent.trimEnd() + (settingsContent.length > 0 ? "\n\n" : "") + modelBlock;
|
|
30718
30843
|
}
|
|
30719
|
-
|
|
30844
|
+
fs23.writeFileSync(resolvedSettingsPath, settingsContent.trimEnd() + "\n", "utf-8");
|
|
30720
30845
|
}
|
|
30721
30846
|
return {
|
|
30722
30847
|
client: "aider",
|
|
@@ -30761,7 +30886,7 @@ var init_aider = __esm({
|
|
|
30761
30886
|
|
|
30762
30887
|
// src/sync/index.ts
|
|
30763
30888
|
import "dotenv/config";
|
|
30764
|
-
import
|
|
30889
|
+
import fs24 from "node:fs";
|
|
30765
30890
|
import path19 from "node:path";
|
|
30766
30891
|
import os5 from "node:os";
|
|
30767
30892
|
import Database3 from "better-sqlite3";
|
|
@@ -30801,14 +30926,14 @@ function getDefaultPaths() {
|
|
|
30801
30926
|
path19.join(home, ".opencode", "opencode.jsonc"),
|
|
30802
30927
|
path19.join(home, ".opencode", "opencode.json")
|
|
30803
30928
|
];
|
|
30804
|
-
const existingOpenCode = openCodeCandidates.find((p) =>
|
|
30929
|
+
const existingOpenCode = openCodeCandidates.find((p) => fs24.existsSync(p));
|
|
30805
30930
|
const kiloCandidates = [
|
|
30806
30931
|
path19.join(home, ".config", "kilo", "kilo.json"),
|
|
30807
30932
|
path19.join(home, ".kilo", "kilo.json"),
|
|
30808
30933
|
path19.join(home, ".config", "kilo", "config.json"),
|
|
30809
30934
|
path19.join(home, ".kilo", "config.json")
|
|
30810
30935
|
];
|
|
30811
|
-
const existingKilo = kiloCandidates.find((p) =>
|
|
30936
|
+
const existingKilo = kiloCandidates.find((p) => fs24.existsSync(p));
|
|
30812
30937
|
let clinePath;
|
|
30813
30938
|
if (isWindows) {
|
|
30814
30939
|
clinePath = path19.join(appData, "Code", "User", "globalStorage", "state.vscdb");
|
|
@@ -30825,7 +30950,7 @@ function getDefaultPaths() {
|
|
|
30825
30950
|
}
|
|
30826
30951
|
return {
|
|
30827
30952
|
claudeCode: path19.join(home, ".claude", "settings.json"),
|
|
30828
|
-
codex:
|
|
30953
|
+
codex: fs24.existsSync(path19.join(home, ".codex", "config.toml")) ? path19.join(home, ".codex", "config.toml") : process.env.CODEX_HOME ? path19.join(process.env.CODEX_HOME, "config.toml") : path19.join(home, ".codex", "config.toml"),
|
|
30829
30954
|
openCode: existingOpenCode || openCodeCandidates[0],
|
|
30830
30955
|
omp: path19.join(home, ".omp", "agent", "models.yml"),
|
|
30831
30956
|
hermes: path19.join(home, ".hermes", "config.yaml"),
|
|
@@ -30847,7 +30972,7 @@ function isExecutableInPath(name) {
|
|
|
30847
30972
|
for (const ext of extensions) {
|
|
30848
30973
|
const fullPath = path19.join(dir, name + ext);
|
|
30849
30974
|
try {
|
|
30850
|
-
if (
|
|
30975
|
+
if (fs24.existsSync(fullPath) && !fs24.statSync(fullPath).isDirectory()) {
|
|
30851
30976
|
return true;
|
|
30852
30977
|
}
|
|
30853
30978
|
} catch {
|
|
@@ -30865,9 +30990,9 @@ function isVscodeExtensionInstalled(pattern) {
|
|
|
30865
30990
|
path19.join(home, ".windsurf", "extensions")
|
|
30866
30991
|
];
|
|
30867
30992
|
for (const d of candidateDirs) {
|
|
30868
|
-
if (
|
|
30993
|
+
if (fs24.existsSync(d)) {
|
|
30869
30994
|
try {
|
|
30870
|
-
const entries =
|
|
30995
|
+
const entries = fs24.readdirSync(d);
|
|
30871
30996
|
if (entries.some((e) => pattern.test(e))) return true;
|
|
30872
30997
|
} catch {
|
|
30873
30998
|
}
|
|
@@ -30879,9 +31004,9 @@ function isZedInstalled() {
|
|
|
30879
31004
|
if (isExecutableInPath("zed")) return true;
|
|
30880
31005
|
if (process.platform === "win32") {
|
|
30881
31006
|
const local = process.env.LOCALAPPDATA || "";
|
|
30882
|
-
if (
|
|
31007
|
+
if (fs24.existsSync(path19.join(local, "Programs", "Zed"))) return true;
|
|
30883
31008
|
} else if (process.platform === "darwin") {
|
|
30884
|
-
if (
|
|
31009
|
+
if (fs24.existsSync("/Applications/Zed.app")) return true;
|
|
30885
31010
|
}
|
|
30886
31011
|
return false;
|
|
30887
31012
|
}
|
|
@@ -30894,7 +31019,7 @@ function isMatchingLocalHost(text, port = 7936) {
|
|
|
30894
31019
|
}
|
|
30895
31020
|
function isClientToolInstalled(id, targetPath, isCustomTestPath = false) {
|
|
30896
31021
|
if (isCustomTestPath) {
|
|
30897
|
-
return
|
|
31022
|
+
return fs24.existsSync(targetPath);
|
|
30898
31023
|
}
|
|
30899
31024
|
switch (id) {
|
|
30900
31025
|
case "hermes":
|
|
@@ -30910,15 +31035,15 @@ function isClientToolInstalled(id, targetPath, isCustomTestPath = false) {
|
|
|
30910
31035
|
case "zed":
|
|
30911
31036
|
return isZedInstalled();
|
|
30912
31037
|
case "claude-code":
|
|
30913
|
-
return isExecutableInPath("claude") ||
|
|
31038
|
+
return isExecutableInPath("claude") || fs24.existsSync(targetPath);
|
|
30914
31039
|
case "codex":
|
|
30915
|
-
return isExecutableInPath("codex") ||
|
|
31040
|
+
return isExecutableInPath("codex") || fs24.existsSync(targetPath);
|
|
30916
31041
|
case "opencode":
|
|
30917
|
-
return isExecutableInPath("opencode") ||
|
|
31042
|
+
return isExecutableInPath("opencode") || fs24.existsSync(targetPath);
|
|
30918
31043
|
case "omp":
|
|
30919
|
-
return isExecutableInPath("omp") ||
|
|
31044
|
+
return isExecutableInPath("omp") || fs24.existsSync(targetPath);
|
|
30920
31045
|
default:
|
|
30921
|
-
return
|
|
31046
|
+
return fs24.existsSync(targetPath);
|
|
30922
31047
|
}
|
|
30923
31048
|
}
|
|
30924
31049
|
function inspectClientSyncStatus(id, filePath, port = 7936) {
|
|
@@ -30928,7 +31053,7 @@ function inspectClientSyncStatus(id, filePath, port = 7936) {
|
|
|
30928
31053
|
filePath && defaultTarget && path19.resolve(filePath) !== path19.resolve(defaultTarget)
|
|
30929
31054
|
);
|
|
30930
31055
|
const targetPath = filePath || defaultTarget;
|
|
30931
|
-
if (!
|
|
31056
|
+
if (!fs24.existsSync(targetPath)) {
|
|
30932
31057
|
return { id, installed: false, synced: false };
|
|
30933
31058
|
}
|
|
30934
31059
|
const toolInstalled = isClientToolInstalled(id, targetPath, isCustomTestPath);
|
|
@@ -30958,7 +31083,7 @@ function inspectClientSyncStatus(id, filePath, port = 7936) {
|
|
|
30958
31083
|
const isInstalled = isCustomTestPath ? true : rowExists || isExecutableInPath("cline") || isVscodeExtensionInstalled(/cline|zoo-code|roo-cline/i);
|
|
30959
31084
|
return { id, installed: isInstalled, synced: isInstalled && isSynced, model };
|
|
30960
31085
|
}
|
|
30961
|
-
const raw =
|
|
31086
|
+
const raw = fs24.readFileSync(targetPath, "utf-8");
|
|
30962
31087
|
if (id === "claude-code") {
|
|
30963
31088
|
const data = JSON.parse(raw);
|
|
30964
31089
|
const url = data?.env?.ANTHROPIC_BASE_URL || "";
|
|
@@ -31084,7 +31209,7 @@ function syncAllClients(options = {}) {
|
|
|
31084
31209
|
return options.targets.includes(client);
|
|
31085
31210
|
};
|
|
31086
31211
|
if (shouldSync("claude-code")) {
|
|
31087
|
-
const claudeExisted =
|
|
31212
|
+
const claudeExisted = fs24.existsSync(paths.claudeCode);
|
|
31088
31213
|
const claudeRes = syncClaudeCode({
|
|
31089
31214
|
filePath: paths.claudeCode,
|
|
31090
31215
|
apiKey,
|
|
@@ -31102,7 +31227,7 @@ function syncAllClients(options = {}) {
|
|
|
31102
31227
|
}
|
|
31103
31228
|
}
|
|
31104
31229
|
if (shouldSync("codex")) {
|
|
31105
|
-
const codexExisted =
|
|
31230
|
+
const codexExisted = fs24.existsSync(paths.codex);
|
|
31106
31231
|
const codexRes = syncCodex({
|
|
31107
31232
|
filePath: paths.codex,
|
|
31108
31233
|
apiKey,
|
|
@@ -31121,7 +31246,7 @@ function syncAllClients(options = {}) {
|
|
|
31121
31246
|
}
|
|
31122
31247
|
}
|
|
31123
31248
|
if (shouldSync("opencode")) {
|
|
31124
|
-
const openCodeExisted =
|
|
31249
|
+
const openCodeExisted = fs24.existsSync(paths.openCode);
|
|
31125
31250
|
const openCodeRes = syncOpenCode({
|
|
31126
31251
|
filePath: paths.openCode,
|
|
31127
31252
|
apiKey,
|
|
@@ -31141,7 +31266,7 @@ function syncAllClients(options = {}) {
|
|
|
31141
31266
|
}
|
|
31142
31267
|
}
|
|
31143
31268
|
if (shouldSync("omp")) {
|
|
31144
|
-
const ompExisted =
|
|
31269
|
+
const ompExisted = fs24.existsSync(paths.omp);
|
|
31145
31270
|
const ompRes = syncOmp({
|
|
31146
31271
|
filePath: paths.omp,
|
|
31147
31272
|
apiKey,
|
|
@@ -31160,7 +31285,7 @@ function syncAllClients(options = {}) {
|
|
|
31160
31285
|
}
|
|
31161
31286
|
}
|
|
31162
31287
|
if (shouldSync("hermes")) {
|
|
31163
|
-
const hermesExisted =
|
|
31288
|
+
const hermesExisted = fs24.existsSync(paths.hermes);
|
|
31164
31289
|
const hermesRes = syncHermes({
|
|
31165
31290
|
filePath: paths.hermes,
|
|
31166
31291
|
apiKey,
|
|
@@ -31178,7 +31303,7 @@ function syncAllClients(options = {}) {
|
|
|
31178
31303
|
}
|
|
31179
31304
|
}
|
|
31180
31305
|
if (shouldSync("openclaw")) {
|
|
31181
|
-
const openClawExisted =
|
|
31306
|
+
const openClawExisted = fs24.existsSync(paths.openClaw);
|
|
31182
31307
|
const openClawRes = syncOpenClaw({
|
|
31183
31308
|
filePath: paths.openClaw,
|
|
31184
31309
|
apiKey,
|
|
@@ -31197,7 +31322,7 @@ function syncAllClients(options = {}) {
|
|
|
31197
31322
|
}
|
|
31198
31323
|
}
|
|
31199
31324
|
if (shouldSync("kilo")) {
|
|
31200
|
-
const kiloExisted =
|
|
31325
|
+
const kiloExisted = fs24.existsSync(paths.kilo);
|
|
31201
31326
|
const kiloRes = syncKilo({
|
|
31202
31327
|
filePath: paths.kilo,
|
|
31203
31328
|
apiKey,
|
|
@@ -31217,7 +31342,7 @@ function syncAllClients(options = {}) {
|
|
|
31217
31342
|
}
|
|
31218
31343
|
}
|
|
31219
31344
|
if (shouldSync("cline")) {
|
|
31220
|
-
const clineExisted =
|
|
31345
|
+
const clineExisted = fs24.existsSync(paths.cline);
|
|
31221
31346
|
const clineRes = syncCline({
|
|
31222
31347
|
filePath: paths.cline,
|
|
31223
31348
|
apiKey,
|
|
@@ -31235,7 +31360,7 @@ function syncAllClients(options = {}) {
|
|
|
31235
31360
|
}
|
|
31236
31361
|
}
|
|
31237
31362
|
if (shouldSync("zed")) {
|
|
31238
|
-
const zedExisted =
|
|
31363
|
+
const zedExisted = fs24.existsSync(paths.zed);
|
|
31239
31364
|
const zedRes = syncZed({
|
|
31240
31365
|
filePath: paths.zed,
|
|
31241
31366
|
apiKey,
|
|
@@ -31255,7 +31380,7 @@ function syncAllClients(options = {}) {
|
|
|
31255
31380
|
}
|
|
31256
31381
|
}
|
|
31257
31382
|
if (shouldSync("aider")) {
|
|
31258
|
-
const aiderExisted =
|
|
31383
|
+
const aiderExisted = fs24.existsSync(paths.aider);
|
|
31259
31384
|
const aiderRes = syncAider({
|
|
31260
31385
|
filePath: paths.aider,
|
|
31261
31386
|
apiKey,
|
|
@@ -31273,11 +31398,11 @@ function syncAllClients(options = {}) {
|
|
|
31273
31398
|
}
|
|
31274
31399
|
}
|
|
31275
31400
|
try {
|
|
31276
|
-
|
|
31401
|
+
fs24.mkdirSync(path19.dirname(stateFilePath), { recursive: true });
|
|
31277
31402
|
let existingClients = {};
|
|
31278
|
-
if (
|
|
31403
|
+
if (fs24.existsSync(stateFilePath)) {
|
|
31279
31404
|
try {
|
|
31280
|
-
const raw =
|
|
31405
|
+
const raw = fs24.readFileSync(stateFilePath, "utf-8");
|
|
31281
31406
|
const parsed = JSON.parse(raw);
|
|
31282
31407
|
if (parsed?.clients && typeof parsed.clients === "object") {
|
|
31283
31408
|
existingClients = parsed.clients;
|
|
@@ -31296,7 +31421,7 @@ function syncAllClients(options = {}) {
|
|
|
31296
31421
|
...stateRecords
|
|
31297
31422
|
}
|
|
31298
31423
|
};
|
|
31299
|
-
|
|
31424
|
+
fs24.writeFileSync(stateFilePath, JSON.stringify(stateContent, null, 2) + "\n", "utf-8");
|
|
31300
31425
|
} catch (err) {
|
|
31301
31426
|
console.error("Warning: could not write sync state file:", err);
|
|
31302
31427
|
}
|
|
@@ -31308,9 +31433,9 @@ function restoreAllClients(options = {}) {
|
|
|
31308
31433
|
const details = [];
|
|
31309
31434
|
let restoredCount = 0;
|
|
31310
31435
|
let state = null;
|
|
31311
|
-
if (
|
|
31436
|
+
if (fs24.existsSync(stateFilePath)) {
|
|
31312
31437
|
try {
|
|
31313
|
-
const raw =
|
|
31438
|
+
const raw = fs24.readFileSync(stateFilePath, "utf-8");
|
|
31314
31439
|
state = JSON.parse(raw);
|
|
31315
31440
|
} catch {
|
|
31316
31441
|
}
|
|
@@ -31335,7 +31460,7 @@ function restoreAllClients(options = {}) {
|
|
|
31335
31460
|
if (!shouldRestore(c.id)) continue;
|
|
31336
31461
|
const filePath = c.stateRecord?.filePath || c.defaultPath;
|
|
31337
31462
|
const backupPath = c.stateRecord?.backupPath;
|
|
31338
|
-
const canAttempt = options.stateFilePath ? Boolean(c.stateRecord) : Boolean(c.stateRecord ||
|
|
31463
|
+
const canAttempt = options.stateFilePath ? Boolean(c.stateRecord) : Boolean(c.stateRecord || fs24.existsSync(filePath));
|
|
31339
31464
|
if (canAttempt) {
|
|
31340
31465
|
const res = c.restoreFn(filePath, backupPath);
|
|
31341
31466
|
details.push(res);
|
|
@@ -31348,12 +31473,12 @@ function restoreAllClients(options = {}) {
|
|
|
31348
31473
|
}
|
|
31349
31474
|
}
|
|
31350
31475
|
}
|
|
31351
|
-
if (stateFilePath &&
|
|
31476
|
+
if (stateFilePath && fs24.existsSync(stateFilePath)) {
|
|
31352
31477
|
try {
|
|
31353
31478
|
if (state && state.clients && Object.keys(state.clients).length > 0) {
|
|
31354
|
-
|
|
31479
|
+
fs24.writeFileSync(stateFilePath, JSON.stringify(state, null, 2) + "\n", "utf-8");
|
|
31355
31480
|
} else {
|
|
31356
|
-
|
|
31481
|
+
fs24.unlinkSync(stateFilePath);
|
|
31357
31482
|
}
|
|
31358
31483
|
} catch {
|
|
31359
31484
|
}
|
|
@@ -31790,7 +31915,7 @@ var init_sync_view = __esm({
|
|
|
31790
31915
|
});
|
|
31791
31916
|
|
|
31792
31917
|
// src/tui/views/storage-view.ts
|
|
31793
|
-
import
|
|
31918
|
+
import fs25 from "node:fs";
|
|
31794
31919
|
import path20 from "node:path";
|
|
31795
31920
|
var StorageView;
|
|
31796
31921
|
var init_storage_view = __esm({
|
|
@@ -31856,8 +31981,8 @@ var init_storage_view = __esm({
|
|
|
31856
31981
|
let totalBytes = 0;
|
|
31857
31982
|
let count = 0;
|
|
31858
31983
|
this.profileStats = [];
|
|
31859
|
-
if (
|
|
31860
|
-
const entries =
|
|
31984
|
+
if (fs25.existsSync(profilesDir)) {
|
|
31985
|
+
const entries = fs25.readdirSync(profilesDir, { withFileTypes: true });
|
|
31861
31986
|
for (const entry of entries) {
|
|
31862
31987
|
if (entry.isDirectory()) {
|
|
31863
31988
|
count++;
|
|
@@ -33892,8 +34017,8 @@ var init_app = __esm({
|
|
|
33892
34017
|
// src/index.ts
|
|
33893
34018
|
init_paths();
|
|
33894
34019
|
init_server();
|
|
33895
|
-
import
|
|
33896
|
-
import
|
|
34020
|
+
import dotenv2 from "dotenv";
|
|
34021
|
+
import fs26 from "node:fs";
|
|
33897
34022
|
try {
|
|
33898
34023
|
process.title = "QwenProxy";
|
|
33899
34024
|
} catch {
|
|
@@ -33901,10 +34026,10 @@ try {
|
|
|
33901
34026
|
process.env.DOTENV_CONFIG_QUIET = "true";
|
|
33902
34027
|
ensureDataDirs();
|
|
33903
34028
|
var envPath = getEnvFilePath();
|
|
33904
|
-
if (
|
|
33905
|
-
|
|
34029
|
+
if (fs26.existsSync(envPath)) {
|
|
34030
|
+
dotenv2.config({ path: envPath, quiet: true });
|
|
33906
34031
|
} else {
|
|
33907
|
-
|
|
34032
|
+
dotenv2.config({ quiet: true });
|
|
33908
34033
|
}
|
|
33909
34034
|
process.on("uncaughtException", async (error) => {
|
|
33910
34035
|
const { isPlaywrightAlreadyClosedError: isPlaywrightAlreadyClosedError2 } = await Promise.resolve().then(() => (init_playwright(), playwright_exports));
|