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/sync-clients.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/sync-clients.ts
|
|
2
|
-
import
|
|
3
|
-
import
|
|
2
|
+
import fs15 from "node:fs";
|
|
3
|
+
import dotenv2 from "dotenv";
|
|
4
4
|
|
|
5
5
|
// src/core/paths.ts
|
|
6
6
|
import fs from "node:fs";
|
|
@@ -88,13 +88,23 @@ function ensureDataDirs(targetDataDir) {
|
|
|
88
88
|
|
|
89
89
|
// src/sync/index.ts
|
|
90
90
|
import "dotenv/config";
|
|
91
|
-
import
|
|
91
|
+
import fs14 from "node:fs";
|
|
92
92
|
import path13 from "node:path";
|
|
93
93
|
import os3 from "node:os";
|
|
94
94
|
import Database2 from "better-sqlite3";
|
|
95
95
|
|
|
96
96
|
// src/core/config.ts
|
|
97
|
+
import fs2 from "node:fs";
|
|
98
|
+
import dotenv from "dotenv";
|
|
97
99
|
import { z } from "zod";
|
|
100
|
+
if (!isRunningUnderNodeTest()) {
|
|
101
|
+
const envPath2 = getEnvFilePath();
|
|
102
|
+
if (fs2.existsSync(envPath2)) {
|
|
103
|
+
dotenv.config({ path: envPath2, quiet: true });
|
|
104
|
+
} else {
|
|
105
|
+
dotenv.config({ quiet: true });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
98
108
|
var envSchema = z.object({
|
|
99
109
|
PORT: z.string().regex(/^\d+$/, "PORT must be a number").refine((value) => {
|
|
100
110
|
const port = Number(value);
|
|
@@ -484,11 +494,11 @@ function isLoopbackHost(host) {
|
|
|
484
494
|
}
|
|
485
495
|
|
|
486
496
|
// src/sync/claude-code.ts
|
|
487
|
-
import
|
|
497
|
+
import fs4 from "node:fs";
|
|
488
498
|
import path3 from "node:path";
|
|
489
499
|
|
|
490
500
|
// src/sync/utils.ts
|
|
491
|
-
import
|
|
501
|
+
import fs3 from "node:fs";
|
|
492
502
|
import path2 from "node:path";
|
|
493
503
|
function createTimestampBackup(filePath) {
|
|
494
504
|
const dir = path2.dirname(filePath);
|
|
@@ -498,19 +508,19 @@ function createTimestampBackup(filePath) {
|
|
|
498
508
|
const pad = (n) => String(n).padStart(2, "0");
|
|
499
509
|
const timestamp = `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}_${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
|
|
500
510
|
const backupPath = path2.join(dir, `${base}.qwenproxy.${timestamp}${ext}.bak`);
|
|
501
|
-
|
|
511
|
+
fs3.copyFileSync(filePath, backupPath);
|
|
502
512
|
return backupPath;
|
|
503
513
|
}
|
|
504
514
|
function findLatestBackup(filePath) {
|
|
505
515
|
const dir = path2.dirname(filePath);
|
|
506
516
|
const ext = path2.extname(filePath);
|
|
507
517
|
const base = path2.basename(filePath, ext);
|
|
508
|
-
if (!
|
|
518
|
+
if (!fs3.existsSync(dir)) return void 0;
|
|
509
519
|
try {
|
|
510
|
-
const files =
|
|
520
|
+
const files = fs3.readdirSync(dir);
|
|
511
521
|
const candidates = files.filter((f) => f.startsWith(base) && f.includes("qwenproxy") && f.endsWith(".bak")).map((f) => path2.join(dir, f)).sort((a, b) => {
|
|
512
522
|
try {
|
|
513
|
-
return
|
|
523
|
+
return fs3.statSync(b).mtimeMs - fs3.statSync(a).mtimeMs;
|
|
514
524
|
} catch {
|
|
515
525
|
return 0;
|
|
516
526
|
}
|
|
@@ -521,13 +531,13 @@ function findLatestBackup(filePath) {
|
|
|
521
531
|
}
|
|
522
532
|
}
|
|
523
533
|
function restoreFromBackup(filePath, backupPath) {
|
|
524
|
-
const targetBackup = backupPath &&
|
|
525
|
-
if (!targetBackup || !
|
|
534
|
+
const targetBackup = backupPath && fs3.existsSync(backupPath) ? backupPath : findLatestBackup(filePath);
|
|
535
|
+
if (!targetBackup || !fs3.existsSync(targetBackup)) {
|
|
526
536
|
return false;
|
|
527
537
|
}
|
|
528
|
-
|
|
538
|
+
fs3.copyFileSync(targetBackup, filePath);
|
|
529
539
|
try {
|
|
530
|
-
|
|
540
|
+
fs3.unlinkSync(targetBackup);
|
|
531
541
|
} catch {
|
|
532
542
|
}
|
|
533
543
|
return true;
|
|
@@ -544,13 +554,13 @@ function formatModelDisplayName(model) {
|
|
|
544
554
|
function syncClaudeCode(options) {
|
|
545
555
|
const { filePath, apiKey, baseUrl, model = "qwen3.8-max" } = options;
|
|
546
556
|
try {
|
|
547
|
-
|
|
557
|
+
fs4.mkdirSync(path3.dirname(filePath), { recursive: true });
|
|
548
558
|
let backupPath;
|
|
549
559
|
let existingSettings = {};
|
|
550
|
-
if (
|
|
560
|
+
if (fs4.existsSync(filePath)) {
|
|
551
561
|
backupPath = createTimestampBackup(filePath);
|
|
552
562
|
try {
|
|
553
|
-
const content =
|
|
563
|
+
const content = fs4.readFileSync(filePath, "utf-8");
|
|
554
564
|
existingSettings = JSON.parse(content);
|
|
555
565
|
} catch {
|
|
556
566
|
existingSettings = {};
|
|
@@ -576,7 +586,7 @@ function syncClaudeCode(options) {
|
|
|
576
586
|
model,
|
|
577
587
|
enableArtifact: false
|
|
578
588
|
};
|
|
579
|
-
|
|
589
|
+
fs4.writeFileSync(filePath, JSON.stringify(updatedSettings, null, 2) + "\n", "utf-8");
|
|
580
590
|
return {
|
|
581
591
|
client: "claude-code",
|
|
582
592
|
filePath,
|
|
@@ -598,9 +608,9 @@ function syncClaudeCode(options) {
|
|
|
598
608
|
function restoreClaudeCode(filePath, backupPath) {
|
|
599
609
|
const restoredFromBackup = restoreFromBackup(filePath, backupPath);
|
|
600
610
|
let manuallyCleaned = false;
|
|
601
|
-
if (
|
|
611
|
+
if (fs4.existsSync(filePath)) {
|
|
602
612
|
try {
|
|
603
|
-
const data = JSON.parse(
|
|
613
|
+
const data = JSON.parse(fs4.readFileSync(filePath, "utf-8"));
|
|
604
614
|
if (data.env && (data.env.ANTHROPIC_BASE_URL?.includes("7936") || data.env.ANTHROPIC_AUTH_TOKEN === "sk-qwenproxy-local" || data.env.ANTHROPIC_MODEL?.includes("qwen"))) {
|
|
605
615
|
delete data.env.ANTHROPIC_BASE_URL;
|
|
606
616
|
delete data.env.ANTHROPIC_AUTH_TOKEN;
|
|
@@ -620,7 +630,7 @@ function restoreClaudeCode(filePath, backupPath) {
|
|
|
620
630
|
if (Object.keys(data.env).length === 0) {
|
|
621
631
|
delete data.env;
|
|
622
632
|
}
|
|
623
|
-
|
|
633
|
+
fs4.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
624
634
|
manuallyCleaned = true;
|
|
625
635
|
}
|
|
626
636
|
} catch {
|
|
@@ -638,7 +648,7 @@ function restoreClaudeCode(filePath, backupPath) {
|
|
|
638
648
|
}
|
|
639
649
|
|
|
640
650
|
// src/sync/codex.ts
|
|
641
|
-
import
|
|
651
|
+
import fs5 from "node:fs";
|
|
642
652
|
import path4 from "node:path";
|
|
643
653
|
import os2 from "node:os";
|
|
644
654
|
function removeTomlSection(content, sectionHeader) {
|
|
@@ -679,12 +689,12 @@ function updateTopLevelKey(content, key, value) {
|
|
|
679
689
|
return newTopPart + restPart;
|
|
680
690
|
}
|
|
681
691
|
function syncCodexSingleFile(targetPath, options) {
|
|
682
|
-
|
|
692
|
+
fs5.mkdirSync(path4.dirname(targetPath), { recursive: true });
|
|
683
693
|
let backupPath;
|
|
684
694
|
let content = "";
|
|
685
|
-
if (
|
|
695
|
+
if (fs5.existsSync(targetPath)) {
|
|
686
696
|
backupPath = createTimestampBackup(targetPath);
|
|
687
|
-
content =
|
|
697
|
+
content = fs5.readFileSync(targetPath, "utf-8");
|
|
688
698
|
}
|
|
689
699
|
const { apiKey, baseUrl, model = "qwen3.8-max", setActive = true } = options;
|
|
690
700
|
const providerBlock = `[model_providers.qwenproxy]
|
|
@@ -705,8 +715,8 @@ experimental_bearer_token = "${apiKey}"
|
|
|
705
715
|
try {
|
|
706
716
|
const rawCatalogPath = catalogMatch[1];
|
|
707
717
|
const catalogPath = path4.isAbsolute(rawCatalogPath) ? rawCatalogPath : path4.resolve(path4.dirname(targetPath), rawCatalogPath);
|
|
708
|
-
if (
|
|
709
|
-
const catalog = JSON.parse(
|
|
718
|
+
if (fs5.existsSync(catalogPath)) {
|
|
719
|
+
const catalog = JSON.parse(fs5.readFileSync(catalogPath, "utf-8"));
|
|
710
720
|
if (Array.isArray(catalog.models)) {
|
|
711
721
|
const hasModel = catalog.models.some((m) => m?.slug === model);
|
|
712
722
|
if (!hasModel) {
|
|
@@ -719,14 +729,14 @@ experimental_bearer_token = "${apiKey}"
|
|
|
719
729
|
context_window: 1e6,
|
|
720
730
|
max_context_window: 1e6
|
|
721
731
|
});
|
|
722
|
-
|
|
732
|
+
fs5.writeFileSync(catalogPath, JSON.stringify(catalog, null, 2), "utf-8");
|
|
723
733
|
}
|
|
724
734
|
}
|
|
725
735
|
}
|
|
726
736
|
} catch {
|
|
727
737
|
}
|
|
728
738
|
}
|
|
729
|
-
|
|
739
|
+
fs5.writeFileSync(targetPath, content.trimEnd() + "\n", "utf-8");
|
|
730
740
|
return { backupPath };
|
|
731
741
|
}
|
|
732
742
|
function syncCodex(options) {
|
|
@@ -742,7 +752,7 @@ function syncCodex(options) {
|
|
|
742
752
|
const alternatePath = isStandard ? codexHomePath : standardPath;
|
|
743
753
|
if (alternatePath && path4.resolve(alternatePath).toLowerCase() !== path4.resolve(filePath).toLowerCase()) {
|
|
744
754
|
try {
|
|
745
|
-
if (
|
|
755
|
+
if (fs5.existsSync(alternatePath) || fs5.existsSync(path4.dirname(alternatePath))) {
|
|
746
756
|
syncCodexSingleFile(alternatePath, options);
|
|
747
757
|
}
|
|
748
758
|
} catch {
|
|
@@ -771,16 +781,16 @@ function restoreCodex(filePath, backupPath) {
|
|
|
771
781
|
const restoredFromBackup = restoreFromBackup(filePath, backupPath);
|
|
772
782
|
let manuallyCleaned = false;
|
|
773
783
|
const cleanSingleFile = (p) => {
|
|
774
|
-
if (
|
|
784
|
+
if (fs5.existsSync(p)) {
|
|
775
785
|
try {
|
|
776
|
-
let content =
|
|
786
|
+
let content = fs5.readFileSync(p, "utf-8");
|
|
777
787
|
if (content.includes("[model_providers.qwenproxy]") || /^model_provider\s*=\s*["']qwenproxy["']/m.test(content)) {
|
|
778
788
|
content = removeTomlSection(content, "model_providers.qwenproxy");
|
|
779
789
|
content = content.replace(/^model_provider\s*=\s*["']qwenproxy["']\r?\n?/m, "");
|
|
780
790
|
if (/^model\s*=\s*["']qwen/m.test(content)) {
|
|
781
791
|
content = content.replace(/^model\s*=\s*["']qwen[^"']*["']\r?\n?/m, "");
|
|
782
792
|
}
|
|
783
|
-
|
|
793
|
+
fs5.writeFileSync(p, content.trimEnd() + "\n", "utf-8");
|
|
784
794
|
manuallyCleaned = true;
|
|
785
795
|
}
|
|
786
796
|
} catch {
|
|
@@ -811,7 +821,7 @@ function restoreCodex(filePath, backupPath) {
|
|
|
811
821
|
}
|
|
812
822
|
|
|
813
823
|
// src/sync/opencode.ts
|
|
814
|
-
import
|
|
824
|
+
import fs6 from "node:fs";
|
|
815
825
|
import path5 from "node:path";
|
|
816
826
|
function buildOpenCodeProviderObject(baseUrl, apiKey, primaryModel = "qwen3.8-max", models) {
|
|
817
827
|
const modelsObj = {};
|
|
@@ -937,12 +947,12 @@ function syncOpenCode(options) {
|
|
|
937
947
|
setActive = true
|
|
938
948
|
} = options;
|
|
939
949
|
try {
|
|
940
|
-
|
|
950
|
+
fs6.mkdirSync(path5.dirname(filePath), { recursive: true });
|
|
941
951
|
let backupPath;
|
|
942
952
|
let content = "";
|
|
943
|
-
if (
|
|
953
|
+
if (fs6.existsSync(filePath)) {
|
|
944
954
|
backupPath = createTimestampBackup(filePath);
|
|
945
|
-
content =
|
|
955
|
+
content = fs6.readFileSync(filePath, "utf-8");
|
|
946
956
|
}
|
|
947
957
|
const providerObj = buildOpenCodeProviderObject(baseUrl, apiKey, model, models);
|
|
948
958
|
const providerJson = JSON.stringify(providerObj, null, 6).split("\n").map((line, idx) => idx === 0 ? line : ` ${line}`).join("\n");
|
|
@@ -957,7 +967,7 @@ function syncOpenCode(options) {
|
|
|
957
967
|
initial.provider = {
|
|
958
968
|
qwenproxy: providerObj
|
|
959
969
|
};
|
|
960
|
-
|
|
970
|
+
fs6.writeFileSync(filePath, JSON.stringify(initial, null, 2) + "\n", "utf-8");
|
|
961
971
|
} else {
|
|
962
972
|
const existingSpan = findKeyObjectSpan(content, "qwenproxy");
|
|
963
973
|
if (existingSpan) {
|
|
@@ -981,7 +991,7 @@ ${qwenEntry}
|
|
|
981
991
|
}
|
|
982
992
|
}
|
|
983
993
|
}
|
|
984
|
-
|
|
994
|
+
fs6.writeFileSync(
|
|
985
995
|
filePath,
|
|
986
996
|
applyOpenCodeActiveModel(content, model, setActive),
|
|
987
997
|
"utf-8"
|
|
@@ -1008,9 +1018,9 @@ ${qwenEntry}
|
|
|
1008
1018
|
function restoreOpenCode(filePath, backupPath) {
|
|
1009
1019
|
const restoredFromBackup = restoreFromBackup(filePath, backupPath);
|
|
1010
1020
|
let manuallyCleaned = false;
|
|
1011
|
-
if (
|
|
1021
|
+
if (fs6.existsSync(filePath)) {
|
|
1012
1022
|
try {
|
|
1013
|
-
const data = JSON.parse(
|
|
1023
|
+
const data = JSON.parse(fs6.readFileSync(filePath, "utf-8"));
|
|
1014
1024
|
if (data.provider && data.provider.qwenproxy) {
|
|
1015
1025
|
delete data.provider.qwenproxy;
|
|
1016
1026
|
if (data.model && data.model.includes("qwen")) {
|
|
@@ -1019,7 +1029,7 @@ function restoreOpenCode(filePath, backupPath) {
|
|
|
1019
1029
|
if (Object.keys(data.provider).length === 0) {
|
|
1020
1030
|
delete data.provider;
|
|
1021
1031
|
}
|
|
1022
|
-
|
|
1032
|
+
fs6.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
1023
1033
|
manuallyCleaned = true;
|
|
1024
1034
|
}
|
|
1025
1035
|
} catch {
|
|
@@ -1037,7 +1047,7 @@ function restoreOpenCode(filePath, backupPath) {
|
|
|
1037
1047
|
}
|
|
1038
1048
|
|
|
1039
1049
|
// src/sync/omp.ts
|
|
1040
|
-
import
|
|
1050
|
+
import fs7 from "node:fs";
|
|
1041
1051
|
import path6 from "node:path";
|
|
1042
1052
|
function buildOmpProviderYaml(baseUrl, apiKey, primaryModel = "qwen3.8-max", models) {
|
|
1043
1053
|
const modelList = Array.from(
|
|
@@ -1069,12 +1079,12 @@ ${formattedModels}
|
|
|
1069
1079
|
function syncOmp(options) {
|
|
1070
1080
|
const { filePath, apiKey, baseUrl, model = "qwen3.8-max", models } = options;
|
|
1071
1081
|
try {
|
|
1072
|
-
|
|
1082
|
+
fs7.mkdirSync(path6.dirname(filePath), { recursive: true });
|
|
1073
1083
|
let backupPath;
|
|
1074
1084
|
let content = "";
|
|
1075
|
-
if (
|
|
1085
|
+
if (fs7.existsSync(filePath)) {
|
|
1076
1086
|
backupPath = createTimestampBackup(filePath);
|
|
1077
|
-
content =
|
|
1087
|
+
content = fs7.readFileSync(filePath, "utf-8");
|
|
1078
1088
|
}
|
|
1079
1089
|
const providerBlock = buildOmpProviderYaml(baseUrl, apiKey, model, models);
|
|
1080
1090
|
if (!content.trim()) {
|
|
@@ -1094,7 +1104,7 @@ ${providerBlock}`;
|
|
|
1094
1104
|
}
|
|
1095
1105
|
}
|
|
1096
1106
|
}
|
|
1097
|
-
|
|
1107
|
+
fs7.writeFileSync(filePath, content.trimEnd() + "\n", "utf-8");
|
|
1098
1108
|
return {
|
|
1099
1109
|
client: "omp",
|
|
1100
1110
|
filePath,
|
|
@@ -1116,13 +1126,13 @@ ${providerBlock}`;
|
|
|
1116
1126
|
function restoreOmp(filePath, backupPath) {
|
|
1117
1127
|
const restoredFromBackup = restoreFromBackup(filePath, backupPath);
|
|
1118
1128
|
let manuallyCleaned = false;
|
|
1119
|
-
if (
|
|
1129
|
+
if (fs7.existsSync(filePath)) {
|
|
1120
1130
|
try {
|
|
1121
|
-
let content =
|
|
1131
|
+
let content = fs7.readFileSync(filePath, "utf-8");
|
|
1122
1132
|
if (content.includes("qwenproxy:")) {
|
|
1123
1133
|
const regex = /^\s*qwenproxy:\s*\r?\n(?:^[ \t].*\r?\n?)*/m;
|
|
1124
1134
|
content = content.replace(regex, "");
|
|
1125
|
-
|
|
1135
|
+
fs7.writeFileSync(filePath, content, "utf-8");
|
|
1126
1136
|
manuallyCleaned = true;
|
|
1127
1137
|
}
|
|
1128
1138
|
} catch {
|
|
@@ -1140,7 +1150,7 @@ function restoreOmp(filePath, backupPath) {
|
|
|
1140
1150
|
}
|
|
1141
1151
|
|
|
1142
1152
|
// src/sync/hermes.ts
|
|
1143
|
-
import
|
|
1153
|
+
import fs8 from "node:fs";
|
|
1144
1154
|
import path7 from "node:path";
|
|
1145
1155
|
function buildHermesModelBlock(baseUrl, apiKey, model = "qwen3.8-max", reasoningEffort = "high") {
|
|
1146
1156
|
return `model:
|
|
@@ -1164,12 +1174,12 @@ function buildHermesProviderBlock(baseUrl, apiKey) {
|
|
|
1164
1174
|
function syncHermes(options) {
|
|
1165
1175
|
const { filePath, apiKey, baseUrl, model = "qwen3.8-max", reasoningEffort = "high" } = options;
|
|
1166
1176
|
try {
|
|
1167
|
-
|
|
1177
|
+
fs8.mkdirSync(path7.dirname(filePath), { recursive: true });
|
|
1168
1178
|
let backupPath;
|
|
1169
1179
|
let content = "";
|
|
1170
|
-
if (
|
|
1180
|
+
if (fs8.existsSync(filePath)) {
|
|
1171
1181
|
backupPath = createTimestampBackup(filePath);
|
|
1172
|
-
content =
|
|
1182
|
+
content = fs8.readFileSync(filePath, "utf-8");
|
|
1173
1183
|
}
|
|
1174
1184
|
const modelBlock = buildHermesModelBlock(baseUrl, apiKey, model, reasoningEffort);
|
|
1175
1185
|
const providerBlock = buildHermesProviderBlock(baseUrl, apiKey);
|
|
@@ -1195,7 +1205,7 @@ function syncHermes(options) {
|
|
|
1195
1205
|
}
|
|
1196
1206
|
}
|
|
1197
1207
|
}
|
|
1198
|
-
|
|
1208
|
+
fs8.writeFileSync(filePath, content.trimEnd() + "\n", "utf-8");
|
|
1199
1209
|
return {
|
|
1200
1210
|
client: "hermes",
|
|
1201
1211
|
filePath,
|
|
@@ -1227,7 +1237,7 @@ function restoreHermes(filePath, backupPath) {
|
|
|
1227
1237
|
}
|
|
1228
1238
|
|
|
1229
1239
|
// src/sync/openclaw.ts
|
|
1230
|
-
import
|
|
1240
|
+
import fs9 from "node:fs";
|
|
1231
1241
|
import path8 from "node:path";
|
|
1232
1242
|
function findKeyObjectSpan2(content, key) {
|
|
1233
1243
|
const regex = new RegExp(`"${key}"\\s*:\\s*\\{`);
|
|
@@ -1326,12 +1336,12 @@ function buildOpenClawProviderObject(baseUrl, apiKey, model = "qwen3.8-max", mod
|
|
|
1326
1336
|
function syncOpenClaw(options) {
|
|
1327
1337
|
const { filePath, apiKey, baseUrl, model = "qwen3.8-max", models, reasoningEffort = "high" } = options;
|
|
1328
1338
|
try {
|
|
1329
|
-
|
|
1339
|
+
fs9.mkdirSync(path8.dirname(filePath), { recursive: true });
|
|
1330
1340
|
let backupPath;
|
|
1331
1341
|
let content = "";
|
|
1332
|
-
if (
|
|
1342
|
+
if (fs9.existsSync(filePath)) {
|
|
1333
1343
|
backupPath = createTimestampBackup(filePath);
|
|
1334
|
-
content =
|
|
1344
|
+
content = fs9.readFileSync(filePath, "utf-8");
|
|
1335
1345
|
}
|
|
1336
1346
|
const providerObj = buildOpenClawProviderObject(baseUrl, apiKey, model, models);
|
|
1337
1347
|
const providerJson = JSON.stringify(providerObj, null, 6).split("\n").map((line, idx) => idx === 0 ? line : ` ${line}`).join("\n");
|
|
@@ -1355,7 +1365,7 @@ function syncOpenClaw(options) {
|
|
|
1355
1365
|
}
|
|
1356
1366
|
}
|
|
1357
1367
|
};
|
|
1358
|
-
|
|
1368
|
+
fs9.writeFileSync(filePath, JSON.stringify(initial, null, 2) + "\n", "utf-8");
|
|
1359
1369
|
} else {
|
|
1360
1370
|
const existingSpan = findKeyObjectSpan2(content, "qwenproxy");
|
|
1361
1371
|
if (existingSpan) {
|
|
@@ -1392,7 +1402,7 @@ ${qwenEntry}
|
|
|
1392
1402
|
}
|
|
1393
1403
|
}
|
|
1394
1404
|
}
|
|
1395
|
-
|
|
1405
|
+
fs9.writeFileSync(filePath, content, "utf-8");
|
|
1396
1406
|
}
|
|
1397
1407
|
return {
|
|
1398
1408
|
client: "openclaw",
|
|
@@ -1425,7 +1435,7 @@ function restoreOpenClaw(filePath, backupPath) {
|
|
|
1425
1435
|
}
|
|
1426
1436
|
|
|
1427
1437
|
// src/sync/kilo.ts
|
|
1428
|
-
import
|
|
1438
|
+
import fs10 from "node:fs";
|
|
1429
1439
|
import path9 from "node:path";
|
|
1430
1440
|
function findKeyObjectSpan3(content, key) {
|
|
1431
1441
|
const regex = new RegExp(`"${key}"\\s*:\\s*\\{`);
|
|
@@ -1532,12 +1542,12 @@ function buildKiloProviderObject(baseUrl, apiKey, primaryModel = "qwen3.8-max",
|
|
|
1532
1542
|
function syncKilo(options) {
|
|
1533
1543
|
const { filePath, apiKey, baseUrl, model = "qwen3.8-max", models, setActive = true } = options;
|
|
1534
1544
|
try {
|
|
1535
|
-
|
|
1545
|
+
fs10.mkdirSync(path9.dirname(filePath), { recursive: true });
|
|
1536
1546
|
let backupPath;
|
|
1537
1547
|
let content = "";
|
|
1538
|
-
if (
|
|
1548
|
+
if (fs10.existsSync(filePath)) {
|
|
1539
1549
|
backupPath = createTimestampBackup(filePath);
|
|
1540
|
-
content =
|
|
1550
|
+
content = fs10.readFileSync(filePath, "utf-8");
|
|
1541
1551
|
}
|
|
1542
1552
|
const providerObj = buildKiloProviderObject(baseUrl, apiKey, model, models);
|
|
1543
1553
|
const providerJson = JSON.stringify(providerObj, null, 6).split("\n").map((line, idx) => idx === 0 ? line : ` ${line}`).join("\n");
|
|
@@ -1552,7 +1562,7 @@ function syncKilo(options) {
|
|
|
1552
1562
|
if (setActive) {
|
|
1553
1563
|
initial.model = `qwenproxy/${model}`;
|
|
1554
1564
|
}
|
|
1555
|
-
|
|
1565
|
+
fs10.writeFileSync(filePath, JSON.stringify(initial, null, 2) + "\n", "utf-8");
|
|
1556
1566
|
} else {
|
|
1557
1567
|
const existingSpan = findKeyObjectSpan3(content, "qwenproxy");
|
|
1558
1568
|
if (existingSpan) {
|
|
@@ -1582,7 +1592,7 @@ ${qwenEntry}
|
|
|
1582
1592
|
content = content.replace(modelRegex, `"model": "qwenproxy/${model}"`);
|
|
1583
1593
|
}
|
|
1584
1594
|
}
|
|
1585
|
-
|
|
1595
|
+
fs10.writeFileSync(filePath, content, "utf-8");
|
|
1586
1596
|
}
|
|
1587
1597
|
return {
|
|
1588
1598
|
client: "kilo",
|
|
@@ -1615,7 +1625,7 @@ function restoreKilo(filePath, backupPath) {
|
|
|
1615
1625
|
}
|
|
1616
1626
|
|
|
1617
1627
|
// src/sync/cline.ts
|
|
1618
|
-
import
|
|
1628
|
+
import fs11 from "node:fs";
|
|
1619
1629
|
import path10 from "node:path";
|
|
1620
1630
|
import Database from "better-sqlite3";
|
|
1621
1631
|
var TARGET_KEYS = [
|
|
@@ -1626,9 +1636,9 @@ var TARGET_KEYS = [
|
|
|
1626
1636
|
function syncCline(options) {
|
|
1627
1637
|
const { filePath, baseUrl, model = "qwen3.8-max", reasoningEffort = "high" } = options;
|
|
1628
1638
|
try {
|
|
1629
|
-
|
|
1639
|
+
fs11.mkdirSync(path10.dirname(filePath), { recursive: true });
|
|
1630
1640
|
let backupPath;
|
|
1631
|
-
if (
|
|
1641
|
+
if (fs11.existsSync(filePath)) {
|
|
1632
1642
|
backupPath = createTimestampBackup(filePath);
|
|
1633
1643
|
}
|
|
1634
1644
|
const db = new Database(filePath);
|
|
@@ -1700,7 +1710,7 @@ function syncCline(options) {
|
|
|
1700
1710
|
function restoreCline(filePath, backupPath) {
|
|
1701
1711
|
const restoredFromBackup = restoreFromBackup(filePath, backupPath);
|
|
1702
1712
|
let manuallyCleaned = false;
|
|
1703
|
-
if (
|
|
1713
|
+
if (fs11.existsSync(filePath)) {
|
|
1704
1714
|
try {
|
|
1705
1715
|
const db = new Database(filePath);
|
|
1706
1716
|
const rows = db.prepare("SELECT key, value FROM ItemTable WHERE key = 'saoudrizwan.claude-dev' OR key = 'ZooCodeOrganization.zoo-code'").all();
|
|
@@ -1733,7 +1743,7 @@ function restoreCline(filePath, backupPath) {
|
|
|
1733
1743
|
}
|
|
1734
1744
|
|
|
1735
1745
|
// src/sync/zed.ts
|
|
1736
|
-
import
|
|
1746
|
+
import fs12 from "node:fs";
|
|
1737
1747
|
import path11 from "node:path";
|
|
1738
1748
|
function parseJsonWithComments(raw) {
|
|
1739
1749
|
let result = "";
|
|
@@ -1847,13 +1857,13 @@ function buildZedAvailableModels(primaryModel = "qwen3.8-max", models) {
|
|
|
1847
1857
|
function syncZed(options) {
|
|
1848
1858
|
const { filePath, baseUrl, model = "qwen3.8-max", models, setActive = true } = options;
|
|
1849
1859
|
try {
|
|
1850
|
-
|
|
1860
|
+
fs12.mkdirSync(path11.dirname(filePath), { recursive: true });
|
|
1851
1861
|
let backupPath;
|
|
1852
1862
|
let existingSettings = {};
|
|
1853
|
-
if (
|
|
1863
|
+
if (fs12.existsSync(filePath)) {
|
|
1854
1864
|
backupPath = createTimestampBackup(filePath);
|
|
1855
1865
|
try {
|
|
1856
|
-
const content =
|
|
1866
|
+
const content = fs12.readFileSync(filePath, "utf-8");
|
|
1857
1867
|
existingSettings = parseJsonWithComments(content);
|
|
1858
1868
|
} catch {
|
|
1859
1869
|
existingSettings = {};
|
|
@@ -1883,7 +1893,7 @@ function syncZed(options) {
|
|
|
1883
1893
|
}
|
|
1884
1894
|
};
|
|
1885
1895
|
}
|
|
1886
|
-
|
|
1896
|
+
fs12.writeFileSync(filePath, JSON.stringify(updatedSettings, null, 2) + "\n", "utf-8");
|
|
1887
1897
|
return {
|
|
1888
1898
|
client: "zed",
|
|
1889
1899
|
filePath,
|
|
@@ -1905,9 +1915,9 @@ function syncZed(options) {
|
|
|
1905
1915
|
function restoreZed(filePath, backupPath) {
|
|
1906
1916
|
const restoredFromBackup = restoreFromBackup(filePath, backupPath);
|
|
1907
1917
|
let manuallyCleaned = false;
|
|
1908
|
-
if (
|
|
1918
|
+
if (fs12.existsSync(filePath)) {
|
|
1909
1919
|
try {
|
|
1910
|
-
let content =
|
|
1920
|
+
let content = fs12.readFileSync(filePath, "utf-8");
|
|
1911
1921
|
if (content.includes("127.0.0.1:7936") || content.includes("qwen3.8-max")) {
|
|
1912
1922
|
const data = parseJsonWithComments(content);
|
|
1913
1923
|
if (data.language_models?.openai?.api_url?.includes("7936")) {
|
|
@@ -1915,7 +1925,7 @@ function restoreZed(filePath, backupPath) {
|
|
|
1915
1925
|
if (Object.keys(data.language_models).length === 0) {
|
|
1916
1926
|
delete data.language_models;
|
|
1917
1927
|
}
|
|
1918
|
-
|
|
1928
|
+
fs12.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
1919
1929
|
manuallyCleaned = true;
|
|
1920
1930
|
}
|
|
1921
1931
|
}
|
|
@@ -1934,7 +1944,7 @@ function restoreZed(filePath, backupPath) {
|
|
|
1934
1944
|
}
|
|
1935
1945
|
|
|
1936
1946
|
// src/sync/aider.ts
|
|
1937
|
-
import
|
|
1947
|
+
import fs13 from "node:fs";
|
|
1938
1948
|
import path12 from "node:path";
|
|
1939
1949
|
function updateYamlKeyValue(content, key, value) {
|
|
1940
1950
|
const regex = new RegExp(`^${key}:.*$`, "m");
|
|
@@ -1954,12 +1964,12 @@ function syncAider(options) {
|
|
|
1954
1964
|
modelSettingsPath
|
|
1955
1965
|
} = options;
|
|
1956
1966
|
try {
|
|
1957
|
-
|
|
1967
|
+
fs13.mkdirSync(path12.dirname(filePath), { recursive: true });
|
|
1958
1968
|
let backupPath;
|
|
1959
1969
|
let confContent = "";
|
|
1960
|
-
if (
|
|
1970
|
+
if (fs13.existsSync(filePath)) {
|
|
1961
1971
|
backupPath = createTimestampBackup(filePath);
|
|
1962
|
-
confContent =
|
|
1972
|
+
confContent = fs13.readFileSync(filePath, "utf-8");
|
|
1963
1973
|
}
|
|
1964
1974
|
const fullModelName = model.startsWith("openai/") ? model : `openai/${model}`;
|
|
1965
1975
|
const weakModelName = "openai/qwen3.7-plus";
|
|
@@ -1968,15 +1978,15 @@ function syncAider(options) {
|
|
|
1968
1978
|
confContent = updateYamlKeyValue(confContent, "model", fullModelName);
|
|
1969
1979
|
confContent = updateYamlKeyValue(confContent, "editor-model", fullModelName);
|
|
1970
1980
|
confContent = updateYamlKeyValue(confContent, "weak-model", weakModelName);
|
|
1971
|
-
|
|
1981
|
+
fs13.writeFileSync(filePath, confContent.trimEnd() + "\n", "utf-8");
|
|
1972
1982
|
let extraBackupPath;
|
|
1973
1983
|
const resolvedSettingsPath = modelSettingsPath || path12.join(path12.dirname(filePath), ".aider.model.settings.yml");
|
|
1974
1984
|
if (resolvedSettingsPath) {
|
|
1975
|
-
|
|
1985
|
+
fs13.mkdirSync(path12.dirname(resolvedSettingsPath), { recursive: true });
|
|
1976
1986
|
let settingsContent = "";
|
|
1977
|
-
if (
|
|
1987
|
+
if (fs13.existsSync(resolvedSettingsPath)) {
|
|
1978
1988
|
extraBackupPath = createTimestampBackup(resolvedSettingsPath);
|
|
1979
|
-
settingsContent =
|
|
1989
|
+
settingsContent = fs13.readFileSync(resolvedSettingsPath, "utf-8");
|
|
1980
1990
|
}
|
|
1981
1991
|
const modelBlock = `- name: ${fullModelName}
|
|
1982
1992
|
extra_params:
|
|
@@ -1990,7 +2000,7 @@ function syncAider(options) {
|
|
|
1990
2000
|
} else {
|
|
1991
2001
|
settingsContent = settingsContent.trimEnd() + (settingsContent.length > 0 ? "\n\n" : "") + modelBlock;
|
|
1992
2002
|
}
|
|
1993
|
-
|
|
2003
|
+
fs13.writeFileSync(resolvedSettingsPath, settingsContent.trimEnd() + "\n", "utf-8");
|
|
1994
2004
|
}
|
|
1995
2005
|
return {
|
|
1996
2006
|
client: "aider",
|
|
@@ -2080,14 +2090,14 @@ function getDefaultPaths() {
|
|
|
2080
2090
|
path13.join(home, ".opencode", "opencode.jsonc"),
|
|
2081
2091
|
path13.join(home, ".opencode", "opencode.json")
|
|
2082
2092
|
];
|
|
2083
|
-
const existingOpenCode = openCodeCandidates.find((p) =>
|
|
2093
|
+
const existingOpenCode = openCodeCandidates.find((p) => fs14.existsSync(p));
|
|
2084
2094
|
const kiloCandidates = [
|
|
2085
2095
|
path13.join(home, ".config", "kilo", "kilo.json"),
|
|
2086
2096
|
path13.join(home, ".kilo", "kilo.json"),
|
|
2087
2097
|
path13.join(home, ".config", "kilo", "config.json"),
|
|
2088
2098
|
path13.join(home, ".kilo", "config.json")
|
|
2089
2099
|
];
|
|
2090
|
-
const existingKilo = kiloCandidates.find((p) =>
|
|
2100
|
+
const existingKilo = kiloCandidates.find((p) => fs14.existsSync(p));
|
|
2091
2101
|
let clinePath;
|
|
2092
2102
|
if (isWindows) {
|
|
2093
2103
|
clinePath = path13.join(appData, "Code", "User", "globalStorage", "state.vscdb");
|
|
@@ -2104,7 +2114,7 @@ function getDefaultPaths() {
|
|
|
2104
2114
|
}
|
|
2105
2115
|
return {
|
|
2106
2116
|
claudeCode: path13.join(home, ".claude", "settings.json"),
|
|
2107
|
-
codex:
|
|
2117
|
+
codex: fs14.existsSync(path13.join(home, ".codex", "config.toml")) ? path13.join(home, ".codex", "config.toml") : process.env.CODEX_HOME ? path13.join(process.env.CODEX_HOME, "config.toml") : path13.join(home, ".codex", "config.toml"),
|
|
2108
2118
|
openCode: existingOpenCode || openCodeCandidates[0],
|
|
2109
2119
|
omp: path13.join(home, ".omp", "agent", "models.yml"),
|
|
2110
2120
|
hermes: path13.join(home, ".hermes", "config.yaml"),
|
|
@@ -2126,7 +2136,7 @@ function isExecutableInPath(name) {
|
|
|
2126
2136
|
for (const ext of extensions) {
|
|
2127
2137
|
const fullPath = path13.join(dir, name + ext);
|
|
2128
2138
|
try {
|
|
2129
|
-
if (
|
|
2139
|
+
if (fs14.existsSync(fullPath) && !fs14.statSync(fullPath).isDirectory()) {
|
|
2130
2140
|
return true;
|
|
2131
2141
|
}
|
|
2132
2142
|
} catch {
|
|
@@ -2144,9 +2154,9 @@ function isVscodeExtensionInstalled(pattern) {
|
|
|
2144
2154
|
path13.join(home, ".windsurf", "extensions")
|
|
2145
2155
|
];
|
|
2146
2156
|
for (const d of candidateDirs) {
|
|
2147
|
-
if (
|
|
2157
|
+
if (fs14.existsSync(d)) {
|
|
2148
2158
|
try {
|
|
2149
|
-
const entries =
|
|
2159
|
+
const entries = fs14.readdirSync(d);
|
|
2150
2160
|
if (entries.some((e) => pattern.test(e))) return true;
|
|
2151
2161
|
} catch {
|
|
2152
2162
|
}
|
|
@@ -2158,9 +2168,9 @@ function isZedInstalled() {
|
|
|
2158
2168
|
if (isExecutableInPath("zed")) return true;
|
|
2159
2169
|
if (process.platform === "win32") {
|
|
2160
2170
|
const local = process.env.LOCALAPPDATA || "";
|
|
2161
|
-
if (
|
|
2171
|
+
if (fs14.existsSync(path13.join(local, "Programs", "Zed"))) return true;
|
|
2162
2172
|
} else if (process.platform === "darwin") {
|
|
2163
|
-
if (
|
|
2173
|
+
if (fs14.existsSync("/Applications/Zed.app")) return true;
|
|
2164
2174
|
}
|
|
2165
2175
|
return false;
|
|
2166
2176
|
}
|
|
@@ -2173,7 +2183,7 @@ function isMatchingLocalHost(text, port = 7936) {
|
|
|
2173
2183
|
}
|
|
2174
2184
|
function isClientToolInstalled(id, targetPath, isCustomTestPath = false) {
|
|
2175
2185
|
if (isCustomTestPath) {
|
|
2176
|
-
return
|
|
2186
|
+
return fs14.existsSync(targetPath);
|
|
2177
2187
|
}
|
|
2178
2188
|
switch (id) {
|
|
2179
2189
|
case "hermes":
|
|
@@ -2189,15 +2199,15 @@ function isClientToolInstalled(id, targetPath, isCustomTestPath = false) {
|
|
|
2189
2199
|
case "zed":
|
|
2190
2200
|
return isZedInstalled();
|
|
2191
2201
|
case "claude-code":
|
|
2192
|
-
return isExecutableInPath("claude") ||
|
|
2202
|
+
return isExecutableInPath("claude") || fs14.existsSync(targetPath);
|
|
2193
2203
|
case "codex":
|
|
2194
|
-
return isExecutableInPath("codex") ||
|
|
2204
|
+
return isExecutableInPath("codex") || fs14.existsSync(targetPath);
|
|
2195
2205
|
case "opencode":
|
|
2196
|
-
return isExecutableInPath("opencode") ||
|
|
2206
|
+
return isExecutableInPath("opencode") || fs14.existsSync(targetPath);
|
|
2197
2207
|
case "omp":
|
|
2198
|
-
return isExecutableInPath("omp") ||
|
|
2208
|
+
return isExecutableInPath("omp") || fs14.existsSync(targetPath);
|
|
2199
2209
|
default:
|
|
2200
|
-
return
|
|
2210
|
+
return fs14.existsSync(targetPath);
|
|
2201
2211
|
}
|
|
2202
2212
|
}
|
|
2203
2213
|
function inspectClientSyncStatus(id, filePath, port = 7936) {
|
|
@@ -2207,7 +2217,7 @@ function inspectClientSyncStatus(id, filePath, port = 7936) {
|
|
|
2207
2217
|
filePath && defaultTarget && path13.resolve(filePath) !== path13.resolve(defaultTarget)
|
|
2208
2218
|
);
|
|
2209
2219
|
const targetPath = filePath || defaultTarget;
|
|
2210
|
-
if (!
|
|
2220
|
+
if (!fs14.existsSync(targetPath)) {
|
|
2211
2221
|
return { id, installed: false, synced: false };
|
|
2212
2222
|
}
|
|
2213
2223
|
const toolInstalled = isClientToolInstalled(id, targetPath, isCustomTestPath);
|
|
@@ -2237,7 +2247,7 @@ function inspectClientSyncStatus(id, filePath, port = 7936) {
|
|
|
2237
2247
|
const isInstalled = isCustomTestPath ? true : rowExists || isExecutableInPath("cline") || isVscodeExtensionInstalled(/cline|zoo-code|roo-cline/i);
|
|
2238
2248
|
return { id, installed: isInstalled, synced: isInstalled && isSynced, model };
|
|
2239
2249
|
}
|
|
2240
|
-
const raw =
|
|
2250
|
+
const raw = fs14.readFileSync(targetPath, "utf-8");
|
|
2241
2251
|
if (id === "claude-code") {
|
|
2242
2252
|
const data = JSON.parse(raw);
|
|
2243
2253
|
const url = data?.env?.ANTHROPIC_BASE_URL || "";
|
|
@@ -2363,7 +2373,7 @@ function syncAllClients(options = {}) {
|
|
|
2363
2373
|
return options.targets.includes(client);
|
|
2364
2374
|
};
|
|
2365
2375
|
if (shouldSync("claude-code")) {
|
|
2366
|
-
const claudeExisted =
|
|
2376
|
+
const claudeExisted = fs14.existsSync(paths.claudeCode);
|
|
2367
2377
|
const claudeRes = syncClaudeCode({
|
|
2368
2378
|
filePath: paths.claudeCode,
|
|
2369
2379
|
apiKey,
|
|
@@ -2381,7 +2391,7 @@ function syncAllClients(options = {}) {
|
|
|
2381
2391
|
}
|
|
2382
2392
|
}
|
|
2383
2393
|
if (shouldSync("codex")) {
|
|
2384
|
-
const codexExisted =
|
|
2394
|
+
const codexExisted = fs14.existsSync(paths.codex);
|
|
2385
2395
|
const codexRes = syncCodex({
|
|
2386
2396
|
filePath: paths.codex,
|
|
2387
2397
|
apiKey,
|
|
@@ -2400,7 +2410,7 @@ function syncAllClients(options = {}) {
|
|
|
2400
2410
|
}
|
|
2401
2411
|
}
|
|
2402
2412
|
if (shouldSync("opencode")) {
|
|
2403
|
-
const openCodeExisted =
|
|
2413
|
+
const openCodeExisted = fs14.existsSync(paths.openCode);
|
|
2404
2414
|
const openCodeRes = syncOpenCode({
|
|
2405
2415
|
filePath: paths.openCode,
|
|
2406
2416
|
apiKey,
|
|
@@ -2420,7 +2430,7 @@ function syncAllClients(options = {}) {
|
|
|
2420
2430
|
}
|
|
2421
2431
|
}
|
|
2422
2432
|
if (shouldSync("omp")) {
|
|
2423
|
-
const ompExisted =
|
|
2433
|
+
const ompExisted = fs14.existsSync(paths.omp);
|
|
2424
2434
|
const ompRes = syncOmp({
|
|
2425
2435
|
filePath: paths.omp,
|
|
2426
2436
|
apiKey,
|
|
@@ -2439,7 +2449,7 @@ function syncAllClients(options = {}) {
|
|
|
2439
2449
|
}
|
|
2440
2450
|
}
|
|
2441
2451
|
if (shouldSync("hermes")) {
|
|
2442
|
-
const hermesExisted =
|
|
2452
|
+
const hermesExisted = fs14.existsSync(paths.hermes);
|
|
2443
2453
|
const hermesRes = syncHermes({
|
|
2444
2454
|
filePath: paths.hermes,
|
|
2445
2455
|
apiKey,
|
|
@@ -2457,7 +2467,7 @@ function syncAllClients(options = {}) {
|
|
|
2457
2467
|
}
|
|
2458
2468
|
}
|
|
2459
2469
|
if (shouldSync("openclaw")) {
|
|
2460
|
-
const openClawExisted =
|
|
2470
|
+
const openClawExisted = fs14.existsSync(paths.openClaw);
|
|
2461
2471
|
const openClawRes = syncOpenClaw({
|
|
2462
2472
|
filePath: paths.openClaw,
|
|
2463
2473
|
apiKey,
|
|
@@ -2476,7 +2486,7 @@ function syncAllClients(options = {}) {
|
|
|
2476
2486
|
}
|
|
2477
2487
|
}
|
|
2478
2488
|
if (shouldSync("kilo")) {
|
|
2479
|
-
const kiloExisted =
|
|
2489
|
+
const kiloExisted = fs14.existsSync(paths.kilo);
|
|
2480
2490
|
const kiloRes = syncKilo({
|
|
2481
2491
|
filePath: paths.kilo,
|
|
2482
2492
|
apiKey,
|
|
@@ -2496,7 +2506,7 @@ function syncAllClients(options = {}) {
|
|
|
2496
2506
|
}
|
|
2497
2507
|
}
|
|
2498
2508
|
if (shouldSync("cline")) {
|
|
2499
|
-
const clineExisted =
|
|
2509
|
+
const clineExisted = fs14.existsSync(paths.cline);
|
|
2500
2510
|
const clineRes = syncCline({
|
|
2501
2511
|
filePath: paths.cline,
|
|
2502
2512
|
apiKey,
|
|
@@ -2514,7 +2524,7 @@ function syncAllClients(options = {}) {
|
|
|
2514
2524
|
}
|
|
2515
2525
|
}
|
|
2516
2526
|
if (shouldSync("zed")) {
|
|
2517
|
-
const zedExisted =
|
|
2527
|
+
const zedExisted = fs14.existsSync(paths.zed);
|
|
2518
2528
|
const zedRes = syncZed({
|
|
2519
2529
|
filePath: paths.zed,
|
|
2520
2530
|
apiKey,
|
|
@@ -2534,7 +2544,7 @@ function syncAllClients(options = {}) {
|
|
|
2534
2544
|
}
|
|
2535
2545
|
}
|
|
2536
2546
|
if (shouldSync("aider")) {
|
|
2537
|
-
const aiderExisted =
|
|
2547
|
+
const aiderExisted = fs14.existsSync(paths.aider);
|
|
2538
2548
|
const aiderRes = syncAider({
|
|
2539
2549
|
filePath: paths.aider,
|
|
2540
2550
|
apiKey,
|
|
@@ -2552,11 +2562,11 @@ function syncAllClients(options = {}) {
|
|
|
2552
2562
|
}
|
|
2553
2563
|
}
|
|
2554
2564
|
try {
|
|
2555
|
-
|
|
2565
|
+
fs14.mkdirSync(path13.dirname(stateFilePath), { recursive: true });
|
|
2556
2566
|
let existingClients = {};
|
|
2557
|
-
if (
|
|
2567
|
+
if (fs14.existsSync(stateFilePath)) {
|
|
2558
2568
|
try {
|
|
2559
|
-
const raw =
|
|
2569
|
+
const raw = fs14.readFileSync(stateFilePath, "utf-8");
|
|
2560
2570
|
const parsed = JSON.parse(raw);
|
|
2561
2571
|
if (parsed?.clients && typeof parsed.clients === "object") {
|
|
2562
2572
|
existingClients = parsed.clients;
|
|
@@ -2575,7 +2585,7 @@ function syncAllClients(options = {}) {
|
|
|
2575
2585
|
...stateRecords
|
|
2576
2586
|
}
|
|
2577
2587
|
};
|
|
2578
|
-
|
|
2588
|
+
fs14.writeFileSync(stateFilePath, JSON.stringify(stateContent, null, 2) + "\n", "utf-8");
|
|
2579
2589
|
} catch (err) {
|
|
2580
2590
|
console.error("Warning: could not write sync state file:", err);
|
|
2581
2591
|
}
|
|
@@ -2587,9 +2597,9 @@ function restoreAllClients(options = {}) {
|
|
|
2587
2597
|
const details = [];
|
|
2588
2598
|
let restoredCount = 0;
|
|
2589
2599
|
let state = null;
|
|
2590
|
-
if (
|
|
2600
|
+
if (fs14.existsSync(stateFilePath)) {
|
|
2591
2601
|
try {
|
|
2592
|
-
const raw =
|
|
2602
|
+
const raw = fs14.readFileSync(stateFilePath, "utf-8");
|
|
2593
2603
|
state = JSON.parse(raw);
|
|
2594
2604
|
} catch {
|
|
2595
2605
|
}
|
|
@@ -2614,7 +2624,7 @@ function restoreAllClients(options = {}) {
|
|
|
2614
2624
|
if (!shouldRestore(c.id)) continue;
|
|
2615
2625
|
const filePath = c.stateRecord?.filePath || c.defaultPath;
|
|
2616
2626
|
const backupPath = c.stateRecord?.backupPath;
|
|
2617
|
-
const canAttempt = options.stateFilePath ? Boolean(c.stateRecord) : Boolean(c.stateRecord ||
|
|
2627
|
+
const canAttempt = options.stateFilePath ? Boolean(c.stateRecord) : Boolean(c.stateRecord || fs14.existsSync(filePath));
|
|
2618
2628
|
if (canAttempt) {
|
|
2619
2629
|
const res = c.restoreFn(filePath, backupPath);
|
|
2620
2630
|
details.push(res);
|
|
@@ -2627,12 +2637,12 @@ function restoreAllClients(options = {}) {
|
|
|
2627
2637
|
}
|
|
2628
2638
|
}
|
|
2629
2639
|
}
|
|
2630
|
-
if (stateFilePath &&
|
|
2640
|
+
if (stateFilePath && fs14.existsSync(stateFilePath)) {
|
|
2631
2641
|
try {
|
|
2632
2642
|
if (state && state.clients && Object.keys(state.clients).length > 0) {
|
|
2633
|
-
|
|
2643
|
+
fs14.writeFileSync(stateFilePath, JSON.stringify(state, null, 2) + "\n", "utf-8");
|
|
2634
2644
|
} else {
|
|
2635
|
-
|
|
2645
|
+
fs14.unlinkSync(stateFilePath);
|
|
2636
2646
|
}
|
|
2637
2647
|
} catch {
|
|
2638
2648
|
}
|
|
@@ -2644,10 +2654,10 @@ function restoreAllClients(options = {}) {
|
|
|
2644
2654
|
process.env.DOTENV_CONFIG_QUIET = "true";
|
|
2645
2655
|
ensureDataDirs();
|
|
2646
2656
|
var envPath = getEnvFilePath();
|
|
2647
|
-
if (
|
|
2648
|
-
|
|
2657
|
+
if (fs15.existsSync(envPath)) {
|
|
2658
|
+
dotenv2.config({ path: envPath, quiet: true });
|
|
2649
2659
|
} else {
|
|
2650
|
-
|
|
2660
|
+
dotenv2.config({ quiet: true });
|
|
2651
2661
|
}
|
|
2652
2662
|
function parseArgs() {
|
|
2653
2663
|
const args = process.argv.slice(2);
|