swixter 0.1.1 → 0.1.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.md +55 -1
- package/dist/cli/index.js +1258 -162
- package/package.json +2 -2
package/dist/cli/index.js
CHANGED
|
@@ -464,7 +464,7 @@ var import_sisteransi, import_picocolors, uD, W, tD, eD, FD = function() {
|
|
|
464
464
|
` && (s && o && (F += z(s)), i && (F += K(i)));
|
|
465
465
|
}
|
|
466
466
|
return F;
|
|
467
|
-
}, xD, B, AD, S, gD, vD = (e, u, t) => (u in e) ? gD(e, u, { enumerable: true, configurable: true, writable: true, value: t }) : e[u] = t, h = (e, u, t) => (vD(e, typeof u != "symbol" ? u + "" : u, t), t), dD, A, kD, $D = (e, u, t) => (u in e) ? kD(e, u, { enumerable: true, configurable: true, writable: true, value: t }) : e[u] = t, H = (e, u, t) => ($D(e, typeof u != "symbol" ? u + "" : u, t), t), SD, OD, PD = (e, u, t) => (u in e) ? OD(e, u, { enumerable: true, configurable: true, writable: true, value: t }) : e[u] = t, J = (e, u, t) => (PD(e, typeof u != "symbol" ? u + "" : u, t), t), LD, RD;
|
|
467
|
+
}, xD, B, AD, S, gD, vD = (e, u, t) => (u in e) ? gD(e, u, { enumerable: true, configurable: true, writable: true, value: t }) : e[u] = t, h = (e, u, t) => (vD(e, typeof u != "symbol" ? u + "" : u, t), t), dD, A, kD, $D = (e, u, t) => (u in e) ? kD(e, u, { enumerable: true, configurable: true, writable: true, value: t }) : e[u] = t, H = (e, u, t) => ($D(e, typeof u != "symbol" ? u + "" : u, t), t), SD, TD, jD = (e, u, t) => (u in e) ? TD(e, u, { enumerable: true, configurable: true, writable: true, value: t }) : e[u] = t, U = (e, u, t) => (jD(e, typeof u != "symbol" ? u + "" : u, t), t), MD, OD, PD = (e, u, t) => (u in e) ? OD(e, u, { enumerable: true, configurable: true, writable: true, value: t }) : e[u] = t, J = (e, u, t) => (PD(e, typeof u != "symbol" ? u + "" : u, t), t), LD, RD;
|
|
468
468
|
var init_dist = __esm(() => {
|
|
469
469
|
import_sisteransi = __toESM(require_src(), 1);
|
|
470
470
|
import_picocolors = __toESM(require_picocolors(), 1);
|
|
@@ -567,6 +567,27 @@ var init_dist = __esm(() => {
|
|
|
567
567
|
this.value = u ? this.value.filter((t) => t !== this._value) : [...this.value, this._value];
|
|
568
568
|
}
|
|
569
569
|
};
|
|
570
|
+
TD = Object.defineProperty;
|
|
571
|
+
MD = class MD extends x {
|
|
572
|
+
constructor({ mask: u, ...t }) {
|
|
573
|
+
super(t), U(this, "valueWithCursor", ""), U(this, "_mask", "\u2022"), this._mask = u ?? "\u2022", this.on("finalize", () => {
|
|
574
|
+
this.valueWithCursor = this.masked;
|
|
575
|
+
}), this.on("value", () => {
|
|
576
|
+
if (this.cursor >= this.value.length)
|
|
577
|
+
this.valueWithCursor = `${this.masked}${import_picocolors.default.inverse(import_picocolors.default.hidden("_"))}`;
|
|
578
|
+
else {
|
|
579
|
+
const F = this.masked.slice(0, this.cursor), s = this.masked.slice(this.cursor);
|
|
580
|
+
this.valueWithCursor = `${F}${import_picocolors.default.inverse(s[0])}${s.slice(1)}`;
|
|
581
|
+
}
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
get cursor() {
|
|
585
|
+
return this._cursor;
|
|
586
|
+
}
|
|
587
|
+
get masked() {
|
|
588
|
+
return this.value.replaceAll(/./g, this._mask);
|
|
589
|
+
}
|
|
590
|
+
};
|
|
570
591
|
OD = Object.defineProperty;
|
|
571
592
|
LD = class LD extends x {
|
|
572
593
|
constructor(u) {
|
|
@@ -616,7 +637,7 @@ import y2 from "process";
|
|
|
616
637
|
function ce() {
|
|
617
638
|
return y2.platform !== "win32" ? y2.env.TERM !== "linux" : !!y2.env.CI || !!y2.env.WT_SESSION || !!y2.env.TERMINUS_SUBLIME || y2.env.ConEmuTask === "{cmd::Cmder}" || y2.env.TERM_PROGRAM === "Terminus-Sublime" || y2.env.TERM_PROGRAM === "vscode" || y2.env.TERM === "xterm-256color" || y2.env.TERM === "alacritty" || y2.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
|
|
618
639
|
}
|
|
619
|
-
var import_picocolors2, import_sisteransi2, V2, u = (t, n) => V2 ? t : n, le, L2, W2, C, ue, o, d2, k2, P2, A2, T, F, $e, _2, me, de, pe, q, D,
|
|
640
|
+
var import_picocolors2, import_sisteransi2, V2, u = (t, n) => V2 ? t : n, le, L2, W2, C, ue, o, d2, k2, P2, A2, T, F, $e, _2, me, de, pe, q, D, U2, K2, b2 = (t) => {
|
|
620
641
|
switch (t) {
|
|
621
642
|
case "initial":
|
|
622
643
|
case "active":
|
|
@@ -655,6 +676,26 @@ ${import_picocolors2.default.gray(o)}` : ""}`;
|
|
|
655
676
|
default:
|
|
656
677
|
return `${n}${import_picocolors2.default.cyan(o)} ${i}
|
|
657
678
|
${import_picocolors2.default.cyan(d2)}
|
|
679
|
+
`;
|
|
680
|
+
}
|
|
681
|
+
} }).prompt(), ge = (t) => new MD({ validate: t.validate, mask: t.mask ?? $e, render() {
|
|
682
|
+
const n = `${import_picocolors2.default.gray(o)}
|
|
683
|
+
${b2(this.state)} ${t.message}
|
|
684
|
+
`, r2 = this.valueWithCursor, i = this.masked;
|
|
685
|
+
switch (this.state) {
|
|
686
|
+
case "error":
|
|
687
|
+
return `${n.trim()}
|
|
688
|
+
${import_picocolors2.default.yellow(o)} ${i}
|
|
689
|
+
${import_picocolors2.default.yellow(d2)} ${import_picocolors2.default.yellow(this.error)}
|
|
690
|
+
`;
|
|
691
|
+
case "submit":
|
|
692
|
+
return `${n}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.dim(i)}`;
|
|
693
|
+
case "cancel":
|
|
694
|
+
return `${n}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(i ?? ""))}${i ? `
|
|
695
|
+
${import_picocolors2.default.gray(o)}` : ""}`;
|
|
696
|
+
default:
|
|
697
|
+
return `${n}${import_picocolors2.default.cyan(o)} ${r2}
|
|
698
|
+
${import_picocolors2.default.cyan(d2)}
|
|
658
699
|
`;
|
|
659
700
|
}
|
|
660
701
|
} }).prompt(), ye = (t) => {
|
|
@@ -834,7 +875,7 @@ var init_dist2 = __esm(() => {
|
|
|
834
875
|
pe = u("\u256F", "+");
|
|
835
876
|
q = u("\u25CF", "\u2022");
|
|
836
877
|
D = u("\u25C6", "*");
|
|
837
|
-
|
|
878
|
+
U2 = u("\u25B2", "!");
|
|
838
879
|
K2 = u("\u25A0", "x");
|
|
839
880
|
J2 = `${import_picocolors2.default.gray(o)} `;
|
|
840
881
|
});
|
|
@@ -13633,7 +13674,7 @@ var init_types = __esm(() => {
|
|
|
13633
13674
|
});
|
|
13634
13675
|
|
|
13635
13676
|
// src/types.ts
|
|
13636
|
-
var ProviderPresetSchema, ClaudeCodeProfileSchema, CoderConfigSchema, ConfigFileSchema, ExportConfigSchema;
|
|
13677
|
+
var ProviderPresetSchema, ClaudeCodeProfileSchema, CoderConfigSchema, SyncMetaSchema, ConfigFileSchema, ExportConfigSchema;
|
|
13637
13678
|
var init_types2 = __esm(() => {
|
|
13638
13679
|
init_zod();
|
|
13639
13680
|
init_types();
|
|
@@ -13681,12 +13722,20 @@ var init_types2 = __esm(() => {
|
|
|
13681
13722
|
CoderConfigSchema = exports_external.object({
|
|
13682
13723
|
activeProfile: exports_external.string()
|
|
13683
13724
|
});
|
|
13725
|
+
SyncMetaSchema = exports_external.object({
|
|
13726
|
+
lastSyncAt: exports_external.string(),
|
|
13727
|
+
configVersion: exports_external.number(),
|
|
13728
|
+
providersVersion: exports_external.number(),
|
|
13729
|
+
localUpdatedAt: exports_external.string(),
|
|
13730
|
+
dirty: exports_external.boolean().optional()
|
|
13731
|
+
});
|
|
13684
13732
|
ConfigFileSchema = exports_external.object({
|
|
13685
13733
|
profiles: exports_external.record(exports_external.string(), ClaudeCodeProfileSchema),
|
|
13686
13734
|
coders: exports_external.record(exports_external.string(), CoderConfigSchema),
|
|
13687
13735
|
groups: exports_external.record(exports_external.string(), GroupSchema),
|
|
13688
13736
|
activeGroup: exports_external.string().optional(),
|
|
13689
|
-
version: exports_external.string()
|
|
13737
|
+
version: exports_external.string(),
|
|
13738
|
+
syncMeta: SyncMetaSchema.optional()
|
|
13690
13739
|
});
|
|
13691
13740
|
ExportConfigSchema = exports_external.object({
|
|
13692
13741
|
profiles: exports_external.array(ClaudeCodeProfileSchema),
|
|
@@ -13950,7 +13999,7 @@ var CONFIG_VERSION = "2.0.0", EXPORT_VERSION = "1.0.0";
|
|
|
13950
13999
|
var init_versions2 = () => {};
|
|
13951
14000
|
|
|
13952
14001
|
// src/constants/meta.ts
|
|
13953
|
-
var APP_VERSION = "0.1.
|
|
14002
|
+
var APP_VERSION = "0.1.2";
|
|
13954
14003
|
var init_meta = () => {};
|
|
13955
14004
|
|
|
13956
14005
|
// src/constants/install.ts
|
|
@@ -14058,6 +14107,9 @@ var init_install = __esm(() => {
|
|
|
14058
14107
|
// src/constants/proxy.ts
|
|
14059
14108
|
var DEFAULT_PROXY_HOST = "127.0.0.1", DEFAULT_PROXY_PORT = 15721, SWIXTER_PROXY_AUTH_TOKEN = "swixter-local-proxy", SWIXTER_CLAUDE_MODEL = "SWIXTER_CLAUDE_MODEL", SWIXTER_CLAUDE_HAIKU_MODEL = "SWIXTER_CLAUDE_HAIKU_MODEL", SWIXTER_CLAUDE_SONNET_MODEL = "SWIXTER_CLAUDE_SONNET_MODEL", SWIXTER_CLAUDE_OPUS_MODEL = "SWIXTER_CLAUDE_OPUS_MODEL";
|
|
14060
14109
|
|
|
14110
|
+
// src/constants/api.ts
|
|
14111
|
+
var API_BASE = "https://api.swixter.com";
|
|
14112
|
+
|
|
14061
14113
|
// src/constants/index.ts
|
|
14062
14114
|
var init_constants = __esm(() => {
|
|
14063
14115
|
init_coders();
|
|
@@ -19039,13 +19091,15 @@ __export(exports_manager, {
|
|
|
19039
19091
|
saveConfig: () => saveConfig,
|
|
19040
19092
|
resetAllData: () => resetAllData,
|
|
19041
19093
|
profileExists: () => profileExists,
|
|
19094
|
+
markDirty: () => markDirty,
|
|
19042
19095
|
loadConfig: () => loadConfig,
|
|
19043
19096
|
listProfiles: () => listProfiles,
|
|
19044
19097
|
getProfile: () => getProfile,
|
|
19045
19098
|
getConfigPath: () => getConfigPath2,
|
|
19046
19099
|
getActiveProfileForCoder: () => getActiveProfileForCoder,
|
|
19047
19100
|
getActiveProfile: () => getActiveProfile,
|
|
19048
|
-
deleteProfile: () => deleteProfile
|
|
19101
|
+
deleteProfile: () => deleteProfile,
|
|
19102
|
+
clearSyncMeta: () => clearSyncMeta
|
|
19049
19103
|
});
|
|
19050
19104
|
import { existsSync as existsSync5 } from "fs";
|
|
19051
19105
|
import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile5, rename } from "fs/promises";
|
|
@@ -19109,6 +19163,11 @@ async function saveConfig(config2) {
|
|
|
19109
19163
|
throw new Error(`Failed to save configuration: ${error46}`);
|
|
19110
19164
|
}
|
|
19111
19165
|
}
|
|
19166
|
+
function markDirty(config2) {
|
|
19167
|
+
if (config2.syncMeta) {
|
|
19168
|
+
config2.syncMeta.dirty = true;
|
|
19169
|
+
}
|
|
19170
|
+
}
|
|
19112
19171
|
async function getActiveProfile() {
|
|
19113
19172
|
return getActiveProfileForCoder("claude");
|
|
19114
19173
|
}
|
|
@@ -19132,6 +19191,7 @@ async function setActiveProfileForCoder(coder, profileName) {
|
|
|
19132
19191
|
config2.coders[coder] = { activeProfile: "" };
|
|
19133
19192
|
}
|
|
19134
19193
|
config2.coders[coder].activeProfile = profileName;
|
|
19194
|
+
markDirty(config2);
|
|
19135
19195
|
await saveConfig(config2);
|
|
19136
19196
|
}
|
|
19137
19197
|
async function upsertProfile(profile, coder) {
|
|
@@ -19151,6 +19211,7 @@ async function upsertProfile(profile, coder) {
|
|
|
19151
19211
|
config2.coders[coder].activeProfile = profile.name;
|
|
19152
19212
|
}
|
|
19153
19213
|
}
|
|
19214
|
+
markDirty(config2);
|
|
19154
19215
|
await saveConfig(config2);
|
|
19155
19216
|
}
|
|
19156
19217
|
async function deleteProfile(profileName) {
|
|
@@ -19177,6 +19238,7 @@ async function deleteProfile(profileName) {
|
|
|
19177
19238
|
config2.coders[coder].activeProfile = "";
|
|
19178
19239
|
}
|
|
19179
19240
|
}
|
|
19241
|
+
markDirty(config2);
|
|
19180
19242
|
await saveConfig(config2);
|
|
19181
19243
|
}
|
|
19182
19244
|
async function listProfiles() {
|
|
@@ -19205,8 +19267,16 @@ async function resetAllData() {
|
|
|
19205
19267
|
}
|
|
19206
19268
|
}
|
|
19207
19269
|
const defaultConfig = createDefaultConfig();
|
|
19270
|
+
markDirty(defaultConfig);
|
|
19208
19271
|
await saveConfig(defaultConfig);
|
|
19209
19272
|
}
|
|
19273
|
+
async function clearSyncMeta() {
|
|
19274
|
+
const config2 = await loadConfig();
|
|
19275
|
+
if (config2.syncMeta) {
|
|
19276
|
+
delete config2.syncMeta;
|
|
19277
|
+
await saveConfig(config2);
|
|
19278
|
+
}
|
|
19279
|
+
}
|
|
19210
19280
|
var init_manager = __esm(() => {
|
|
19211
19281
|
init_types2();
|
|
19212
19282
|
init_constants();
|
|
@@ -23449,6 +23519,545 @@ var init_export = __esm(() => {
|
|
|
23449
23519
|
init_constants();
|
|
23450
23520
|
});
|
|
23451
23521
|
|
|
23522
|
+
// src/auth/client.ts
|
|
23523
|
+
async function apiRequest(path, options = {}) {
|
|
23524
|
+
const url2 = `${API_BASE}${path}`;
|
|
23525
|
+
const response = await fetch(url2, {
|
|
23526
|
+
...options,
|
|
23527
|
+
headers: {
|
|
23528
|
+
"Content-Type": "application/json",
|
|
23529
|
+
...options.headers
|
|
23530
|
+
}
|
|
23531
|
+
});
|
|
23532
|
+
if (!response.ok) {
|
|
23533
|
+
const error46 = await response.json().catch(() => ({}));
|
|
23534
|
+
throw new AuthError(response.status, error46.code || "UNKNOWN", error46.message || `HTTP ${response.status}`);
|
|
23535
|
+
}
|
|
23536
|
+
const text = await response.text();
|
|
23537
|
+
if (!text)
|
|
23538
|
+
return;
|
|
23539
|
+
return JSON.parse(text);
|
|
23540
|
+
}
|
|
23541
|
+
async function sendVerificationCode(email3) {
|
|
23542
|
+
return apiRequest("/api/auth/register/send-code", {
|
|
23543
|
+
method: "POST",
|
|
23544
|
+
body: JSON.stringify({ email: email3 })
|
|
23545
|
+
});
|
|
23546
|
+
}
|
|
23547
|
+
async function verifyAndRegister(data) {
|
|
23548
|
+
return apiRequest("/api/auth/register/verify", {
|
|
23549
|
+
method: "POST",
|
|
23550
|
+
body: JSON.stringify(data)
|
|
23551
|
+
});
|
|
23552
|
+
}
|
|
23553
|
+
async function loginUser(credentials) {
|
|
23554
|
+
return apiRequest("/api/auth/login", {
|
|
23555
|
+
method: "POST",
|
|
23556
|
+
body: JSON.stringify(credentials)
|
|
23557
|
+
});
|
|
23558
|
+
}
|
|
23559
|
+
async function refreshToken(refreshToken2) {
|
|
23560
|
+
return apiRequest("/api/auth/refresh", {
|
|
23561
|
+
method: "POST",
|
|
23562
|
+
body: JSON.stringify({ refreshToken: refreshToken2 })
|
|
23563
|
+
});
|
|
23564
|
+
}
|
|
23565
|
+
async function logoutUser(refreshToken2) {
|
|
23566
|
+
await apiRequest("/api/auth/logout", {
|
|
23567
|
+
method: "POST",
|
|
23568
|
+
body: JSON.stringify({ refreshToken: refreshToken2 })
|
|
23569
|
+
});
|
|
23570
|
+
}
|
|
23571
|
+
async function setPassword(accessToken, password) {
|
|
23572
|
+
await apiRequest("/api/auth/set-password", {
|
|
23573
|
+
method: "POST",
|
|
23574
|
+
headers: { Authorization: `Bearer ${accessToken}` },
|
|
23575
|
+
body: JSON.stringify({ password })
|
|
23576
|
+
});
|
|
23577
|
+
}
|
|
23578
|
+
async function deleteAccount(accessToken) {
|
|
23579
|
+
await apiRequest("/api/auth/account", {
|
|
23580
|
+
method: "DELETE",
|
|
23581
|
+
headers: { Authorization: `Bearer ${accessToken}` }
|
|
23582
|
+
});
|
|
23583
|
+
}
|
|
23584
|
+
async function sendMagicLink(email3) {
|
|
23585
|
+
return apiRequest("/api/auth/magic-link/send", {
|
|
23586
|
+
method: "POST",
|
|
23587
|
+
body: JSON.stringify({ email: email3 })
|
|
23588
|
+
});
|
|
23589
|
+
}
|
|
23590
|
+
async function verifyMagicLink(email3, token) {
|
|
23591
|
+
return apiRequest("/api/auth/magic-link/verify", {
|
|
23592
|
+
method: "POST",
|
|
23593
|
+
body: JSON.stringify({ email: email3, token })
|
|
23594
|
+
});
|
|
23595
|
+
}
|
|
23596
|
+
async function checkMagicLinkSession(sessionId) {
|
|
23597
|
+
return apiRequest(`/api/auth/magic-link/session/${encodeURIComponent(sessionId)}`, { method: "GET" });
|
|
23598
|
+
}
|
|
23599
|
+
var AuthError;
|
|
23600
|
+
var init_client = __esm(() => {
|
|
23601
|
+
AuthError = class AuthError extends Error {
|
|
23602
|
+
status;
|
|
23603
|
+
code;
|
|
23604
|
+
constructor(status, code, message) {
|
|
23605
|
+
super(message);
|
|
23606
|
+
this.status = status;
|
|
23607
|
+
this.code = code;
|
|
23608
|
+
this.name = "AuthError";
|
|
23609
|
+
}
|
|
23610
|
+
};
|
|
23611
|
+
});
|
|
23612
|
+
|
|
23613
|
+
// src/auth/token.ts
|
|
23614
|
+
import { existsSync as existsSync11 } from "fs";
|
|
23615
|
+
import { readFile as readFile8, writeFile as writeFile8, unlink as unlink2 } from "fs/promises";
|
|
23616
|
+
import { join as join10 } from "path";
|
|
23617
|
+
function getAuthFilePath() {
|
|
23618
|
+
return join10(getConfigDir("swixter"), AUTH_FILE);
|
|
23619
|
+
}
|
|
23620
|
+
async function loadAuthState() {
|
|
23621
|
+
const authPath = getAuthFilePath();
|
|
23622
|
+
if (!existsSync11(authPath))
|
|
23623
|
+
return null;
|
|
23624
|
+
try {
|
|
23625
|
+
const content = await readFile8(authPath, "utf-8");
|
|
23626
|
+
return JSON.parse(content);
|
|
23627
|
+
} catch {
|
|
23628
|
+
return null;
|
|
23629
|
+
}
|
|
23630
|
+
}
|
|
23631
|
+
async function saveAuthState(state) {
|
|
23632
|
+
const authPath = getAuthFilePath();
|
|
23633
|
+
await writeFile8(authPath, JSON.stringify(state, null, 2), { mode: 384, encoding: "utf-8" });
|
|
23634
|
+
}
|
|
23635
|
+
async function clearAuthState() {
|
|
23636
|
+
const authPath = getAuthFilePath();
|
|
23637
|
+
if (existsSync11(authPath)) {
|
|
23638
|
+
await unlink2(authPath);
|
|
23639
|
+
}
|
|
23640
|
+
}
|
|
23641
|
+
function isExpired(expiresAt) {
|
|
23642
|
+
const expiry = new Date(expiresAt).getTime();
|
|
23643
|
+
const now = Date.now();
|
|
23644
|
+
const bufferMs = 5 * 60 * 1000;
|
|
23645
|
+
return now >= expiry - bufferMs;
|
|
23646
|
+
}
|
|
23647
|
+
async function getAccessToken() {
|
|
23648
|
+
const state = await loadAuthState();
|
|
23649
|
+
if (!state)
|
|
23650
|
+
return null;
|
|
23651
|
+
if (!isExpired(state.expiresAt)) {
|
|
23652
|
+
return state.accessToken;
|
|
23653
|
+
}
|
|
23654
|
+
try {
|
|
23655
|
+
const refreshed = await refreshToken(state.refreshToken);
|
|
23656
|
+
state.accessToken = refreshed.accessToken;
|
|
23657
|
+
state.expiresAt = refreshed.expiresAt;
|
|
23658
|
+
await saveAuthState(state);
|
|
23659
|
+
return refreshed.accessToken;
|
|
23660
|
+
} catch {
|
|
23661
|
+
await clearAuthState();
|
|
23662
|
+
return null;
|
|
23663
|
+
}
|
|
23664
|
+
}
|
|
23665
|
+
async function isLoggedIn() {
|
|
23666
|
+
const token = await getAccessToken();
|
|
23667
|
+
return token !== null;
|
|
23668
|
+
}
|
|
23669
|
+
var AUTH_FILE = "auth.json";
|
|
23670
|
+
var init_token = __esm(() => {
|
|
23671
|
+
init_paths();
|
|
23672
|
+
init_client();
|
|
23673
|
+
});
|
|
23674
|
+
|
|
23675
|
+
// src/crypto/derive.ts
|
|
23676
|
+
async function deriveKey(password, saltBase64) {
|
|
23677
|
+
const salt = Uint8Array.from(atob(saltBase64), (c) => c.charCodeAt(0));
|
|
23678
|
+
const keyMaterial = await crypto.subtle.importKey("raw", new TextEncoder().encode(password), "PBKDF2", false, ["deriveKey"]);
|
|
23679
|
+
return crypto.subtle.deriveKey({
|
|
23680
|
+
name: "PBKDF2",
|
|
23681
|
+
salt,
|
|
23682
|
+
iterations: PBKDF2_ITERATIONS,
|
|
23683
|
+
hash: "SHA-256"
|
|
23684
|
+
}, keyMaterial, { name: "AES-GCM", length: 256 }, true, ["encrypt", "decrypt"]);
|
|
23685
|
+
}
|
|
23686
|
+
async function importKeyFromBase64(keyBase64) {
|
|
23687
|
+
const keyBytes = Uint8Array.from(atob(keyBase64), (c) => c.charCodeAt(0));
|
|
23688
|
+
return crypto.subtle.importKey("raw", keyBytes, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
|
|
23689
|
+
}
|
|
23690
|
+
async function exportKeyToBase64(key) {
|
|
23691
|
+
const rawKey = await crypto.subtle.exportKey("raw", key);
|
|
23692
|
+
return btoa(String.fromCharCode(...new Uint8Array(rawKey)));
|
|
23693
|
+
}
|
|
23694
|
+
var PBKDF2_ITERATIONS = 1e5;
|
|
23695
|
+
|
|
23696
|
+
// src/sync/client.ts
|
|
23697
|
+
async function syncRequest(path, accessToken, options = {}) {
|
|
23698
|
+
const url2 = `${API_BASE}${path}`;
|
|
23699
|
+
const response = await fetch(url2, {
|
|
23700
|
+
...options,
|
|
23701
|
+
headers: {
|
|
23702
|
+
"Content-Type": "application/json",
|
|
23703
|
+
Authorization: `Bearer ${accessToken}`,
|
|
23704
|
+
...options.headers
|
|
23705
|
+
}
|
|
23706
|
+
});
|
|
23707
|
+
if (!response.ok) {
|
|
23708
|
+
const error46 = await response.json().catch(() => ({}));
|
|
23709
|
+
throw new SyncError(response.status, error46.code || "UNKNOWN", error46.message || `HTTP ${response.status}`);
|
|
23710
|
+
}
|
|
23711
|
+
return response.json();
|
|
23712
|
+
}
|
|
23713
|
+
async function getSyncStatus(accessToken) {
|
|
23714
|
+
return syncRequest("/api/sync/status", accessToken);
|
|
23715
|
+
}
|
|
23716
|
+
async function pushData(accessToken, data) {
|
|
23717
|
+
return syncRequest("/api/sync/push", accessToken, {
|
|
23718
|
+
method: "POST",
|
|
23719
|
+
body: JSON.stringify(data)
|
|
23720
|
+
});
|
|
23721
|
+
}
|
|
23722
|
+
async function pullData(accessToken, dataKey) {
|
|
23723
|
+
return syncRequest(`/api/sync/pull?dataKey=${encodeURIComponent(dataKey)}`, accessToken);
|
|
23724
|
+
}
|
|
23725
|
+
var SyncError;
|
|
23726
|
+
var init_client2 = __esm(() => {
|
|
23727
|
+
SyncError = class SyncError extends Error {
|
|
23728
|
+
status;
|
|
23729
|
+
code;
|
|
23730
|
+
constructor(status, code, message) {
|
|
23731
|
+
super(message);
|
|
23732
|
+
this.status = status;
|
|
23733
|
+
this.code = code;
|
|
23734
|
+
this.name = "SyncError";
|
|
23735
|
+
}
|
|
23736
|
+
};
|
|
23737
|
+
});
|
|
23738
|
+
|
|
23739
|
+
// src/sync/merge.ts
|
|
23740
|
+
function getLocalVersion(meta2, dataKey) {
|
|
23741
|
+
if (!meta2)
|
|
23742
|
+
return 0;
|
|
23743
|
+
if (dataKey === "config")
|
|
23744
|
+
return meta2.configVersion;
|
|
23745
|
+
if (dataKey === "providers")
|
|
23746
|
+
return meta2.providersVersion;
|
|
23747
|
+
return 0;
|
|
23748
|
+
}
|
|
23749
|
+
function detectConflict(localMeta, remoteStatuses, dataKey) {
|
|
23750
|
+
const localVersion = getLocalVersion(localMeta, dataKey);
|
|
23751
|
+
const remoteEntry = remoteStatuses.find((s) => s.dataKey === dataKey);
|
|
23752
|
+
const remoteVersion = remoteEntry?.dataVersion ?? 0;
|
|
23753
|
+
if (localVersion === remoteVersion) {
|
|
23754
|
+
return null;
|
|
23755
|
+
}
|
|
23756
|
+
if (localVersion === 0) {
|
|
23757
|
+
return null;
|
|
23758
|
+
}
|
|
23759
|
+
if (remoteVersion === 0) {
|
|
23760
|
+
return null;
|
|
23761
|
+
}
|
|
23762
|
+
return {
|
|
23763
|
+
localVersion,
|
|
23764
|
+
remoteVersion,
|
|
23765
|
+
dataKey
|
|
23766
|
+
};
|
|
23767
|
+
}
|
|
23768
|
+
|
|
23769
|
+
// src/crypto/encrypt.ts
|
|
23770
|
+
async function encrypt(key, plaintext) {
|
|
23771
|
+
const iv = crypto.getRandomValues(new Uint8Array(IV_LENGTH));
|
|
23772
|
+
const encoded = new TextEncoder().encode(plaintext);
|
|
23773
|
+
const encrypted = await crypto.subtle.encrypt({ name: "AES-GCM", iv }, key, encoded);
|
|
23774
|
+
const combined = new Uint8Array(iv.length + encrypted.byteLength);
|
|
23775
|
+
combined.set(iv, 0);
|
|
23776
|
+
combined.set(new Uint8Array(encrypted), iv.length);
|
|
23777
|
+
return btoa(String.fromCharCode(...combined));
|
|
23778
|
+
}
|
|
23779
|
+
async function decrypt(key, encryptedBase64) {
|
|
23780
|
+
const combined = Uint8Array.from(atob(encryptedBase64), (c) => c.charCodeAt(0));
|
|
23781
|
+
const iv = combined.slice(0, IV_LENGTH);
|
|
23782
|
+
const ciphertext = combined.slice(IV_LENGTH);
|
|
23783
|
+
const decrypted = await crypto.subtle.decrypt({ name: "AES-GCM", iv }, key, ciphertext);
|
|
23784
|
+
return new TextDecoder().decode(decrypted);
|
|
23785
|
+
}
|
|
23786
|
+
var IV_LENGTH = 12;
|
|
23787
|
+
|
|
23788
|
+
// src/crypto/fields.ts
|
|
23789
|
+
async function encryptSensitiveFields(key, obj) {
|
|
23790
|
+
const result = { ...obj };
|
|
23791
|
+
for (const field of SENSITIVE_FIELDS) {
|
|
23792
|
+
const value = result[field];
|
|
23793
|
+
if (typeof value === "string") {
|
|
23794
|
+
result[field] = await encrypt(key, value);
|
|
23795
|
+
}
|
|
23796
|
+
}
|
|
23797
|
+
return result;
|
|
23798
|
+
}
|
|
23799
|
+
async function decryptSensitiveFields(key, obj) {
|
|
23800
|
+
const result = { ...obj };
|
|
23801
|
+
for (const field of SENSITIVE_FIELDS) {
|
|
23802
|
+
const value = result[field];
|
|
23803
|
+
if (typeof value === "string") {
|
|
23804
|
+
result[field] = await decrypt(key, value);
|
|
23805
|
+
}
|
|
23806
|
+
}
|
|
23807
|
+
return result;
|
|
23808
|
+
}
|
|
23809
|
+
var SENSITIVE_FIELDS;
|
|
23810
|
+
var init_fields = __esm(() => {
|
|
23811
|
+
SENSITIVE_FIELDS = ["apiKey", "authToken"];
|
|
23812
|
+
});
|
|
23813
|
+
|
|
23814
|
+
// src/sync/auto-sync.ts
|
|
23815
|
+
function setAutoSyncEnabled(enabled) {
|
|
23816
|
+
autoSyncEnabled = enabled;
|
|
23817
|
+
}
|
|
23818
|
+
var autoSyncEnabled = false;
|
|
23819
|
+
var init_auto_sync = __esm(() => {
|
|
23820
|
+
init_token();
|
|
23821
|
+
init_client2();
|
|
23822
|
+
init_manager();
|
|
23823
|
+
init_user_providers();
|
|
23824
|
+
init_fields();
|
|
23825
|
+
});
|
|
23826
|
+
|
|
23827
|
+
// src/cli/sync.ts
|
|
23828
|
+
var exports_sync = {};
|
|
23829
|
+
__export(exports_sync, {
|
|
23830
|
+
handleSyncCommand: () => handleSyncCommand
|
|
23831
|
+
});
|
|
23832
|
+
async function requireAuth() {
|
|
23833
|
+
const token = await getAccessToken();
|
|
23834
|
+
if (!token) {
|
|
23835
|
+
console.log(import_picocolors15.default.yellow("Not logged in."));
|
|
23836
|
+
console.log(import_picocolors15.default.dim("Run 'swixter auth login' first"));
|
|
23837
|
+
process.exit(1);
|
|
23838
|
+
}
|
|
23839
|
+
return token;
|
|
23840
|
+
}
|
|
23841
|
+
async function getEncryptionKey() {
|
|
23842
|
+
const state = await loadAuthState();
|
|
23843
|
+
if (!state)
|
|
23844
|
+
throw new Error("Not authenticated");
|
|
23845
|
+
if (state.encryptionKey) {
|
|
23846
|
+
return importKeyFromBase64(state.encryptionKey);
|
|
23847
|
+
}
|
|
23848
|
+
const masterPassword = await ge({
|
|
23849
|
+
message: "Master password:",
|
|
23850
|
+
validate: (v2) => {
|
|
23851
|
+
if (!v2)
|
|
23852
|
+
return "Master password is required for encryption";
|
|
23853
|
+
}
|
|
23854
|
+
});
|
|
23855
|
+
if (pD(masterPassword)) {
|
|
23856
|
+
process.exit(0);
|
|
23857
|
+
}
|
|
23858
|
+
return deriveKey(masterPassword, state.encryptionSalt);
|
|
23859
|
+
}
|
|
23860
|
+
async function cmdStatus() {
|
|
23861
|
+
const token = await requireAuth();
|
|
23862
|
+
const s = Y2();
|
|
23863
|
+
s.start("Checking sync status...");
|
|
23864
|
+
try {
|
|
23865
|
+
const remote = await getSyncStatus(token);
|
|
23866
|
+
const config2 = await loadConfig();
|
|
23867
|
+
const syncMeta = config2.syncMeta;
|
|
23868
|
+
s.stop("Sync status:");
|
|
23869
|
+
console.log();
|
|
23870
|
+
console.log(import_picocolors15.default.bold(" Remote:"));
|
|
23871
|
+
if (remote.statuses.length === 0) {
|
|
23872
|
+
console.log(import_picocolors15.default.dim(" No data synced"));
|
|
23873
|
+
} else {
|
|
23874
|
+
for (const entry of remote.statuses) {
|
|
23875
|
+
console.log(` ${import_picocolors15.default.cyan(entry.dataKey)}: v${entry.dataVersion} (${import_picocolors15.default.dim(entry.updatedAt)})`);
|
|
23876
|
+
}
|
|
23877
|
+
}
|
|
23878
|
+
console.log();
|
|
23879
|
+
console.log(import_picocolors15.default.bold(" Local:"));
|
|
23880
|
+
if (syncMeta) {
|
|
23881
|
+
console.log(` config: v${syncMeta.configVersion} (${import_picocolors15.default.dim(syncMeta.localUpdatedAt)})`);
|
|
23882
|
+
console.log(` providers: v${syncMeta.providersVersion} (${import_picocolors15.default.dim(syncMeta.lastSyncAt)})`);
|
|
23883
|
+
} else {
|
|
23884
|
+
console.log(import_picocolors15.default.dim(" Never synced"));
|
|
23885
|
+
}
|
|
23886
|
+
console.log();
|
|
23887
|
+
} catch (err) {
|
|
23888
|
+
s.stop(import_picocolors15.default.red("Failed to get sync status"));
|
|
23889
|
+
console.error(import_picocolors15.default.red(err.message || "Unknown error"));
|
|
23890
|
+
process.exit(1);
|
|
23891
|
+
}
|
|
23892
|
+
}
|
|
23893
|
+
async function cmdPush(forceLocal = false) {
|
|
23894
|
+
const token = await requireAuth();
|
|
23895
|
+
const s = Y2();
|
|
23896
|
+
s.start("Pushing config to cloud...");
|
|
23897
|
+
try {
|
|
23898
|
+
const remote = await getSyncStatus(token);
|
|
23899
|
+
const config2 = await loadConfig();
|
|
23900
|
+
const syncMeta = config2.syncMeta;
|
|
23901
|
+
if (!forceLocal) {
|
|
23902
|
+
const configConflict = detectConflict(syncMeta ?? null, remote.statuses, "config");
|
|
23903
|
+
if (configConflict) {
|
|
23904
|
+
s.stop(import_picocolors15.default.yellow("Version conflict detected!"));
|
|
23905
|
+
console.log(` Local version: ${configConflict.localVersion}, Remote version: ${configConflict.remoteVersion}`);
|
|
23906
|
+
console.log(import_picocolors15.default.dim(" Use --force-local to overwrite remote, or pull first"));
|
|
23907
|
+
process.exit(1);
|
|
23908
|
+
}
|
|
23909
|
+
}
|
|
23910
|
+
s.stop(import_picocolors15.default.dim("Requesting master password..."));
|
|
23911
|
+
const key = await getEncryptionKey();
|
|
23912
|
+
s.start("Encrypting and pushing...");
|
|
23913
|
+
const encryptedProfiles = {};
|
|
23914
|
+
for (const [id, profile] of Object.entries(config2.profiles)) {
|
|
23915
|
+
encryptedProfiles[id] = await encryptSensitiveFields(key, profile);
|
|
23916
|
+
}
|
|
23917
|
+
const configRemoteEntry = remote.statuses.find((s2) => s2.dataKey === "config");
|
|
23918
|
+
const configVersion = configRemoteEntry?.dataVersion ?? 0;
|
|
23919
|
+
const pushResult = await pushData(token, {
|
|
23920
|
+
dataKey: "config",
|
|
23921
|
+
encryptedData: JSON.stringify(encryptedProfiles),
|
|
23922
|
+
dataVersion: configVersion,
|
|
23923
|
+
clientTimestamp: new Date().toISOString()
|
|
23924
|
+
});
|
|
23925
|
+
const providers = await loadUserProviders();
|
|
23926
|
+
const providersRemoteEntry = remote.statuses.find((s2) => s2.dataKey === "providers");
|
|
23927
|
+
const providersVersion = providersRemoteEntry?.dataVersion ?? 0;
|
|
23928
|
+
const providersPushResult = await pushData(token, {
|
|
23929
|
+
dataKey: "providers",
|
|
23930
|
+
encryptedData: JSON.stringify(await encryptSensitiveFields(key, { providers })),
|
|
23931
|
+
dataVersion: providersVersion,
|
|
23932
|
+
clientTimestamp: new Date().toISOString()
|
|
23933
|
+
});
|
|
23934
|
+
const now = new Date().toISOString();
|
|
23935
|
+
const updatedMeta = {
|
|
23936
|
+
lastSyncAt: now,
|
|
23937
|
+
configVersion: pushResult.dataVersion,
|
|
23938
|
+
providersVersion: providersPushResult.dataVersion,
|
|
23939
|
+
localUpdatedAt: now
|
|
23940
|
+
};
|
|
23941
|
+
config2.syncMeta = updatedMeta;
|
|
23942
|
+
await saveConfig(config2);
|
|
23943
|
+
s.stop(import_picocolors15.default.green(`Pushed config (v${pushResult.dataVersion}), providers (v${providersPushResult.dataVersion})`));
|
|
23944
|
+
} catch (err) {
|
|
23945
|
+
s.stop(import_picocolors15.default.red("Push failed"));
|
|
23946
|
+
if (err instanceof SyncError && err.status === 409) {
|
|
23947
|
+
console.log(import_picocolors15.default.yellow(" Version conflict. Use --force-local to overwrite."));
|
|
23948
|
+
} else {
|
|
23949
|
+
console.error(import_picocolors15.default.red(err.message || "Unknown error"));
|
|
23950
|
+
}
|
|
23951
|
+
process.exit(1);
|
|
23952
|
+
}
|
|
23953
|
+
}
|
|
23954
|
+
async function cmdPull(forceRemote = false) {
|
|
23955
|
+
const token = await requireAuth();
|
|
23956
|
+
const s = Y2();
|
|
23957
|
+
s.start("Pulling config from cloud...");
|
|
23958
|
+
try {
|
|
23959
|
+
const pullResult = await pullData(token, "config");
|
|
23960
|
+
const config2 = await loadConfig();
|
|
23961
|
+
const syncMeta = config2.syncMeta;
|
|
23962
|
+
if (!forceRemote && syncMeta) {
|
|
23963
|
+
const configConflict = detectConflict(syncMeta, [{ dataKey: "config", dataVersion: pullResult.dataVersion, updatedAt: pullResult.updatedAt }], "config");
|
|
23964
|
+
if (configConflict) {
|
|
23965
|
+
s.stop(import_picocolors15.default.yellow("Version conflict detected!"));
|
|
23966
|
+
console.log(` Local version: ${configConflict.localVersion}, Remote version: ${configConflict.remoteVersion}`);
|
|
23967
|
+
console.log(import_picocolors15.default.dim(" Use --force-remote to overwrite local, or push first"));
|
|
23968
|
+
process.exit(1);
|
|
23969
|
+
}
|
|
23970
|
+
}
|
|
23971
|
+
s.stop(import_picocolors15.default.dim("Requesting master password..."));
|
|
23972
|
+
const key = await getEncryptionKey();
|
|
23973
|
+
s.start("Decrypting...");
|
|
23974
|
+
const encryptedProfiles = JSON.parse(pullResult.encryptedData);
|
|
23975
|
+
for (const [id, profile] of Object.entries(encryptedProfiles)) {
|
|
23976
|
+
config2.profiles[id] = await decryptSensitiveFields(key, profile);
|
|
23977
|
+
}
|
|
23978
|
+
let providersVersion = syncMeta?.providersVersion ?? 0;
|
|
23979
|
+
try {
|
|
23980
|
+
const providersResult = await pullData(token, "providers");
|
|
23981
|
+
const providersEncrypted = JSON.parse(providersResult.encryptedData);
|
|
23982
|
+
const providersDecrypted = await decryptSensitiveFields(key, providersEncrypted);
|
|
23983
|
+
if (providersDecrypted.providers && Array.isArray(providersDecrypted.providers)) {
|
|
23984
|
+
await saveUserProviders(providersDecrypted.providers);
|
|
23985
|
+
providersVersion = providersResult.dataVersion;
|
|
23986
|
+
}
|
|
23987
|
+
} catch (err) {
|
|
23988
|
+
if (err instanceof SyncError && err.status === 404) {} else {
|
|
23989
|
+
throw err;
|
|
23990
|
+
}
|
|
23991
|
+
}
|
|
23992
|
+
const now = new Date().toISOString();
|
|
23993
|
+
config2.syncMeta = {
|
|
23994
|
+
lastSyncAt: now,
|
|
23995
|
+
configVersion: pullResult.dataVersion,
|
|
23996
|
+
providersVersion,
|
|
23997
|
+
localUpdatedAt: now
|
|
23998
|
+
};
|
|
23999
|
+
await saveConfig(config2);
|
|
24000
|
+
s.stop(import_picocolors15.default.green(`Pulled config (v${pullResult.dataVersion}), providers (v${providersVersion})`));
|
|
24001
|
+
} catch (err) {
|
|
24002
|
+
s.stop(import_picocolors15.default.red("Pull failed"));
|
|
24003
|
+
if (err instanceof SyncError && err.status === 404) {
|
|
24004
|
+
console.log(import_picocolors15.default.dim("No remote data found. Push first with 'swixter sync push'"));
|
|
24005
|
+
} else {
|
|
24006
|
+
console.error(import_picocolors15.default.red(err.message || "Unknown error"));
|
|
24007
|
+
}
|
|
24008
|
+
process.exit(1);
|
|
24009
|
+
}
|
|
24010
|
+
}
|
|
24011
|
+
async function handleSyncCommand(args) {
|
|
24012
|
+
const subcommand = args[0];
|
|
24013
|
+
switch (subcommand) {
|
|
24014
|
+
case "push": {
|
|
24015
|
+
const forceLocal = args.includes("--force-local");
|
|
24016
|
+
await cmdPush(forceLocal);
|
|
24017
|
+
break;
|
|
24018
|
+
}
|
|
24019
|
+
case "pull": {
|
|
24020
|
+
const forceRemote = args.includes("--force-remote");
|
|
24021
|
+
await cmdPull(forceRemote);
|
|
24022
|
+
break;
|
|
24023
|
+
}
|
|
24024
|
+
case "status":
|
|
24025
|
+
await cmdStatus();
|
|
24026
|
+
break;
|
|
24027
|
+
case "enable":
|
|
24028
|
+
setAutoSyncEnabled(true);
|
|
24029
|
+
console.log(import_picocolors15.default.green("\u2713 Auto sync enabled"));
|
|
24030
|
+
break;
|
|
24031
|
+
case "disable":
|
|
24032
|
+
setAutoSyncEnabled(false);
|
|
24033
|
+
console.log(import_picocolors15.default.green("\u2713 Auto sync disabled"));
|
|
24034
|
+
break;
|
|
24035
|
+
default:
|
|
24036
|
+
console.log(import_picocolors15.default.red(`Unknown sync subcommand: ${subcommand}`));
|
|
24037
|
+
console.log();
|
|
24038
|
+
console.log(import_picocolors15.default.bold("Available subcommands:"));
|
|
24039
|
+
console.log(` ${import_picocolors15.default.cyan("push")} [--force-local] - Push config to cloud`);
|
|
24040
|
+
console.log(` ${import_picocolors15.default.cyan("pull")} [--force-remote] - Pull config from cloud`);
|
|
24041
|
+
console.log(` ${import_picocolors15.default.cyan("status")} - Show sync state`);
|
|
24042
|
+
console.log(` ${import_picocolors15.default.cyan("enable")} - Enable auto sync`);
|
|
24043
|
+
console.log(` ${import_picocolors15.default.cyan("disable")} - Disable auto sync`);
|
|
24044
|
+
console.log();
|
|
24045
|
+
process.exit(1);
|
|
24046
|
+
}
|
|
24047
|
+
}
|
|
24048
|
+
var import_picocolors15;
|
|
24049
|
+
var init_sync = __esm(() => {
|
|
24050
|
+
init_dist2();
|
|
24051
|
+
init_token();
|
|
24052
|
+
init_client2();
|
|
24053
|
+
init_client2();
|
|
24054
|
+
init_manager();
|
|
24055
|
+
init_user_providers();
|
|
24056
|
+
init_fields();
|
|
24057
|
+
init_auto_sync();
|
|
24058
|
+
import_picocolors15 = __toESM(require_picocolors(), 1);
|
|
24059
|
+
});
|
|
24060
|
+
|
|
23452
24061
|
// src/cli/group.ts
|
|
23453
24062
|
var exports_group = {};
|
|
23454
24063
|
__export(exports_group, {
|
|
@@ -23459,7 +24068,7 @@ function cancelAndExit() {
|
|
|
23459
24068
|
process.exit(EXIT_CODES.cancelled);
|
|
23460
24069
|
}
|
|
23461
24070
|
function exitWithError(message, exitCode = EXIT_CODES.generalError) {
|
|
23462
|
-
console.log(
|
|
24071
|
+
console.log(import_picocolors17.default.red(message));
|
|
23463
24072
|
process.exit(exitCode);
|
|
23464
24073
|
}
|
|
23465
24074
|
async function getExistingGroupNameSet() {
|
|
@@ -23533,7 +24142,7 @@ async function handleGroupCommand(args) {
|
|
|
23533
24142
|
await cmdShow(args.slice(1));
|
|
23534
24143
|
break;
|
|
23535
24144
|
default:
|
|
23536
|
-
console.log(
|
|
24145
|
+
console.log(import_picocolors17.default.red(`Unknown subcommand: ${subcommand}`));
|
|
23537
24146
|
console.log(groupHelp());
|
|
23538
24147
|
process.exit(EXIT_CODES.invalidArgument);
|
|
23539
24148
|
}
|
|
@@ -23541,15 +24150,15 @@ async function handleGroupCommand(args) {
|
|
|
23541
24150
|
async function cmdList4() {
|
|
23542
24151
|
const groups = await listGroups();
|
|
23543
24152
|
if (groups.length === 0) {
|
|
23544
|
-
console.log(
|
|
24153
|
+
console.log(import_picocolors17.default.yellow("No groups defined. Create one with: swixter group create"));
|
|
23545
24154
|
return;
|
|
23546
24155
|
}
|
|
23547
24156
|
console.log();
|
|
23548
|
-
console.log(
|
|
24157
|
+
console.log(import_picocolors17.default.bold("Groups:"));
|
|
23549
24158
|
console.log();
|
|
23550
24159
|
for (const group of groups) {
|
|
23551
|
-
const marker = group.isDefault ?
|
|
23552
|
-
const name = group.isDefault ?
|
|
24160
|
+
const marker = group.isDefault ? import_picocolors17.default.green("\u2713") : " ";
|
|
24161
|
+
const name = group.isDefault ? import_picocolors17.default.green(group.name) : import_picocolors17.default.cyan(group.name);
|
|
23553
24162
|
console.log(` ${marker} ${name} - ${group.profiles.length} profiles`);
|
|
23554
24163
|
}
|
|
23555
24164
|
console.log();
|
|
@@ -23590,9 +24199,9 @@ async function cmdCreate4(args) {
|
|
|
23590
24199
|
}
|
|
23591
24200
|
const group = await createGroup({ name, profiles });
|
|
23592
24201
|
console.log();
|
|
23593
|
-
console.log(
|
|
23594
|
-
console.log(
|
|
23595
|
-
console.log(
|
|
24202
|
+
console.log(import_picocolors17.default.green(`\u2713 Group "${group.name}" created`));
|
|
24203
|
+
console.log(import_picocolors17.default.dim(` ID: ${group.id}`));
|
|
24204
|
+
console.log(import_picocolors17.default.dim(` Profiles: ${group.profiles.join(", ")}`));
|
|
23596
24205
|
console.log();
|
|
23597
24206
|
}
|
|
23598
24207
|
async function promptForProfiles(initialSelectedProfiles = []) {
|
|
@@ -23630,7 +24239,7 @@ async function promptForProfiles(initialSelectedProfiles = []) {
|
|
|
23630
24239
|
return selectedProfiles;
|
|
23631
24240
|
}
|
|
23632
24241
|
console.log();
|
|
23633
|
-
console.log(
|
|
24242
|
+
console.log(import_picocolors17.default.dim("Set failover priority. Priority 1 is tried first."));
|
|
23634
24243
|
return await promptForProfileOrder(selectedProfiles);
|
|
23635
24244
|
}
|
|
23636
24245
|
async function promptForProfileOrder(selectedProfiles) {
|
|
@@ -23734,9 +24343,9 @@ async function cmdEdit4(args) {
|
|
|
23734
24343
|
exitWithError(`Failed to update group: ${group.name}`);
|
|
23735
24344
|
}
|
|
23736
24345
|
console.log();
|
|
23737
|
-
console.log(
|
|
23738
|
-
console.log(
|
|
23739
|
-
console.log(
|
|
24346
|
+
console.log(import_picocolors17.default.green(`\u2713 Group "${updated.name}" updated`));
|
|
24347
|
+
console.log(import_picocolors17.default.dim(` ID: ${updated.id}`));
|
|
24348
|
+
console.log(import_picocolors17.default.dim(` Profiles: ${updated.profiles.join(", ")}`));
|
|
23740
24349
|
console.log();
|
|
23741
24350
|
}
|
|
23742
24351
|
async function cmdDelete4(args) {
|
|
@@ -23762,7 +24371,7 @@ async function cmdDelete4(args) {
|
|
|
23762
24371
|
}
|
|
23763
24372
|
if (confirmed) {
|
|
23764
24373
|
await deleteGroup(group.id);
|
|
23765
|
-
console.log(
|
|
24374
|
+
console.log(import_picocolors17.default.green(`\u2713 Group "${group.name}" deleted`));
|
|
23766
24375
|
}
|
|
23767
24376
|
}
|
|
23768
24377
|
async function cmdSetDefault(args) {
|
|
@@ -23772,7 +24381,7 @@ async function cmdSetDefault(args) {
|
|
|
23772
24381
|
}
|
|
23773
24382
|
const group = await setDefaultGroup(name);
|
|
23774
24383
|
if (group) {
|
|
23775
|
-
console.log(
|
|
24384
|
+
console.log(import_picocolors17.default.green(`\u2713 "${group.name}" is now the default group`));
|
|
23776
24385
|
} else {
|
|
23777
24386
|
exitWithError(`Group not found: ${name}`, EXIT_CODES.notFound);
|
|
23778
24387
|
}
|
|
@@ -23787,37 +24396,37 @@ async function cmdShow(args) {
|
|
|
23787
24396
|
exitWithError(`Group not found: ${name}`, EXIT_CODES.notFound);
|
|
23788
24397
|
}
|
|
23789
24398
|
console.log();
|
|
23790
|
-
console.log(
|
|
23791
|
-
console.log(
|
|
23792
|
-
console.log(
|
|
23793
|
-
console.log(
|
|
24399
|
+
console.log(import_picocolors17.default.bold("Group: ") + import_picocolors17.default.cyan(group.name));
|
|
24400
|
+
console.log(import_picocolors17.default.bold("ID: ") + group.id);
|
|
24401
|
+
console.log(import_picocolors17.default.bold("Default: ") + (group.isDefault ? import_picocolors17.default.green("yes") : import_picocolors17.default.dim("no")));
|
|
24402
|
+
console.log(import_picocolors17.default.bold("Profiles:"));
|
|
23794
24403
|
group.profiles.forEach((p2, i2) => {
|
|
23795
|
-
console.log(
|
|
24404
|
+
console.log(import_picocolors17.default.dim(` ${i2 + 1}. ${p2}`));
|
|
23796
24405
|
});
|
|
23797
24406
|
console.log();
|
|
23798
24407
|
}
|
|
23799
24408
|
function groupHelp() {
|
|
23800
24409
|
return `
|
|
23801
|
-
${
|
|
23802
|
-
|
|
23803
|
-
${
|
|
23804
|
-
${
|
|
23805
|
-
|
|
23806
|
-
${
|
|
23807
|
-
${
|
|
23808
|
-
${
|
|
23809
|
-
${
|
|
23810
|
-
${
|
|
23811
|
-
${
|
|
23812
|
-
${
|
|
23813
|
-
|
|
23814
|
-
${
|
|
23815
|
-
${
|
|
23816
|
-
${
|
|
23817
|
-
${
|
|
24410
|
+
${import_picocolors17.default.bold("Swixter Group Commands")}
|
|
24411
|
+
|
|
24412
|
+
${import_picocolors17.default.bold("Usage:")}
|
|
24413
|
+
${import_picocolors17.default.green("swixter group <command> [options]")}
|
|
24414
|
+
|
|
24415
|
+
${import_picocolors17.default.bold("Commands:")}
|
|
24416
|
+
${import_picocolors17.default.cyan("list, ls")} List all groups
|
|
24417
|
+
${import_picocolors17.default.cyan("create, new")} Create a new group
|
|
24418
|
+
${import_picocolors17.default.cyan("edit")} Edit a group
|
|
24419
|
+
${import_picocolors17.default.cyan("delete, rm")} Delete a group
|
|
24420
|
+
${import_picocolors17.default.cyan("set-default")} Set default group
|
|
24421
|
+
${import_picocolors17.default.cyan("show, info")} Show group details
|
|
24422
|
+
|
|
24423
|
+
${import_picocolors17.default.bold("Examples:")}
|
|
24424
|
+
${import_picocolors17.default.green("swixter group list")}
|
|
24425
|
+
${import_picocolors17.default.green("swixter group create my-group --profiles profile-a,profile-b")}
|
|
24426
|
+
${import_picocolors17.default.green("swixter group set-default my-group")}
|
|
23818
24427
|
`;
|
|
23819
24428
|
}
|
|
23820
|
-
var
|
|
24429
|
+
var import_picocolors17;
|
|
23821
24430
|
var init_group = __esm(() => {
|
|
23822
24431
|
init_dist2();
|
|
23823
24432
|
init_manager2();
|
|
@@ -23826,7 +24435,7 @@ var init_group = __esm(() => {
|
|
|
23826
24435
|
init_messages();
|
|
23827
24436
|
init_formatting();
|
|
23828
24437
|
init_validation();
|
|
23829
|
-
|
|
24438
|
+
import_picocolors17 = __toESM(require_picocolors(), 1);
|
|
23830
24439
|
});
|
|
23831
24440
|
|
|
23832
24441
|
// src/cli/proxy.ts
|
|
@@ -23926,13 +24535,13 @@ async function handleProxyCommand(args) {
|
|
|
23926
24535
|
await cmdRun4(args.slice(1));
|
|
23927
24536
|
break;
|
|
23928
24537
|
case "status":
|
|
23929
|
-
await
|
|
24538
|
+
await cmdStatus3();
|
|
23930
24539
|
break;
|
|
23931
24540
|
default:
|
|
23932
24541
|
if (!subcommand || subcommand === "status") {
|
|
23933
|
-
await
|
|
24542
|
+
await cmdStatus3();
|
|
23934
24543
|
} else {
|
|
23935
|
-
console.log(
|
|
24544
|
+
console.log(import_picocolors18.default.red(`Unknown subcommand: ${subcommand}`));
|
|
23936
24545
|
console.log(proxyHelp());
|
|
23937
24546
|
process.exit(1);
|
|
23938
24547
|
}
|
|
@@ -23964,21 +24573,21 @@ async function cmdStart(args) {
|
|
|
23964
24573
|
if (groupName) {
|
|
23965
24574
|
const group = await getGroup(groupName);
|
|
23966
24575
|
if (!group) {
|
|
23967
|
-
console.log(
|
|
24576
|
+
console.log(import_picocolors18.default.red(`Group "${groupName}" not found`));
|
|
23968
24577
|
process.exit(EXIT_CODES.notFound);
|
|
23969
24578
|
return;
|
|
23970
24579
|
}
|
|
23971
24580
|
}
|
|
23972
24581
|
const defaultStatus = getProxyStatus("default");
|
|
23973
24582
|
if (defaultStatus.running) {
|
|
23974
|
-
console.log(
|
|
24583
|
+
console.log(import_picocolors18.default.yellow(`Default proxy already running on ${defaultStatus.host}:${defaultStatus.port}`));
|
|
23975
24584
|
return;
|
|
23976
24585
|
}
|
|
23977
24586
|
if (!groupName) {
|
|
23978
24587
|
const activeGroup = await getActiveGroup();
|
|
23979
24588
|
if (activeGroup) {
|
|
23980
24589
|
groupName = activeGroup.name;
|
|
23981
|
-
console.log(
|
|
24590
|
+
console.log(import_picocolors18.default.dim(`Using default group: ${groupName}`));
|
|
23982
24591
|
}
|
|
23983
24592
|
}
|
|
23984
24593
|
const resolvedPort = port || DEFAULT_PROXY_PORT;
|
|
@@ -23989,7 +24598,7 @@ async function cmdStart(args) {
|
|
|
23989
24598
|
}
|
|
23990
24599
|
}
|
|
23991
24600
|
async function cmdStartBlocking(config2) {
|
|
23992
|
-
console.log(
|
|
24601
|
+
console.log(import_picocolors18.default.cyan("Starting proxy server..."));
|
|
23993
24602
|
await startProxyServer({
|
|
23994
24603
|
instanceId: "default",
|
|
23995
24604
|
type: "service",
|
|
@@ -23999,30 +24608,28 @@ async function cmdStartBlocking(config2) {
|
|
|
23999
24608
|
groupName: config2.groupName
|
|
24000
24609
|
});
|
|
24001
24610
|
console.log();
|
|
24002
|
-
console.log(
|
|
24611
|
+
console.log(import_picocolors18.default.green("\u2713 Proxy server started"));
|
|
24003
24612
|
console.log(` Instance: default (service)`);
|
|
24004
24613
|
console.log(` Address: ${config2.host}:${config2.port}`);
|
|
24005
24614
|
console.log(` Timeout: ${config2.timeout}ms`);
|
|
24006
|
-
console.log(
|
|
24007
|
-
console.log(
|
|
24008
|
-
console.log(
|
|
24009
|
-
console.log(
|
|
24010
|
-
console.log(
|
|
24011
|
-
console.log(
|
|
24012
|
-
console.log(
|
|
24615
|
+
console.log(import_picocolors18.default.dim(` Group: ${config2.groupName || "none"}`));
|
|
24616
|
+
console.log(import_picocolors18.default.dim(` Endpoints:`));
|
|
24617
|
+
console.log(import_picocolors18.default.dim(` - /v1/chat/completions (OpenAI)`));
|
|
24618
|
+
console.log(import_picocolors18.default.dim(` - /v1/messages (Anthropic)`));
|
|
24619
|
+
console.log(import_picocolors18.default.dim(` - /v1/responses (Anthropic)`));
|
|
24620
|
+
console.log(import_picocolors18.default.dim(` - /anthropic/* (Anthropic)`));
|
|
24621
|
+
console.log(import_picocolors18.default.dim(` - /health (Health check)`));
|
|
24013
24622
|
console.log();
|
|
24014
|
-
console.log(
|
|
24623
|
+
console.log(import_picocolors18.default.dim("Press Ctrl+C to stop"));
|
|
24015
24624
|
}
|
|
24016
24625
|
async function cmdStartDaemon(config2) {
|
|
24017
24626
|
const defaultStatus = getProxyStatus("default");
|
|
24018
24627
|
if (defaultStatus.running) {
|
|
24019
|
-
console.log(
|
|
24628
|
+
console.log(import_picocolors18.default.yellow(`Default proxy already running on ${defaultStatus.host}:${defaultStatus.port}`));
|
|
24020
24629
|
return;
|
|
24021
24630
|
}
|
|
24022
|
-
console.log(
|
|
24631
|
+
console.log(import_picocolors18.default.cyan("Starting proxy server in background..."));
|
|
24023
24632
|
const args = [
|
|
24024
|
-
"run",
|
|
24025
|
-
"cli",
|
|
24026
24633
|
"proxy",
|
|
24027
24634
|
"start",
|
|
24028
24635
|
"--host",
|
|
@@ -24035,22 +24642,21 @@ async function cmdStartDaemon(config2) {
|
|
|
24035
24642
|
if (config2.groupName) {
|
|
24036
24643
|
args.push("--group", config2.groupName);
|
|
24037
24644
|
}
|
|
24038
|
-
const child = spawn3(
|
|
24645
|
+
const child = spawn3(process.execPath, [process.argv[1], ...args], {
|
|
24039
24646
|
detached: true,
|
|
24040
|
-
stdio: "ignore"
|
|
24041
|
-
cwd: process.cwd()
|
|
24647
|
+
stdio: "ignore"
|
|
24042
24648
|
});
|
|
24043
24649
|
child.unref();
|
|
24044
24650
|
const isHealthy = await waitForProxyHealth(config2.host, config2.port);
|
|
24045
24651
|
const hasRuntime = isHealthy ? await waitForProxyRuntime(config2.host, config2.port) : false;
|
|
24046
24652
|
if (isHealthy && hasRuntime) {
|
|
24047
|
-
console.log(
|
|
24653
|
+
console.log(import_picocolors18.default.green("\u2713 Proxy server started in background"));
|
|
24048
24654
|
console.log(` Instance: default (service)`);
|
|
24049
24655
|
console.log(` Address: ${config2.host}:${config2.port}`);
|
|
24050
|
-
console.log(
|
|
24051
|
-
console.log(
|
|
24656
|
+
console.log(import_picocolors18.default.dim(` Use "swixter proxy status" to check status`));
|
|
24657
|
+
console.log(import_picocolors18.default.dim(` Use "swixter proxy stop" to stop`));
|
|
24052
24658
|
} else {
|
|
24053
|
-
console.log(
|
|
24659
|
+
console.log(import_picocolors18.default.red("\u2717 Failed to start proxy server in background"));
|
|
24054
24660
|
process.exit(1);
|
|
24055
24661
|
}
|
|
24056
24662
|
}
|
|
@@ -24058,11 +24664,11 @@ async function cmdStop(args) {
|
|
|
24058
24664
|
const instanceId = args[0] || "default";
|
|
24059
24665
|
const status = getProxyStatus(instanceId);
|
|
24060
24666
|
if (!status.running) {
|
|
24061
|
-
console.log(
|
|
24667
|
+
console.log(import_picocolors18.default.yellow(`Proxy instance "${instanceId}" is not running`));
|
|
24062
24668
|
return;
|
|
24063
24669
|
}
|
|
24064
24670
|
await stopProxyServer(instanceId);
|
|
24065
|
-
console.log(
|
|
24671
|
+
console.log(import_picocolors18.default.green(`\u2713 Proxy instance "${instanceId}" stopped`));
|
|
24066
24672
|
}
|
|
24067
24673
|
async function cmdRun4(args) {
|
|
24068
24674
|
const doubleDash = args.indexOf("--");
|
|
@@ -24090,17 +24696,17 @@ async function cmdRun4(args) {
|
|
|
24090
24696
|
groupName = activeGroup?.name;
|
|
24091
24697
|
}
|
|
24092
24698
|
if (!groupName) {
|
|
24093
|
-
console.log(
|
|
24094
|
-
console.log(
|
|
24699
|
+
console.log(import_picocolors18.default.red("No group specified and no default group set"));
|
|
24700
|
+
console.log(import_picocolors18.default.dim("Use --group or create a default group first"));
|
|
24095
24701
|
return;
|
|
24096
24702
|
}
|
|
24097
24703
|
const group = await getGroup(groupName);
|
|
24098
24704
|
if (!group) {
|
|
24099
|
-
console.log(
|
|
24705
|
+
console.log(import_picocolors18.default.red(`Group "${groupName}" not found`));
|
|
24100
24706
|
process.exit(EXIT_CODES.notFound);
|
|
24101
24707
|
return;
|
|
24102
24708
|
}
|
|
24103
|
-
console.log(
|
|
24709
|
+
console.log(import_picocolors18.default.cyan("Starting proxy server..."));
|
|
24104
24710
|
const allInstances = listProxyInstances();
|
|
24105
24711
|
const runtimeBinding = resolveProxyRuntimeBinding({
|
|
24106
24712
|
groupName,
|
|
@@ -24119,15 +24725,15 @@ async function cmdRun4(args) {
|
|
|
24119
24725
|
}
|
|
24120
24726
|
const coder = coderArgs[0];
|
|
24121
24727
|
if (!coder) {
|
|
24122
|
-
console.log(
|
|
24123
|
-
console.log(
|
|
24728
|
+
console.log(import_picocolors18.default.red("Coder command required after --"));
|
|
24729
|
+
console.log(import_picocolors18.default.dim("Example: swixter proxy run -- claude"));
|
|
24124
24730
|
await stopProxyServer(instanceId);
|
|
24125
24731
|
return;
|
|
24126
24732
|
}
|
|
24127
24733
|
const env = buildCoderProxyEnv(coder, process.env, runtimeBinding.port);
|
|
24128
|
-
console.log(
|
|
24129
|
-
console.log(
|
|
24130
|
-
console.log(
|
|
24734
|
+
console.log(import_picocolors18.default.green(`\u2713 Running: ${coder} ${coderArgs.slice(1).join(" ")}`));
|
|
24735
|
+
console.log(import_picocolors18.default.dim(` Instance: ${instanceId} (run)`));
|
|
24736
|
+
console.log(import_picocolors18.default.dim(` Proxy: ${runtimeBinding.host}:${runtimeBinding.port}`));
|
|
24131
24737
|
if (coder === "claude") {
|
|
24132
24738
|
const firstProfile = group.profiles[0] ? await getProfile(group.profiles[0]) : null;
|
|
24133
24739
|
const proxyProfile = {
|
|
@@ -24162,21 +24768,21 @@ async function cmdRun4(args) {
|
|
|
24162
24768
|
process.exit(1);
|
|
24163
24769
|
});
|
|
24164
24770
|
}
|
|
24165
|
-
async function
|
|
24771
|
+
async function cmdStatus3() {
|
|
24166
24772
|
const instances = listProxyInstances();
|
|
24167
24773
|
console.log();
|
|
24168
|
-
console.log(
|
|
24774
|
+
console.log(import_picocolors18.default.bold("Proxy Status:"));
|
|
24169
24775
|
console.log();
|
|
24170
24776
|
const running = instances.filter((s) => s.running);
|
|
24171
24777
|
if (running.length === 0) {
|
|
24172
|
-
console.log(` ${
|
|
24778
|
+
console.log(` ${import_picocolors18.default.red("\u25CF")} No proxy instances running`);
|
|
24173
24779
|
console.log();
|
|
24174
|
-
console.log(
|
|
24780
|
+
console.log(import_picocolors18.default.dim(" Start with: swixter proxy start"));
|
|
24175
24781
|
return;
|
|
24176
24782
|
}
|
|
24177
24783
|
for (const status of running) {
|
|
24178
|
-
const typeLabel = status.type === "service" ?
|
|
24179
|
-
console.log(` ${
|
|
24784
|
+
const typeLabel = status.type === "service" ? import_picocolors18.default.cyan("service") : import_picocolors18.default.yellow("run");
|
|
24785
|
+
console.log(` ${import_picocolors18.default.green("\u25CF")} ${import_picocolors18.default.bold(status.instanceId)} (${typeLabel})`);
|
|
24180
24786
|
console.log(` Address: ${status.host}:${status.port}`);
|
|
24181
24787
|
console.log(` Group: ${status.groupName || "none"}`);
|
|
24182
24788
|
console.log(` Requests: ${status.requestCount} | Errors: ${status.errorCount}`);
|
|
@@ -24188,35 +24794,35 @@ async function cmdStatus() {
|
|
|
24188
24794
|
}
|
|
24189
24795
|
function proxyHelp() {
|
|
24190
24796
|
return `
|
|
24191
|
-
${
|
|
24192
|
-
|
|
24193
|
-
${
|
|
24194
|
-
${
|
|
24195
|
-
|
|
24196
|
-
${
|
|
24197
|
-
${
|
|
24198
|
-
${
|
|
24199
|
-
${
|
|
24200
|
-
${
|
|
24201
|
-
|
|
24202
|
-
${
|
|
24203
|
-
${
|
|
24204
|
-
${
|
|
24205
|
-
${
|
|
24206
|
-
${
|
|
24207
|
-
${
|
|
24208
|
-
|
|
24209
|
-
${
|
|
24210
|
-
${
|
|
24211
|
-
${
|
|
24212
|
-
${
|
|
24213
|
-
${
|
|
24214
|
-
${
|
|
24215
|
-
${
|
|
24216
|
-
${
|
|
24797
|
+
${import_picocolors18.default.bold("Swixter Proxy Commands")}
|
|
24798
|
+
|
|
24799
|
+
${import_picocolors18.default.bold("Usage:")}
|
|
24800
|
+
${import_picocolors18.default.green("swixter proxy <command> [options]")}
|
|
24801
|
+
|
|
24802
|
+
${import_picocolors18.default.bold("Commands:")}
|
|
24803
|
+
${import_picocolors18.default.cyan("start")} Start proxy server (default instance)
|
|
24804
|
+
${import_picocolors18.default.cyan("stop")} [instanceId] Stop proxy instance (default: "default")
|
|
24805
|
+
${import_picocolors18.default.cyan("run")} Start proxy and run coder with env vars
|
|
24806
|
+
${import_picocolors18.default.cyan("status")} Show all proxy instances
|
|
24807
|
+
|
|
24808
|
+
${import_picocolors18.default.bold("Options:")}
|
|
24809
|
+
${import_picocolors18.default.dim("--group <name>")} Use specified group
|
|
24810
|
+
${import_picocolors18.default.dim("--port <port>")} Proxy port (default: 15721)
|
|
24811
|
+
${import_picocolors18.default.dim("--host <host>")} Proxy host (default: 127.0.0.1)
|
|
24812
|
+
${import_picocolors18.default.dim("--timeout <ms>")} Request timeout in ms (default: 3000000)
|
|
24813
|
+
${import_picocolors18.default.dim("--daemon")} Run in background (detached)
|
|
24814
|
+
|
|
24815
|
+
${import_picocolors18.default.bold("Examples:")}
|
|
24816
|
+
${import_picocolors18.default.green("swixter proxy start")}
|
|
24817
|
+
${import_picocolors18.default.green("swixter proxy start --daemon")}
|
|
24818
|
+
${import_picocolors18.default.green("swixter proxy start --group my-group")}
|
|
24819
|
+
${import_picocolors18.default.green("swixter proxy run --group my-group -- claude")}
|
|
24820
|
+
${import_picocolors18.default.green("swixter proxy stop")}
|
|
24821
|
+
${import_picocolors18.default.green("swixter proxy stop run-15722")}
|
|
24822
|
+
${import_picocolors18.default.dim(" # Stop a specific run instance")}
|
|
24217
24823
|
`;
|
|
24218
24824
|
}
|
|
24219
|
-
var
|
|
24825
|
+
var import_picocolors18;
|
|
24220
24826
|
var init_proxy = __esm(() => {
|
|
24221
24827
|
init_manager();
|
|
24222
24828
|
init_claude2();
|
|
@@ -24224,12 +24830,12 @@ var init_proxy = __esm(() => {
|
|
|
24224
24830
|
init_formatting();
|
|
24225
24831
|
init_server();
|
|
24226
24832
|
init_manager2();
|
|
24227
|
-
|
|
24833
|
+
import_picocolors18 = __toESM(require_picocolors(), 1);
|
|
24228
24834
|
});
|
|
24229
24835
|
|
|
24230
24836
|
// src/cli/index.ts
|
|
24231
24837
|
init_claude2();
|
|
24232
|
-
var
|
|
24838
|
+
var import_picocolors19 = __toESM(require_picocolors(), 1);
|
|
24233
24839
|
|
|
24234
24840
|
// src/cli/qwen.ts
|
|
24235
24841
|
init_dist2();
|
|
@@ -27784,7 +28390,489 @@ async function showProvider(providerId) {
|
|
|
27784
28390
|
console.log();
|
|
27785
28391
|
}
|
|
27786
28392
|
|
|
28393
|
+
// src/cli/auth.ts
|
|
28394
|
+
init_dist2();
|
|
28395
|
+
init_client();
|
|
28396
|
+
init_token();
|
|
28397
|
+
init_manager();
|
|
28398
|
+
var import_picocolors16 = __toESM(require_picocolors(), 1);
|
|
28399
|
+
import * as readline from "readline";
|
|
28400
|
+
var MAGIC_LINK_POLL_INTERVAL_MS = 2000;
|
|
28401
|
+
var MAGIC_LINK_MAX_ATTEMPTS = 300;
|
|
28402
|
+
async function cmdRegister() {
|
|
28403
|
+
Ie(import_picocolors16.default.bold(import_picocolors16.default.cyan("Register Swixter Account")));
|
|
28404
|
+
const email3 = await he({
|
|
28405
|
+
message: "Email:",
|
|
28406
|
+
validate: (v2) => {
|
|
28407
|
+
if (!v2)
|
|
28408
|
+
return "Email is required";
|
|
28409
|
+
if (!v2.includes("@"))
|
|
28410
|
+
return "Invalid email format";
|
|
28411
|
+
}
|
|
28412
|
+
});
|
|
28413
|
+
if (pD(email3))
|
|
28414
|
+
return;
|
|
28415
|
+
const s = Y2();
|
|
28416
|
+
s.start("Sending verification code...");
|
|
28417
|
+
try {
|
|
28418
|
+
const sendResult = await sendVerificationCode(email3);
|
|
28419
|
+
s.stop(import_picocolors16.default.green(`\u2713 Verification code sent! (Expires in ${sendResult.expiresIn}s)`));
|
|
28420
|
+
} catch (err) {
|
|
28421
|
+
s.stop(import_picocolors16.default.red("\u2717 Failed to send verification code"));
|
|
28422
|
+
if (err.status === 409) {
|
|
28423
|
+
console.error(import_picocolors16.default.red("This email is already registered. Try logging in instead."));
|
|
28424
|
+
} else if (err.status === 429) {
|
|
28425
|
+
console.error(import_picocolors16.default.red(err.message || "Please wait before requesting a new code."));
|
|
28426
|
+
} else {
|
|
28427
|
+
console.error(import_picocolors16.default.red(err.message || "Unknown error"));
|
|
28428
|
+
}
|
|
28429
|
+
process.exit(1);
|
|
28430
|
+
}
|
|
28431
|
+
const code = await he({
|
|
28432
|
+
message: "Enter the 6-digit verification code sent to your email:",
|
|
28433
|
+
validate: (v2) => {
|
|
28434
|
+
if (!v2)
|
|
28435
|
+
return "Verification code is required";
|
|
28436
|
+
if (!/^\d{6}$/.test(v2))
|
|
28437
|
+
return "Please enter a 6-digit code";
|
|
28438
|
+
}
|
|
28439
|
+
});
|
|
28440
|
+
if (pD(code))
|
|
28441
|
+
return;
|
|
28442
|
+
const password = await ge({
|
|
28443
|
+
message: "Create password:",
|
|
28444
|
+
validate: (v2) => {
|
|
28445
|
+
if (!v2)
|
|
28446
|
+
return "Password is required";
|
|
28447
|
+
if (v2.length < 6)
|
|
28448
|
+
return "Password must be at least 6 characters";
|
|
28449
|
+
}
|
|
28450
|
+
});
|
|
28451
|
+
if (pD(password))
|
|
28452
|
+
return;
|
|
28453
|
+
const displayName = await he({
|
|
28454
|
+
message: "Display name (optional):"
|
|
28455
|
+
});
|
|
28456
|
+
if (pD(displayName))
|
|
28457
|
+
return;
|
|
28458
|
+
s.start("Creating account...");
|
|
28459
|
+
try {
|
|
28460
|
+
const result = await verifyAndRegister({
|
|
28461
|
+
email: email3,
|
|
28462
|
+
code,
|
|
28463
|
+
password,
|
|
28464
|
+
displayName
|
|
28465
|
+
});
|
|
28466
|
+
await persistAuth(result);
|
|
28467
|
+
s.stop(import_picocolors16.default.green("\u2713 Account created and logged in!"));
|
|
28468
|
+
const state = await loadAuthState();
|
|
28469
|
+
await setupEncryptionAfterAuth(state);
|
|
28470
|
+
Se(`Welcome, ${import_picocolors16.default.cyan(result.user.displayName || result.user.email)}!`);
|
|
28471
|
+
} catch (err) {
|
|
28472
|
+
s.stop(import_picocolors16.default.red("\u2717 Registration failed"));
|
|
28473
|
+
if (err.status === 401) {
|
|
28474
|
+
console.error(import_picocolors16.default.red(err.message || "Invalid or expired verification code."));
|
|
28475
|
+
} else if (err.status === 409) {
|
|
28476
|
+
console.error(import_picocolors16.default.red("This email is already registered."));
|
|
28477
|
+
} else {
|
|
28478
|
+
console.error(import_picocolors16.default.red(err.message || "Unknown error"));
|
|
28479
|
+
}
|
|
28480
|
+
process.exit(1);
|
|
28481
|
+
}
|
|
28482
|
+
}
|
|
28483
|
+
async function cmdLogin() {
|
|
28484
|
+
Ie(import_picocolors16.default.bold(import_picocolors16.default.cyan("Login to Swixter")));
|
|
28485
|
+
const email3 = await he({
|
|
28486
|
+
message: "Email:",
|
|
28487
|
+
validate: (v2) => {
|
|
28488
|
+
if (!v2)
|
|
28489
|
+
return "Email is required";
|
|
28490
|
+
if (!v2.includes("@"))
|
|
28491
|
+
return "Invalid email format";
|
|
28492
|
+
}
|
|
28493
|
+
});
|
|
28494
|
+
if (pD(email3))
|
|
28495
|
+
return;
|
|
28496
|
+
const password = await ge({
|
|
28497
|
+
message: "Password:",
|
|
28498
|
+
validate: (v2) => {
|
|
28499
|
+
if (!v2)
|
|
28500
|
+
return "Password is required";
|
|
28501
|
+
}
|
|
28502
|
+
});
|
|
28503
|
+
if (pD(password))
|
|
28504
|
+
return;
|
|
28505
|
+
const s = Y2();
|
|
28506
|
+
s.start("Logging in...");
|
|
28507
|
+
try {
|
|
28508
|
+
const result = await loginUser({
|
|
28509
|
+
email: email3,
|
|
28510
|
+
password
|
|
28511
|
+
});
|
|
28512
|
+
const userChanged = await persistAuth(result);
|
|
28513
|
+
s.stop(import_picocolors16.default.green("\u2713 Logged in successfully!"));
|
|
28514
|
+
const state = await loadAuthState();
|
|
28515
|
+
if (state && !state.encryptionKey) {
|
|
28516
|
+
await setupEncryptionAfterAuth(state);
|
|
28517
|
+
}
|
|
28518
|
+
if (userChanged) {
|
|
28519
|
+
await promptSyncChoice(state);
|
|
28520
|
+
return;
|
|
28521
|
+
}
|
|
28522
|
+
Se(`Welcome back, ${import_picocolors16.default.cyan(result.user.displayName || result.user.email)}!`);
|
|
28523
|
+
} catch (err) {
|
|
28524
|
+
s.stop(import_picocolors16.default.red("\u2717 Login failed"));
|
|
28525
|
+
console.error(import_picocolors16.default.red(err.message || "Invalid email or password"));
|
|
28526
|
+
process.exit(1);
|
|
28527
|
+
}
|
|
28528
|
+
}
|
|
28529
|
+
async function cmdLogout() {
|
|
28530
|
+
const state = await loadAuthState();
|
|
28531
|
+
if (state) {
|
|
28532
|
+
try {
|
|
28533
|
+
await logoutUser(state.refreshToken);
|
|
28534
|
+
} catch {}
|
|
28535
|
+
}
|
|
28536
|
+
await clearAuthState();
|
|
28537
|
+
await clearSyncMeta();
|
|
28538
|
+
console.log(import_picocolors16.default.green("\u2713 Logged out"));
|
|
28539
|
+
}
|
|
28540
|
+
async function cmdStatus2() {
|
|
28541
|
+
const loggedIn = await isLoggedIn();
|
|
28542
|
+
if (!loggedIn) {
|
|
28543
|
+
console.log(import_picocolors16.default.yellow("Not logged in"));
|
|
28544
|
+
console.log(import_picocolors16.default.dim("Run 'swixter auth login' to sign in"));
|
|
28545
|
+
return;
|
|
28546
|
+
}
|
|
28547
|
+
const state = await loadAuthState();
|
|
28548
|
+
if (state) {
|
|
28549
|
+
console.log(import_picocolors16.default.green("\u2713 Logged in"));
|
|
28550
|
+
console.log(` Email: ${import_picocolors16.default.cyan(state.email)}`);
|
|
28551
|
+
console.log(` User ID: ${import_picocolors16.default.dim(state.userId)}`);
|
|
28552
|
+
console.log(` Expires: ${import_picocolors16.default.dim(state.expiresAt)}`);
|
|
28553
|
+
}
|
|
28554
|
+
}
|
|
28555
|
+
async function cmdDeleteAccount() {
|
|
28556
|
+
const state = await loadAuthState();
|
|
28557
|
+
if (!state) {
|
|
28558
|
+
console.log(import_picocolors16.default.yellow("Not logged in"));
|
|
28559
|
+
return;
|
|
28560
|
+
}
|
|
28561
|
+
const confirmed = await ye({
|
|
28562
|
+
message: import_picocolors16.default.red("This will permanently delete your cloud account and all synced data. Continue?"),
|
|
28563
|
+
initialValue: false
|
|
28564
|
+
});
|
|
28565
|
+
if (pD(confirmed) || !confirmed) {
|
|
28566
|
+
console.log(import_picocolors16.default.dim("Cancelled"));
|
|
28567
|
+
return;
|
|
28568
|
+
}
|
|
28569
|
+
const s = Y2();
|
|
28570
|
+
s.start("Deleting account...");
|
|
28571
|
+
try {
|
|
28572
|
+
const token = await getAccessToken();
|
|
28573
|
+
if (!token) {
|
|
28574
|
+
s.stop(import_picocolors16.default.red("Session expired. Please log in again."));
|
|
28575
|
+
process.exit(1);
|
|
28576
|
+
}
|
|
28577
|
+
await deleteAccount(token);
|
|
28578
|
+
await clearAuthState();
|
|
28579
|
+
await clearSyncMeta();
|
|
28580
|
+
s.stop(import_picocolors16.default.green("\u2713 Account deleted"));
|
|
28581
|
+
} catch (err) {
|
|
28582
|
+
s.stop(import_picocolors16.default.red("\u2717 Failed to delete account"));
|
|
28583
|
+
console.error(import_picocolors16.default.red(err.message || "Unknown error"));
|
|
28584
|
+
process.exit(1);
|
|
28585
|
+
}
|
|
28586
|
+
}
|
|
28587
|
+
async function persistAuth(result) {
|
|
28588
|
+
const previousState = await loadAuthState();
|
|
28589
|
+
const userChanged = previousState != null && previousState.email !== result.user.email;
|
|
28590
|
+
await saveAuthState({
|
|
28591
|
+
accessToken: result.accessToken,
|
|
28592
|
+
refreshToken: result.refreshToken,
|
|
28593
|
+
expiresAt: result.expiresAt,
|
|
28594
|
+
encryptionSalt: result.encryptionSalt,
|
|
28595
|
+
authMethod: "password",
|
|
28596
|
+
userId: result.user.id,
|
|
28597
|
+
email: result.user.email
|
|
28598
|
+
});
|
|
28599
|
+
if (userChanged) {
|
|
28600
|
+
await clearSyncMeta();
|
|
28601
|
+
}
|
|
28602
|
+
return userChanged;
|
|
28603
|
+
}
|
|
28604
|
+
async function setupEncryptionAfterAuth(state) {
|
|
28605
|
+
if (!state)
|
|
28606
|
+
return;
|
|
28607
|
+
const setupEncryption = await ye({
|
|
28608
|
+
message: "Set up end-to-end encryption for cloud sync?",
|
|
28609
|
+
initialValue: true
|
|
28610
|
+
});
|
|
28611
|
+
if (pD(setupEncryption) || !setupEncryption) {
|
|
28612
|
+
return;
|
|
28613
|
+
}
|
|
28614
|
+
const masterPassword = await ge({
|
|
28615
|
+
message: "Create master password for encryption (separate from login password):",
|
|
28616
|
+
validate: (v2) => {
|
|
28617
|
+
if (!v2)
|
|
28618
|
+
return "Master password is required";
|
|
28619
|
+
if (v2.length < 8)
|
|
28620
|
+
return "Must be at least 8 characters";
|
|
28621
|
+
}
|
|
28622
|
+
});
|
|
28623
|
+
if (pD(masterPassword))
|
|
28624
|
+
return;
|
|
28625
|
+
const key = await deriveKey(masterPassword, state.encryptionSalt);
|
|
28626
|
+
const keyBase64 = await exportKeyToBase64(key);
|
|
28627
|
+
const remember = await ye({
|
|
28628
|
+
message: "Save encryption key locally for automatic sync? (Less secure but convenient)",
|
|
28629
|
+
initialValue: false
|
|
28630
|
+
});
|
|
28631
|
+
if (!pD(remember) && remember) {
|
|
28632
|
+
state.encryptionKey = keyBase64;
|
|
28633
|
+
await saveAuthState(state);
|
|
28634
|
+
console.log(import_picocolors16.default.dim("Encryption key saved for automatic sync"));
|
|
28635
|
+
}
|
|
28636
|
+
}
|
|
28637
|
+
async function promptSyncChoice(state) {
|
|
28638
|
+
if (!state?.encryptionKey) {
|
|
28639
|
+
console.log(import_picocolors16.default.dim("Cloud sync requires an encryption key. Run 'swixter sync push' after setting one up."));
|
|
28640
|
+
return;
|
|
28641
|
+
}
|
|
28642
|
+
const choice = await ve({
|
|
28643
|
+
message: "Different account detected. How would you like to handle cloud data?",
|
|
28644
|
+
options: [
|
|
28645
|
+
{ value: "pull", label: "Pull from cloud", hint: "Replace local profiles with cloud data" },
|
|
28646
|
+
{ value: "push", label: "Push to cloud", hint: "Upload local profiles to this account" },
|
|
28647
|
+
{ value: "skip", label: "Skip for now", hint: "No sync action" }
|
|
28648
|
+
]
|
|
28649
|
+
});
|
|
28650
|
+
if (pD(choice))
|
|
28651
|
+
return;
|
|
28652
|
+
if (choice === "pull") {
|
|
28653
|
+
const { handleSyncCommand: handleSyncCommand2 } = await Promise.resolve().then(() => (init_sync(), exports_sync));
|
|
28654
|
+
await handleSyncCommand2(["pull", "--force-remote"]);
|
|
28655
|
+
} else if (choice === "push") {
|
|
28656
|
+
const { handleSyncCommand: handleSyncCommand2 } = await Promise.resolve().then(() => (init_sync(), exports_sync));
|
|
28657
|
+
await handleSyncCommand2(["push", "--force-local"]);
|
|
28658
|
+
}
|
|
28659
|
+
}
|
|
28660
|
+
async function promptSetPassword(state, hasPassword) {
|
|
28661
|
+
if (!state)
|
|
28662
|
+
return;
|
|
28663
|
+
if (hasPassword)
|
|
28664
|
+
return;
|
|
28665
|
+
const setPw = await ye({
|
|
28666
|
+
message: "Set a login password for future sign-ins?",
|
|
28667
|
+
initialValue: true
|
|
28668
|
+
});
|
|
28669
|
+
if (pD(setPw) || !setPw)
|
|
28670
|
+
return;
|
|
28671
|
+
const password = await ge({
|
|
28672
|
+
message: "Create password:",
|
|
28673
|
+
validate: (v2) => {
|
|
28674
|
+
if (!v2)
|
|
28675
|
+
return "Password is required";
|
|
28676
|
+
if (v2.length < 6)
|
|
28677
|
+
return "Password must be at least 6 characters";
|
|
28678
|
+
}
|
|
28679
|
+
});
|
|
28680
|
+
if (pD(password))
|
|
28681
|
+
return;
|
|
28682
|
+
const s = Y2();
|
|
28683
|
+
s.start("Setting password...");
|
|
28684
|
+
try {
|
|
28685
|
+
await setPassword(state.accessToken, password);
|
|
28686
|
+
s.stop(import_picocolors16.default.green("\u2713 Password set! You can now log in with email + password."));
|
|
28687
|
+
} catch (err) {
|
|
28688
|
+
s.stop(import_picocolors16.default.red("\u2717 Failed to set password"));
|
|
28689
|
+
console.error(import_picocolors16.default.red(err.message || "Unknown error"));
|
|
28690
|
+
}
|
|
28691
|
+
}
|
|
28692
|
+
async function completeMagicLinkManual(email3) {
|
|
28693
|
+
const token = await he({
|
|
28694
|
+
message: "Enter the magic link token:",
|
|
28695
|
+
validate: (v2) => {
|
|
28696
|
+
if (!v2)
|
|
28697
|
+
return "Token is required";
|
|
28698
|
+
}
|
|
28699
|
+
});
|
|
28700
|
+
if (pD(token))
|
|
28701
|
+
return;
|
|
28702
|
+
const s = Y2();
|
|
28703
|
+
s.start("Verifying...");
|
|
28704
|
+
try {
|
|
28705
|
+
const result = await verifyMagicLink(email3, token);
|
|
28706
|
+
const userChanged = await persistAuth(result);
|
|
28707
|
+
const state = await loadAuthState();
|
|
28708
|
+
if (state && !state.encryptionKey) {
|
|
28709
|
+
s.stop(import_picocolors16.default.green("\u2713 Logged in!"));
|
|
28710
|
+
await setupEncryptionAfterAuth(state);
|
|
28711
|
+
} else {
|
|
28712
|
+
s.stop(import_picocolors16.default.green("\u2713 Logged in!"));
|
|
28713
|
+
}
|
|
28714
|
+
await promptSetPassword(state, !!result.hasPassword);
|
|
28715
|
+
if (userChanged)
|
|
28716
|
+
await promptSyncChoice(state);
|
|
28717
|
+
} catch (err) {
|
|
28718
|
+
s.stop(import_picocolors16.default.red("\u2717 Invalid or expired token"));
|
|
28719
|
+
console.error(import_picocolors16.default.red(err.message || "Unknown error"));
|
|
28720
|
+
process.exit(1);
|
|
28721
|
+
}
|
|
28722
|
+
}
|
|
28723
|
+
async function cmdMagicLinkLogin() {
|
|
28724
|
+
Ie(import_picocolors16.default.bold(import_picocolors16.default.cyan("Magic Link Login")));
|
|
28725
|
+
const email3 = await he({
|
|
28726
|
+
message: "Email:",
|
|
28727
|
+
validate: (v2) => {
|
|
28728
|
+
if (!v2)
|
|
28729
|
+
return "Email is required";
|
|
28730
|
+
if (!v2.includes("@"))
|
|
28731
|
+
return "Invalid email format";
|
|
28732
|
+
}
|
|
28733
|
+
});
|
|
28734
|
+
if (pD(email3))
|
|
28735
|
+
return;
|
|
28736
|
+
const s = Y2();
|
|
28737
|
+
s.start("Sending magic link...");
|
|
28738
|
+
let sessionId;
|
|
28739
|
+
try {
|
|
28740
|
+
const result = await sendMagicLink(email3);
|
|
28741
|
+
sessionId = result.sessionId;
|
|
28742
|
+
s.stop(import_picocolors16.default.green("\u2713 Magic link sent!"));
|
|
28743
|
+
} catch (err) {
|
|
28744
|
+
s.stop(import_picocolors16.default.red("\u2717 Failed to send magic link"));
|
|
28745
|
+
console.error(import_picocolors16.default.red(err.message || "Unknown error"));
|
|
28746
|
+
process.exit(1);
|
|
28747
|
+
}
|
|
28748
|
+
if (!sessionId) {
|
|
28749
|
+
await completeMagicLinkManual(email3);
|
|
28750
|
+
return;
|
|
28751
|
+
}
|
|
28752
|
+
console.log();
|
|
28753
|
+
console.log(import_picocolors16.default.dim("Check your email and click the magic link to log in."));
|
|
28754
|
+
console.log(import_picocolors16.default.dim("The CLI will detect it automatically. Press Enter to enter the token manually."));
|
|
28755
|
+
console.log();
|
|
28756
|
+
let shouldStop = false;
|
|
28757
|
+
let isManual = false;
|
|
28758
|
+
let authResult = null;
|
|
28759
|
+
let hasPassword = false;
|
|
28760
|
+
readline.emitKeypressEvents(process.stdin);
|
|
28761
|
+
const wasRaw = process.stdin.isTTY;
|
|
28762
|
+
if (wasRaw) {
|
|
28763
|
+
process.stdin.setRawMode(true);
|
|
28764
|
+
}
|
|
28765
|
+
const onKeypress = (_str, key) => {
|
|
28766
|
+
if (key.name === "return" || key.name === "enter") {
|
|
28767
|
+
shouldStop = true;
|
|
28768
|
+
isManual = true;
|
|
28769
|
+
}
|
|
28770
|
+
if (key.ctrl && key.name === "c") {
|
|
28771
|
+
cleanupStdin();
|
|
28772
|
+
process.exit(0);
|
|
28773
|
+
}
|
|
28774
|
+
};
|
|
28775
|
+
const cleanupStdin = () => {
|
|
28776
|
+
process.stdin.removeListener("keypress", onKeypress);
|
|
28777
|
+
if (wasRaw) {
|
|
28778
|
+
process.stdin.setRawMode(false);
|
|
28779
|
+
}
|
|
28780
|
+
};
|
|
28781
|
+
process.stdin.on("keypress", onKeypress);
|
|
28782
|
+
s.start("Waiting for browser confirmation...");
|
|
28783
|
+
try {
|
|
28784
|
+
const maxAttempts = MAGIC_LINK_MAX_ATTEMPTS;
|
|
28785
|
+
for (let i2 = 0;i2 < maxAttempts && !shouldStop; i2++) {
|
|
28786
|
+
await new Promise((resolve) => setTimeout(resolve, MAGIC_LINK_POLL_INTERVAL_MS));
|
|
28787
|
+
try {
|
|
28788
|
+
const session = await checkMagicLinkSession(sessionId);
|
|
28789
|
+
if (session.status === "completed" && session.accessToken) {
|
|
28790
|
+
if (!session.refreshToken || !session.expiresAt || !session.user || !session.encryptionSalt) {
|
|
28791
|
+
s.stop(import_picocolors16.default.red("\u2717 Incomplete session data from server"));
|
|
28792
|
+
process.exit(1);
|
|
28793
|
+
}
|
|
28794
|
+
authResult = {
|
|
28795
|
+
accessToken: session.accessToken,
|
|
28796
|
+
refreshToken: session.refreshToken,
|
|
28797
|
+
expiresAt: session.expiresAt,
|
|
28798
|
+
user: session.user,
|
|
28799
|
+
encryptionSalt: session.encryptionSalt
|
|
28800
|
+
};
|
|
28801
|
+
hasPassword = !!session.hasPassword;
|
|
28802
|
+
shouldStop = true;
|
|
28803
|
+
}
|
|
28804
|
+
} catch (err) {
|
|
28805
|
+
if (err.status === 404) {
|
|
28806
|
+
s.stop(import_picocolors16.default.red("\u2717 Session expired. Please try again."));
|
|
28807
|
+
process.exit(1);
|
|
28808
|
+
}
|
|
28809
|
+
}
|
|
28810
|
+
}
|
|
28811
|
+
} finally {
|
|
28812
|
+
s.stop();
|
|
28813
|
+
cleanupStdin();
|
|
28814
|
+
}
|
|
28815
|
+
if (authResult) {
|
|
28816
|
+
const userChanged = await persistAuth(authResult);
|
|
28817
|
+
const state = await loadAuthState();
|
|
28818
|
+
if (state && !state.encryptionKey) {
|
|
28819
|
+
await setupEncryptionAfterAuth(state);
|
|
28820
|
+
}
|
|
28821
|
+
await promptSetPassword(state, hasPassword);
|
|
28822
|
+
if (userChanged)
|
|
28823
|
+
await promptSyncChoice(state);
|
|
28824
|
+
Se(`Welcome back, ${import_picocolors16.default.cyan(authResult.user.displayName || authResult.user.email)}!`);
|
|
28825
|
+
return;
|
|
28826
|
+
}
|
|
28827
|
+
if (isManual) {
|
|
28828
|
+
console.log();
|
|
28829
|
+
await completeMagicLinkManual(email3);
|
|
28830
|
+
return;
|
|
28831
|
+
}
|
|
28832
|
+
console.log(import_picocolors16.default.red("\u2717 Timed out waiting for magic link confirmation."));
|
|
28833
|
+
console.log(import_picocolors16.default.dim("The magic link may have expired. Please try again."));
|
|
28834
|
+
process.exit(1);
|
|
28835
|
+
}
|
|
28836
|
+
async function handleAuthCommand(args) {
|
|
28837
|
+
const subcommand = args[0];
|
|
28838
|
+
switch (subcommand) {
|
|
28839
|
+
case "register":
|
|
28840
|
+
await cmdRegister();
|
|
28841
|
+
break;
|
|
28842
|
+
case "login": {
|
|
28843
|
+
if (args.includes("--magic-link")) {
|
|
28844
|
+
await cmdMagicLinkLogin();
|
|
28845
|
+
} else {
|
|
28846
|
+
await cmdLogin();
|
|
28847
|
+
}
|
|
28848
|
+
break;
|
|
28849
|
+
}
|
|
28850
|
+
case "logout":
|
|
28851
|
+
await cmdLogout();
|
|
28852
|
+
break;
|
|
28853
|
+
case "status":
|
|
28854
|
+
await cmdStatus2();
|
|
28855
|
+
break;
|
|
28856
|
+
case "delete-account":
|
|
28857
|
+
await cmdDeleteAccount();
|
|
28858
|
+
break;
|
|
28859
|
+
default:
|
|
28860
|
+
console.log(import_picocolors16.default.red(`Unknown auth subcommand: ${subcommand}`));
|
|
28861
|
+
console.log();
|
|
28862
|
+
console.log(import_picocolors16.default.bold("Available subcommands:"));
|
|
28863
|
+
console.log(` ${import_picocolors16.default.cyan("register")} - Create a new cloud account`);
|
|
28864
|
+
console.log(` ${import_picocolors16.default.cyan("login")} - Sign in to your account`);
|
|
28865
|
+
console.log(` ${import_picocolors16.default.cyan("login --magic-link")} - Sign in with a magic link`);
|
|
28866
|
+
console.log(` ${import_picocolors16.default.cyan("logout")} - Sign out`);
|
|
28867
|
+
console.log(` ${import_picocolors16.default.cyan("status")} - Check login status`);
|
|
28868
|
+
console.log(` ${import_picocolors16.default.cyan("delete-account")} - Delete your cloud account`);
|
|
28869
|
+
console.log();
|
|
28870
|
+
process.exit(1);
|
|
28871
|
+
}
|
|
28872
|
+
}
|
|
28873
|
+
|
|
27787
28874
|
// src/cli/index.ts
|
|
28875
|
+
init_sync();
|
|
27788
28876
|
init_meta();
|
|
27789
28877
|
init_versions2();
|
|
27790
28878
|
async function cmdProviders(subcommand, args) {
|
|
@@ -27831,104 +28919,104 @@ async function cmdProviders(subcommand, args) {
|
|
|
27831
28919
|
await showProvider(providerId);
|
|
27832
28920
|
return;
|
|
27833
28921
|
}
|
|
27834
|
-
console.log(
|
|
28922
|
+
console.log(import_picocolors19.default.red(`Unknown providers subcommand: ${subcommand}`));
|
|
27835
28923
|
console.log();
|
|
27836
|
-
console.log(
|
|
27837
|
-
console.log(` ${
|
|
27838
|
-
console.log(` ${
|
|
27839
|
-
console.log(` ${
|
|
27840
|
-
console.log(` ${
|
|
28924
|
+
console.log(import_picocolors19.default.bold("Available subcommands:"));
|
|
28925
|
+
console.log(` ${import_picocolors19.default.cyan("list, ls")} - List all providers`);
|
|
28926
|
+
console.log(` ${import_picocolors19.default.cyan("add, new")} - Add a custom provider`);
|
|
28927
|
+
console.log(` ${import_picocolors19.default.cyan("remove, rm, delete")} - Remove a custom provider`);
|
|
28928
|
+
console.log(` ${import_picocolors19.default.cyan("show, info")} - Show provider details`);
|
|
27841
28929
|
console.log();
|
|
27842
28930
|
process.exit(1);
|
|
27843
28931
|
}
|
|
27844
28932
|
async function cmdExport(filePath) {
|
|
27845
28933
|
if (!filePath) {
|
|
27846
|
-
console.log(
|
|
27847
|
-
console.log(
|
|
28934
|
+
console.log(import_picocolors19.default.red("Error: Please specify export file path"));
|
|
28935
|
+
console.log(import_picocolors19.default.dim("Usage: swixter export <file>"));
|
|
27848
28936
|
process.exit(1);
|
|
27849
28937
|
}
|
|
27850
28938
|
try {
|
|
27851
28939
|
await exportConfig(filePath, { sanitizeKeys: false });
|
|
27852
28940
|
console.log();
|
|
27853
|
-
console.log(
|
|
27854
|
-
console.log(` File: ${
|
|
28941
|
+
console.log(import_picocolors19.default.green("\u2713") + " Export successful!");
|
|
28942
|
+
console.log(` File: ${import_picocolors19.default.cyan(filePath)}`);
|
|
27855
28943
|
console.log();
|
|
27856
28944
|
} catch (error46) {
|
|
27857
28945
|
console.log();
|
|
27858
|
-
console.log(
|
|
28946
|
+
console.log(import_picocolors19.default.red(`\u2717 Export failed: ${error46}`));
|
|
27859
28947
|
console.log();
|
|
27860
28948
|
process.exit(1);
|
|
27861
28949
|
}
|
|
27862
28950
|
}
|
|
27863
28951
|
async function cmdCompletion(shell) {
|
|
27864
28952
|
if (!shell) {
|
|
27865
|
-
console.log(
|
|
28953
|
+
console.log(import_picocolors19.default.yellow("Please specify shell type"));
|
|
27866
28954
|
console.log();
|
|
27867
|
-
console.log(
|
|
27868
|
-
console.log(` ${
|
|
28955
|
+
console.log(import_picocolors19.default.bold("Usage:"));
|
|
28956
|
+
console.log(` ${import_picocolors19.default.green("swixter completion <shell>")}`);
|
|
27869
28957
|
console.log();
|
|
27870
|
-
console.log(
|
|
27871
|
-
console.log(` ${
|
|
27872
|
-
console.log(` ${
|
|
27873
|
-
console.log(` ${
|
|
28958
|
+
console.log(import_picocolors19.default.bold("Supported shells:"));
|
|
28959
|
+
console.log(` ${import_picocolors19.default.cyan("bash")} - Bash shell`);
|
|
28960
|
+
console.log(` ${import_picocolors19.default.cyan("zsh")} - Z shell`);
|
|
28961
|
+
console.log(` ${import_picocolors19.default.cyan("fish")} - Fish shell`);
|
|
27874
28962
|
console.log();
|
|
27875
|
-
console.log(
|
|
27876
|
-
console.log(` ${
|
|
27877
|
-
console.log(` ${
|
|
27878
|
-
console.log(` ${
|
|
28963
|
+
console.log(import_picocolors19.default.bold("Examples:"));
|
|
28964
|
+
console.log(` ${import_picocolors19.default.green("swixter completion bash > ~/.local/share/bash-completion/completions/swixter")}`);
|
|
28965
|
+
console.log(` ${import_picocolors19.default.green("swixter completion zsh > ~/.zfunc/_swixter")}`);
|
|
28966
|
+
console.log(` ${import_picocolors19.default.green("swixter completion fish > ~/.config/fish/completions/swixter.fish")}`);
|
|
27879
28967
|
process.exit(1);
|
|
27880
28968
|
}
|
|
27881
28969
|
const supportedShells = ["bash", "zsh", "fish"];
|
|
27882
28970
|
if (!supportedShells.includes(shell)) {
|
|
27883
|
-
console.log(
|
|
27884
|
-
console.log(
|
|
28971
|
+
console.log(import_picocolors19.default.red(`Unsupported shell: ${shell}`));
|
|
28972
|
+
console.log(import_picocolors19.default.dim(`Supported shells: ${supportedShells.join(", ")}`));
|
|
27885
28973
|
process.exit(1);
|
|
27886
28974
|
}
|
|
27887
28975
|
try {
|
|
27888
28976
|
const script = generateCompletion(shell);
|
|
27889
28977
|
console.log(script);
|
|
27890
28978
|
} catch (error46) {
|
|
27891
|
-
console.error(
|
|
28979
|
+
console.error(import_picocolors19.default.red("Failed to generate completion script:"), error46);
|
|
27892
28980
|
process.exit(1);
|
|
27893
28981
|
}
|
|
27894
28982
|
}
|
|
27895
28983
|
async function cmdImport(filePath) {
|
|
27896
28984
|
if (!filePath) {
|
|
27897
|
-
console.log(
|
|
27898
|
-
console.log(
|
|
28985
|
+
console.log(import_picocolors19.default.red("Error: Please specify import file path"));
|
|
28986
|
+
console.log(import_picocolors19.default.dim("Usage: swixter import <file>"));
|
|
27899
28987
|
process.exit(1);
|
|
27900
28988
|
}
|
|
27901
28989
|
try {
|
|
27902
28990
|
const result = await importConfig(filePath, { overwrite: false });
|
|
27903
28991
|
console.log();
|
|
27904
|
-
console.log(
|
|
28992
|
+
console.log(import_picocolors19.default.green("\u2713") + " Import completed!");
|
|
27905
28993
|
console.log();
|
|
27906
|
-
console.log(` Successfully imported: ${
|
|
27907
|
-
console.log(` Skipped: ${
|
|
27908
|
-
console.log(` Errors: ${
|
|
28994
|
+
console.log(` Successfully imported: ${import_picocolors19.default.green(result.imported)} items`);
|
|
28995
|
+
console.log(` Skipped: ${import_picocolors19.default.yellow(result.skipped)} items`);
|
|
28996
|
+
console.log(` Errors: ${import_picocolors19.default.red(result.errors.length)} items`);
|
|
27909
28997
|
console.log();
|
|
27910
28998
|
if (result.errors.length > 0) {
|
|
27911
|
-
console.log(
|
|
27912
|
-
result.errors.forEach((err) => console.log(
|
|
28999
|
+
console.log(import_picocolors19.default.red("Error details:"));
|
|
29000
|
+
result.errors.forEach((err) => console.log(import_picocolors19.default.red(` - ${err}`)));
|
|
27913
29001
|
console.log();
|
|
27914
29002
|
}
|
|
27915
29003
|
} catch (error46) {
|
|
27916
29004
|
console.log();
|
|
27917
|
-
console.log(
|
|
29005
|
+
console.log(import_picocolors19.default.red(`\u2717 Import failed: ${error46}`));
|
|
27918
29006
|
console.log();
|
|
27919
29007
|
process.exit(1);
|
|
27920
29008
|
}
|
|
27921
29009
|
}
|
|
27922
29010
|
async function cmdVersion() {
|
|
27923
29011
|
console.log();
|
|
27924
|
-
console.log(
|
|
29012
|
+
console.log(import_picocolors19.default.bold(import_picocolors19.default.cyan("Swixter")) + import_picocolors19.default.dim(" - AI Coder Configuration Manager"));
|
|
27925
29013
|
console.log();
|
|
27926
|
-
console.log(` ${
|
|
27927
|
-
console.log(` ${
|
|
27928
|
-
console.log(` ${
|
|
29014
|
+
console.log(` ${import_picocolors19.default.bold("Version:")} ${import_picocolors19.default.green(APP_VERSION)}`);
|
|
29015
|
+
console.log(` ${import_picocolors19.default.bold("Config Version:")} ${import_picocolors19.default.cyan(CONFIG_VERSION)}`);
|
|
29016
|
+
console.log(` ${import_picocolors19.default.bold("Export Version:")} ${import_picocolors19.default.cyan(EXPORT_VERSION)}`);
|
|
27929
29017
|
console.log();
|
|
27930
|
-
console.log(
|
|
27931
|
-
console.log(
|
|
29018
|
+
console.log(import_picocolors19.default.dim(" GitHub: https://github.com/dawnswwwww/swixter"));
|
|
29019
|
+
console.log(import_picocolors19.default.dim(" NPM: https://www.npmjs.com/package/swixter"));
|
|
27932
29020
|
console.log();
|
|
27933
29021
|
}
|
|
27934
29022
|
async function main() {
|
|
@@ -27965,6 +29053,14 @@ async function main() {
|
|
|
27965
29053
|
await handleCodexCommand(args.slice(1));
|
|
27966
29054
|
return;
|
|
27967
29055
|
}
|
|
29056
|
+
if (firstArg === "auth") {
|
|
29057
|
+
await handleAuthCommand(args.slice(1));
|
|
29058
|
+
return;
|
|
29059
|
+
}
|
|
29060
|
+
if (firstArg === "sync") {
|
|
29061
|
+
await handleSyncCommand(args.slice(1));
|
|
29062
|
+
return;
|
|
29063
|
+
}
|
|
27968
29064
|
if (firstArg === "providers") {
|
|
27969
29065
|
await cmdProviders(args[1], args.slice(2));
|
|
27970
29066
|
return;
|
|
@@ -27985,11 +29081,11 @@ async function main() {
|
|
|
27985
29081
|
await cmdVersion();
|
|
27986
29082
|
return;
|
|
27987
29083
|
}
|
|
27988
|
-
console.log(
|
|
27989
|
-
console.log(
|
|
29084
|
+
console.log(import_picocolors19.default.red(`Unknown command: ${firstArg}`));
|
|
29085
|
+
console.log(import_picocolors19.default.dim("Run 'swixter --help' for help"));
|
|
27990
29086
|
process.exit(1);
|
|
27991
29087
|
} catch (error46) {
|
|
27992
|
-
console.error(
|
|
29088
|
+
console.error(import_picocolors19.default.red("An error occurred:"), error46);
|
|
27993
29089
|
process.exit(1);
|
|
27994
29090
|
}
|
|
27995
29091
|
}
|