swixter 0.1.0 → 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 +247 -351
- package/dist/cli/index.js +1389 -248
- package/package.json +5 -6
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,17 +19091,19 @@ __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
|
-
import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
|
|
19052
|
-
import { dirname as dirname5 } from "path";
|
|
19105
|
+
import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile5, rename } from "fs/promises";
|
|
19106
|
+
import { dirname as dirname5, join as join4 } from "path";
|
|
19053
19107
|
function getConfigPath2() {
|
|
19054
19108
|
return process.env.SWIXTER_CONFIG_PATH || getConfigPath("swixter");
|
|
19055
19109
|
}
|
|
@@ -19102,11 +19156,18 @@ async function saveConfig(config2) {
|
|
|
19102
19156
|
try {
|
|
19103
19157
|
ConfigFileSchema.parse(config2);
|
|
19104
19158
|
const content = JSON.stringify(config2, null, SERIALIZATION.jsonIndent);
|
|
19105
|
-
|
|
19159
|
+
const tmpPath = join4(dirname5(configPath), `.config.tmp-${Date.now()}`);
|
|
19160
|
+
await writeFile5(tmpPath, content, "utf-8");
|
|
19161
|
+
await rename(tmpPath, configPath);
|
|
19106
19162
|
} catch (error46) {
|
|
19107
19163
|
throw new Error(`Failed to save configuration: ${error46}`);
|
|
19108
19164
|
}
|
|
19109
19165
|
}
|
|
19166
|
+
function markDirty(config2) {
|
|
19167
|
+
if (config2.syncMeta) {
|
|
19168
|
+
config2.syncMeta.dirty = true;
|
|
19169
|
+
}
|
|
19170
|
+
}
|
|
19110
19171
|
async function getActiveProfile() {
|
|
19111
19172
|
return getActiveProfileForCoder("claude");
|
|
19112
19173
|
}
|
|
@@ -19130,6 +19191,7 @@ async function setActiveProfileForCoder(coder, profileName) {
|
|
|
19130
19191
|
config2.coders[coder] = { activeProfile: "" };
|
|
19131
19192
|
}
|
|
19132
19193
|
config2.coders[coder].activeProfile = profileName;
|
|
19194
|
+
markDirty(config2);
|
|
19133
19195
|
await saveConfig(config2);
|
|
19134
19196
|
}
|
|
19135
19197
|
async function upsertProfile(profile, coder) {
|
|
@@ -19149,6 +19211,7 @@ async function upsertProfile(profile, coder) {
|
|
|
19149
19211
|
config2.coders[coder].activeProfile = profile.name;
|
|
19150
19212
|
}
|
|
19151
19213
|
}
|
|
19214
|
+
markDirty(config2);
|
|
19152
19215
|
await saveConfig(config2);
|
|
19153
19216
|
}
|
|
19154
19217
|
async function deleteProfile(profileName) {
|
|
@@ -19156,6 +19219,10 @@ async function deleteProfile(profileName) {
|
|
|
19156
19219
|
if (!config2.profiles[profileName]) {
|
|
19157
19220
|
throw new Error(`Profile "${profileName}" does not exist`);
|
|
19158
19221
|
}
|
|
19222
|
+
const referencingGroups = Object.values(config2.groups || {}).filter((group) => group.profiles.includes(profileName)).map((group) => group.name);
|
|
19223
|
+
if (referencingGroups.length > 0) {
|
|
19224
|
+
throw new Error(`Profile "${profileName}" is used in group(s): ${referencingGroups.join(", ")}. Remove it from the group(s) first.`);
|
|
19225
|
+
}
|
|
19159
19226
|
const allCoders = Object.keys(CODER_REGISTRY);
|
|
19160
19227
|
for (const coder of allCoders) {
|
|
19161
19228
|
try {
|
|
@@ -19168,10 +19235,10 @@ async function deleteProfile(profileName) {
|
|
|
19168
19235
|
delete config2.profiles[profileName];
|
|
19169
19236
|
for (const coder in config2.coders) {
|
|
19170
19237
|
if (config2.coders[coder].activeProfile === profileName) {
|
|
19171
|
-
|
|
19172
|
-
config2.coders[coder].activeProfile = remainingProfiles.length > 0 ? remainingProfiles[0] : "";
|
|
19238
|
+
config2.coders[coder].activeProfile = "";
|
|
19173
19239
|
}
|
|
19174
19240
|
}
|
|
19241
|
+
markDirty(config2);
|
|
19175
19242
|
await saveConfig(config2);
|
|
19176
19243
|
}
|
|
19177
19244
|
async function listProfiles() {
|
|
@@ -19200,8 +19267,16 @@ async function resetAllData() {
|
|
|
19200
19267
|
}
|
|
19201
19268
|
}
|
|
19202
19269
|
const defaultConfig = createDefaultConfig();
|
|
19270
|
+
markDirty(defaultConfig);
|
|
19203
19271
|
await saveConfig(defaultConfig);
|
|
19204
19272
|
}
|
|
19273
|
+
async function clearSyncMeta() {
|
|
19274
|
+
const config2 = await loadConfig();
|
|
19275
|
+
if (config2.syncMeta) {
|
|
19276
|
+
delete config2.syncMeta;
|
|
19277
|
+
await saveConfig(config2);
|
|
19278
|
+
}
|
|
19279
|
+
}
|
|
19205
19280
|
var init_manager = __esm(() => {
|
|
19206
19281
|
init_types2();
|
|
19207
19282
|
init_constants();
|
|
@@ -19424,13 +19499,15 @@ var init_commands2 = __esm(() => {
|
|
|
19424
19499
|
|
|
19425
19500
|
// src/utils/process.ts
|
|
19426
19501
|
import { spawn } from "child_process";
|
|
19502
|
+
import os from "os";
|
|
19427
19503
|
function spawnCLI(options) {
|
|
19428
19504
|
const { command, args, env, displayName, onExit } = options;
|
|
19429
19505
|
const finalEnv = env ? { ...process.env, ...env } : process.env;
|
|
19506
|
+
const isWin32 = os.platform() === "win32";
|
|
19430
19507
|
const child = spawn(command, args, {
|
|
19431
19508
|
env: finalEnv,
|
|
19432
19509
|
stdio: "inherit",
|
|
19433
|
-
shell:
|
|
19510
|
+
shell: isWin32
|
|
19434
19511
|
});
|
|
19435
19512
|
child.on("exit", async (code) => {
|
|
19436
19513
|
await onExit?.();
|
|
@@ -21949,7 +22026,7 @@ async function cmdCreateQuiet(params) {
|
|
|
21949
22026
|
console.log(import_picocolors8.default.dim("Usage: swixter claude create --quiet --name <name> --provider <id> [--api-key <key>] [--auth-token <token>] [--base-url <url>] [--anthropic-model <model>] [--default-haiku-model <model>] [--default-opus-model <model>] [--default-sonnet-model <model>] [--apply]"));
|
|
21950
22027
|
process.exit(1);
|
|
21951
22028
|
}
|
|
21952
|
-
const preset =
|
|
22029
|
+
const preset = await getPresetByIdAsync(params.provider);
|
|
21953
22030
|
if (!preset) {
|
|
21954
22031
|
console.log(import_picocolors8.default.red(`Error: Unknown provider ID: ${params.provider}`));
|
|
21955
22032
|
console.log(import_picocolors8.default.dim("Run 'swixter providers' to see all supported providers"));
|
|
@@ -22020,7 +22097,7 @@ async function cmdList() {
|
|
|
22020
22097
|
console.log(import_picocolors8.default.bold(LABELS.profileList));
|
|
22021
22098
|
console.log();
|
|
22022
22099
|
for (const profile of profiles) {
|
|
22023
|
-
const preset =
|
|
22100
|
+
const preset = await getPresetByIdAsync(profile.providerId);
|
|
22024
22101
|
const isCurrent = current?.name === profile.name;
|
|
22025
22102
|
const marker = isCurrent ? import_picocolors8.default.green(MARKERS.active) : import_picocolors8.default.dim(MARKERS.inactive);
|
|
22026
22103
|
const baseUrl = profile.baseURL || preset?.baseURL || MISC_DEFAULTS.baseUrlFallback;
|
|
@@ -22042,7 +22119,11 @@ async function cmdSwitch(profileName, args = []) {
|
|
|
22042
22119
|
try {
|
|
22043
22120
|
await setActiveProfileForCoder(CODER_NAME, profileName);
|
|
22044
22121
|
const profile = await getActiveProfileForCoder(CODER_NAME);
|
|
22045
|
-
|
|
22122
|
+
if (!profile) {
|
|
22123
|
+
console.log(import_picocolors8.default.red("Error: Profile not found after switch"));
|
|
22124
|
+
process.exit(1);
|
|
22125
|
+
}
|
|
22126
|
+
const preset = await getPresetByIdAsync(profile.providerId);
|
|
22046
22127
|
const baseUrl = profile.baseURL || preset?.baseURL || "Default";
|
|
22047
22128
|
console.log();
|
|
22048
22129
|
console.log(import_picocolors8.default.green("\u2713") + " Switched successfully!");
|
|
@@ -22093,10 +22174,13 @@ async function cmdEdit(profileName) {
|
|
|
22093
22174
|
}
|
|
22094
22175
|
const selected = await ve({
|
|
22095
22176
|
message: "Select profile to edit",
|
|
22096
|
-
options: profiles2.map((profile2) =>
|
|
22097
|
-
|
|
22098
|
-
|
|
22099
|
-
|
|
22177
|
+
options: await Promise.all(profiles2.map(async (profile2) => {
|
|
22178
|
+
const preset = await getPresetByIdAsync(profile2.providerId);
|
|
22179
|
+
return {
|
|
22180
|
+
value: profile2.name,
|
|
22181
|
+
label: profile2.name,
|
|
22182
|
+
hint: preset?.displayName || ""
|
|
22183
|
+
};
|
|
22100
22184
|
}))
|
|
22101
22185
|
});
|
|
22102
22186
|
if (pD(selected)) {
|
|
@@ -22117,7 +22201,7 @@ async function cmdEdit(profileName) {
|
|
|
22117
22201
|
console.log();
|
|
22118
22202
|
const { allPresets: allPresets2 } = await Promise.resolve().then(() => (init_presets(), exports_presets));
|
|
22119
22203
|
const presets = allPresets2;
|
|
22120
|
-
const currentPreset =
|
|
22204
|
+
const currentPreset = await getPresetByIdAsync(profile.providerId);
|
|
22121
22205
|
const shouldChangeProvider = await ye({
|
|
22122
22206
|
message: `Change provider? Current: ${currentPreset?.displayName}`,
|
|
22123
22207
|
initialValue: false
|
|
@@ -22288,7 +22372,7 @@ async function cmdApply() {
|
|
|
22288
22372
|
}
|
|
22289
22373
|
try {
|
|
22290
22374
|
const adapter = getAdapter(CODER_NAME);
|
|
22291
|
-
const preset =
|
|
22375
|
+
const preset = await getPresetByIdAsync(profile.providerId);
|
|
22292
22376
|
console.log();
|
|
22293
22377
|
console.log(import_picocolors8.default.dim(`Applying profile to ${adapter.configPath}...`));
|
|
22294
22378
|
await applyClaudeProfile(profile);
|
|
@@ -22318,7 +22402,7 @@ async function cmdCurrent() {
|
|
|
22318
22402
|
console.log(import_picocolors8.default.yellow("No active profile"));
|
|
22319
22403
|
return;
|
|
22320
22404
|
}
|
|
22321
|
-
const preset =
|
|
22405
|
+
const preset = await getPresetByIdAsync(profile.providerId);
|
|
22322
22406
|
const baseUrl = profile.baseURL || preset?.baseURL || "Default";
|
|
22323
22407
|
console.log();
|
|
22324
22408
|
console.log(import_picocolors8.default.bold("Current active profile:"));
|
|
@@ -22402,10 +22486,13 @@ async function cmdSwitchInteractive() {
|
|
|
22402
22486
|
const current = await getActiveProfileForCoder(CODER_NAME);
|
|
22403
22487
|
const profileName = await ve({
|
|
22404
22488
|
message: "Select profile to switch to",
|
|
22405
|
-
options: profiles.map((profile) =>
|
|
22406
|
-
|
|
22407
|
-
|
|
22408
|
-
|
|
22489
|
+
options: await Promise.all(profiles.map(async (profile) => {
|
|
22490
|
+
const preset = await getPresetByIdAsync(profile.providerId);
|
|
22491
|
+
return {
|
|
22492
|
+
value: profile.name,
|
|
22493
|
+
label: profile.name,
|
|
22494
|
+
hint: profile.name === current?.name ? "(current)" : preset?.displayName || ""
|
|
22495
|
+
};
|
|
22409
22496
|
}))
|
|
22410
22497
|
});
|
|
22411
22498
|
if (pD(profileName)) {
|
|
@@ -22422,10 +22509,13 @@ async function cmdDeleteInteractive() {
|
|
|
22422
22509
|
}
|
|
22423
22510
|
const profileName = await ve({
|
|
22424
22511
|
message: "Select profile to delete",
|
|
22425
|
-
options: profiles.map((profile) =>
|
|
22426
|
-
|
|
22427
|
-
|
|
22428
|
-
|
|
22512
|
+
options: await Promise.all(profiles.map(async (profile) => {
|
|
22513
|
+
const preset = await getPresetByIdAsync(profile.providerId);
|
|
22514
|
+
return {
|
|
22515
|
+
value: profile.name,
|
|
22516
|
+
label: profile.name,
|
|
22517
|
+
hint: preset?.displayName || ""
|
|
22518
|
+
};
|
|
22429
22519
|
}))
|
|
22430
22520
|
});
|
|
22431
22521
|
if (pD(profileName)) {
|
|
@@ -22500,7 +22590,7 @@ async function cmdRun(args) {
|
|
|
22500
22590
|
process.exit(1);
|
|
22501
22591
|
}
|
|
22502
22592
|
}
|
|
22503
|
-
const preset =
|
|
22593
|
+
const preset = await getPresetByIdAsync(profile.providerId);
|
|
22504
22594
|
const baseURL = profile.baseURL || preset?.baseURL || "";
|
|
22505
22595
|
const env = {};
|
|
22506
22596
|
for (const [key, value] of Object.entries(process.env)) {
|
|
@@ -22603,7 +22693,7 @@ class ProxyRouter {
|
|
|
22603
22693
|
|
|
22604
22694
|
// src/proxy/logger.ts
|
|
22605
22695
|
import { appendFileSync, existsSync as existsSync6, mkdirSync, renameSync, rmSync, statSync } from "fs";
|
|
22606
|
-
import { dirname as dirname6, join as
|
|
22696
|
+
import { dirname as dirname6, join as join6 } from "path";
|
|
22607
22697
|
function formatMeta(meta2) {
|
|
22608
22698
|
return meta2 ? { ...meta2 } : {};
|
|
22609
22699
|
}
|
|
@@ -22628,7 +22718,7 @@ function writeProxyLog(logPath, record2) {
|
|
|
22628
22718
|
} catch {}
|
|
22629
22719
|
}
|
|
22630
22720
|
function getProxyLogPath(instanceId) {
|
|
22631
|
-
return
|
|
22721
|
+
return join6(dirname6(getConfigPath2()), `proxy-${instanceId}.log`);
|
|
22632
22722
|
}
|
|
22633
22723
|
function createProxyLogger(instanceId) {
|
|
22634
22724
|
const logPath = getProxyLogPath(instanceId);
|
|
@@ -22748,9 +22838,6 @@ class CircuitBreaker {
|
|
|
22748
22838
|
}
|
|
22749
22839
|
isAvailable(profileId) {
|
|
22750
22840
|
const state = this.getState(profileId);
|
|
22751
|
-
if (state.state === "half_open") {
|
|
22752
|
-
return true;
|
|
22753
|
-
}
|
|
22754
22841
|
return !state.isOpen;
|
|
22755
22842
|
}
|
|
22756
22843
|
recordSuccess(profileId) {
|
|
@@ -22797,6 +22884,7 @@ class CircuitBreaker {
|
|
|
22797
22884
|
if (!state || state.state !== "open")
|
|
22798
22885
|
return;
|
|
22799
22886
|
state.state = "half_open";
|
|
22887
|
+
state.isOpen = false;
|
|
22800
22888
|
}
|
|
22801
22889
|
forceHalfOpen(profileId) {
|
|
22802
22890
|
const state = this.getOrCreateState(profileId);
|
|
@@ -23140,9 +23228,9 @@ var init_handler = __esm(() => {
|
|
|
23140
23228
|
|
|
23141
23229
|
// src/proxy/server.ts
|
|
23142
23230
|
import { existsSync as existsSync7, readFileSync, writeFileSync } from "fs";
|
|
23143
|
-
import { dirname as dirname7, join as
|
|
23231
|
+
import { dirname as dirname7, join as join7 } from "path";
|
|
23144
23232
|
function getRegistryPath() {
|
|
23145
|
-
return
|
|
23233
|
+
return join7(dirname7(getConfigPath2()), "proxy-instances.json");
|
|
23146
23234
|
}
|
|
23147
23235
|
function loadRegistry() {
|
|
23148
23236
|
const path = getRegistryPath();
|
|
@@ -23191,7 +23279,7 @@ function cleanStaleInstances() {
|
|
|
23191
23279
|
saveRegistry(registry2);
|
|
23192
23280
|
}
|
|
23193
23281
|
function migrateLegacyRuntime() {
|
|
23194
|
-
const legacyPath =
|
|
23282
|
+
const legacyPath = join7(dirname7(getConfigPath2()), "proxy-runtime.json");
|
|
23195
23283
|
if (!existsSync7(legacyPath))
|
|
23196
23284
|
return;
|
|
23197
23285
|
const registryPath = getRegistryPath();
|
|
@@ -23431,6 +23519,545 @@ var init_export = __esm(() => {
|
|
|
23431
23519
|
init_constants();
|
|
23432
23520
|
});
|
|
23433
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
|
+
|
|
23434
24061
|
// src/cli/group.ts
|
|
23435
24062
|
var exports_group = {};
|
|
23436
24063
|
__export(exports_group, {
|
|
@@ -23441,7 +24068,7 @@ function cancelAndExit() {
|
|
|
23441
24068
|
process.exit(EXIT_CODES.cancelled);
|
|
23442
24069
|
}
|
|
23443
24070
|
function exitWithError(message, exitCode = EXIT_CODES.generalError) {
|
|
23444
|
-
console.log(
|
|
24071
|
+
console.log(import_picocolors17.default.red(message));
|
|
23445
24072
|
process.exit(exitCode);
|
|
23446
24073
|
}
|
|
23447
24074
|
async function getExistingGroupNameSet() {
|
|
@@ -23515,7 +24142,7 @@ async function handleGroupCommand(args) {
|
|
|
23515
24142
|
await cmdShow(args.slice(1));
|
|
23516
24143
|
break;
|
|
23517
24144
|
default:
|
|
23518
|
-
console.log(
|
|
24145
|
+
console.log(import_picocolors17.default.red(`Unknown subcommand: ${subcommand}`));
|
|
23519
24146
|
console.log(groupHelp());
|
|
23520
24147
|
process.exit(EXIT_CODES.invalidArgument);
|
|
23521
24148
|
}
|
|
@@ -23523,15 +24150,15 @@ async function handleGroupCommand(args) {
|
|
|
23523
24150
|
async function cmdList4() {
|
|
23524
24151
|
const groups = await listGroups();
|
|
23525
24152
|
if (groups.length === 0) {
|
|
23526
|
-
console.log(
|
|
24153
|
+
console.log(import_picocolors17.default.yellow("No groups defined. Create one with: swixter group create"));
|
|
23527
24154
|
return;
|
|
23528
24155
|
}
|
|
23529
24156
|
console.log();
|
|
23530
|
-
console.log(
|
|
24157
|
+
console.log(import_picocolors17.default.bold("Groups:"));
|
|
23531
24158
|
console.log();
|
|
23532
24159
|
for (const group of groups) {
|
|
23533
|
-
const marker = group.isDefault ?
|
|
23534
|
-
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);
|
|
23535
24162
|
console.log(` ${marker} ${name} - ${group.profiles.length} profiles`);
|
|
23536
24163
|
}
|
|
23537
24164
|
console.log();
|
|
@@ -23572,9 +24199,9 @@ async function cmdCreate4(args) {
|
|
|
23572
24199
|
}
|
|
23573
24200
|
const group = await createGroup({ name, profiles });
|
|
23574
24201
|
console.log();
|
|
23575
|
-
console.log(
|
|
23576
|
-
console.log(
|
|
23577
|
-
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(", ")}`));
|
|
23578
24205
|
console.log();
|
|
23579
24206
|
}
|
|
23580
24207
|
async function promptForProfiles(initialSelectedProfiles = []) {
|
|
@@ -23612,7 +24239,7 @@ async function promptForProfiles(initialSelectedProfiles = []) {
|
|
|
23612
24239
|
return selectedProfiles;
|
|
23613
24240
|
}
|
|
23614
24241
|
console.log();
|
|
23615
|
-
console.log(
|
|
24242
|
+
console.log(import_picocolors17.default.dim("Set failover priority. Priority 1 is tried first."));
|
|
23616
24243
|
return await promptForProfileOrder(selectedProfiles);
|
|
23617
24244
|
}
|
|
23618
24245
|
async function promptForProfileOrder(selectedProfiles) {
|
|
@@ -23716,9 +24343,9 @@ async function cmdEdit4(args) {
|
|
|
23716
24343
|
exitWithError(`Failed to update group: ${group.name}`);
|
|
23717
24344
|
}
|
|
23718
24345
|
console.log();
|
|
23719
|
-
console.log(
|
|
23720
|
-
console.log(
|
|
23721
|
-
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(", ")}`));
|
|
23722
24349
|
console.log();
|
|
23723
24350
|
}
|
|
23724
24351
|
async function cmdDelete4(args) {
|
|
@@ -23744,7 +24371,7 @@ async function cmdDelete4(args) {
|
|
|
23744
24371
|
}
|
|
23745
24372
|
if (confirmed) {
|
|
23746
24373
|
await deleteGroup(group.id);
|
|
23747
|
-
console.log(
|
|
24374
|
+
console.log(import_picocolors17.default.green(`\u2713 Group "${group.name}" deleted`));
|
|
23748
24375
|
}
|
|
23749
24376
|
}
|
|
23750
24377
|
async function cmdSetDefault(args) {
|
|
@@ -23754,7 +24381,7 @@ async function cmdSetDefault(args) {
|
|
|
23754
24381
|
}
|
|
23755
24382
|
const group = await setDefaultGroup(name);
|
|
23756
24383
|
if (group) {
|
|
23757
|
-
console.log(
|
|
24384
|
+
console.log(import_picocolors17.default.green(`\u2713 "${group.name}" is now the default group`));
|
|
23758
24385
|
} else {
|
|
23759
24386
|
exitWithError(`Group not found: ${name}`, EXIT_CODES.notFound);
|
|
23760
24387
|
}
|
|
@@ -23769,37 +24396,37 @@ async function cmdShow(args) {
|
|
|
23769
24396
|
exitWithError(`Group not found: ${name}`, EXIT_CODES.notFound);
|
|
23770
24397
|
}
|
|
23771
24398
|
console.log();
|
|
23772
|
-
console.log(
|
|
23773
|
-
console.log(
|
|
23774
|
-
console.log(
|
|
23775
|
-
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:"));
|
|
23776
24403
|
group.profiles.forEach((p2, i2) => {
|
|
23777
|
-
console.log(
|
|
24404
|
+
console.log(import_picocolors17.default.dim(` ${i2 + 1}. ${p2}`));
|
|
23778
24405
|
});
|
|
23779
24406
|
console.log();
|
|
23780
24407
|
}
|
|
23781
24408
|
function groupHelp() {
|
|
23782
24409
|
return `
|
|
23783
|
-
${
|
|
23784
|
-
|
|
23785
|
-
${
|
|
23786
|
-
${
|
|
23787
|
-
|
|
23788
|
-
${
|
|
23789
|
-
${
|
|
23790
|
-
${
|
|
23791
|
-
${
|
|
23792
|
-
${
|
|
23793
|
-
${
|
|
23794
|
-
${
|
|
23795
|
-
|
|
23796
|
-
${
|
|
23797
|
-
${
|
|
23798
|
-
${
|
|
23799
|
-
${
|
|
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")}
|
|
23800
24427
|
`;
|
|
23801
24428
|
}
|
|
23802
|
-
var
|
|
24429
|
+
var import_picocolors17;
|
|
23803
24430
|
var init_group = __esm(() => {
|
|
23804
24431
|
init_dist2();
|
|
23805
24432
|
init_manager2();
|
|
@@ -23808,7 +24435,7 @@ var init_group = __esm(() => {
|
|
|
23808
24435
|
init_messages();
|
|
23809
24436
|
init_formatting();
|
|
23810
24437
|
init_validation();
|
|
23811
|
-
|
|
24438
|
+
import_picocolors17 = __toESM(require_picocolors(), 1);
|
|
23812
24439
|
});
|
|
23813
24440
|
|
|
23814
24441
|
// src/cli/proxy.ts
|
|
@@ -23908,13 +24535,13 @@ async function handleProxyCommand(args) {
|
|
|
23908
24535
|
await cmdRun4(args.slice(1));
|
|
23909
24536
|
break;
|
|
23910
24537
|
case "status":
|
|
23911
|
-
await
|
|
24538
|
+
await cmdStatus3();
|
|
23912
24539
|
break;
|
|
23913
24540
|
default:
|
|
23914
24541
|
if (!subcommand || subcommand === "status") {
|
|
23915
|
-
await
|
|
24542
|
+
await cmdStatus3();
|
|
23916
24543
|
} else {
|
|
23917
|
-
console.log(
|
|
24544
|
+
console.log(import_picocolors18.default.red(`Unknown subcommand: ${subcommand}`));
|
|
23918
24545
|
console.log(proxyHelp());
|
|
23919
24546
|
process.exit(1);
|
|
23920
24547
|
}
|
|
@@ -23946,21 +24573,21 @@ async function cmdStart(args) {
|
|
|
23946
24573
|
if (groupName) {
|
|
23947
24574
|
const group = await getGroup(groupName);
|
|
23948
24575
|
if (!group) {
|
|
23949
|
-
console.log(
|
|
24576
|
+
console.log(import_picocolors18.default.red(`Group "${groupName}" not found`));
|
|
23950
24577
|
process.exit(EXIT_CODES.notFound);
|
|
23951
24578
|
return;
|
|
23952
24579
|
}
|
|
23953
24580
|
}
|
|
23954
24581
|
const defaultStatus = getProxyStatus("default");
|
|
23955
24582
|
if (defaultStatus.running) {
|
|
23956
|
-
console.log(
|
|
24583
|
+
console.log(import_picocolors18.default.yellow(`Default proxy already running on ${defaultStatus.host}:${defaultStatus.port}`));
|
|
23957
24584
|
return;
|
|
23958
24585
|
}
|
|
23959
24586
|
if (!groupName) {
|
|
23960
24587
|
const activeGroup = await getActiveGroup();
|
|
23961
24588
|
if (activeGroup) {
|
|
23962
24589
|
groupName = activeGroup.name;
|
|
23963
|
-
console.log(
|
|
24590
|
+
console.log(import_picocolors18.default.dim(`Using default group: ${groupName}`));
|
|
23964
24591
|
}
|
|
23965
24592
|
}
|
|
23966
24593
|
const resolvedPort = port || DEFAULT_PROXY_PORT;
|
|
@@ -23971,7 +24598,7 @@ async function cmdStart(args) {
|
|
|
23971
24598
|
}
|
|
23972
24599
|
}
|
|
23973
24600
|
async function cmdStartBlocking(config2) {
|
|
23974
|
-
console.log(
|
|
24601
|
+
console.log(import_picocolors18.default.cyan("Starting proxy server..."));
|
|
23975
24602
|
await startProxyServer({
|
|
23976
24603
|
instanceId: "default",
|
|
23977
24604
|
type: "service",
|
|
@@ -23981,30 +24608,28 @@ async function cmdStartBlocking(config2) {
|
|
|
23981
24608
|
groupName: config2.groupName
|
|
23982
24609
|
});
|
|
23983
24610
|
console.log();
|
|
23984
|
-
console.log(
|
|
24611
|
+
console.log(import_picocolors18.default.green("\u2713 Proxy server started"));
|
|
23985
24612
|
console.log(` Instance: default (service)`);
|
|
23986
24613
|
console.log(` Address: ${config2.host}:${config2.port}`);
|
|
23987
24614
|
console.log(` Timeout: ${config2.timeout}ms`);
|
|
23988
|
-
console.log(
|
|
23989
|
-
console.log(
|
|
23990
|
-
console.log(
|
|
23991
|
-
console.log(
|
|
23992
|
-
console.log(
|
|
23993
|
-
console.log(
|
|
23994
|
-
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)`));
|
|
23995
24622
|
console.log();
|
|
23996
|
-
console.log(
|
|
24623
|
+
console.log(import_picocolors18.default.dim("Press Ctrl+C to stop"));
|
|
23997
24624
|
}
|
|
23998
24625
|
async function cmdStartDaemon(config2) {
|
|
23999
24626
|
const defaultStatus = getProxyStatus("default");
|
|
24000
24627
|
if (defaultStatus.running) {
|
|
24001
|
-
console.log(
|
|
24628
|
+
console.log(import_picocolors18.default.yellow(`Default proxy already running on ${defaultStatus.host}:${defaultStatus.port}`));
|
|
24002
24629
|
return;
|
|
24003
24630
|
}
|
|
24004
|
-
console.log(
|
|
24631
|
+
console.log(import_picocolors18.default.cyan("Starting proxy server in background..."));
|
|
24005
24632
|
const args = [
|
|
24006
|
-
"run",
|
|
24007
|
-
"cli",
|
|
24008
24633
|
"proxy",
|
|
24009
24634
|
"start",
|
|
24010
24635
|
"--host",
|
|
@@ -24017,22 +24642,21 @@ async function cmdStartDaemon(config2) {
|
|
|
24017
24642
|
if (config2.groupName) {
|
|
24018
24643
|
args.push("--group", config2.groupName);
|
|
24019
24644
|
}
|
|
24020
|
-
const child = spawn3(
|
|
24645
|
+
const child = spawn3(process.execPath, [process.argv[1], ...args], {
|
|
24021
24646
|
detached: true,
|
|
24022
|
-
stdio: "ignore"
|
|
24023
|
-
cwd: process.cwd()
|
|
24647
|
+
stdio: "ignore"
|
|
24024
24648
|
});
|
|
24025
24649
|
child.unref();
|
|
24026
24650
|
const isHealthy = await waitForProxyHealth(config2.host, config2.port);
|
|
24027
24651
|
const hasRuntime = isHealthy ? await waitForProxyRuntime(config2.host, config2.port) : false;
|
|
24028
24652
|
if (isHealthy && hasRuntime) {
|
|
24029
|
-
console.log(
|
|
24653
|
+
console.log(import_picocolors18.default.green("\u2713 Proxy server started in background"));
|
|
24030
24654
|
console.log(` Instance: default (service)`);
|
|
24031
24655
|
console.log(` Address: ${config2.host}:${config2.port}`);
|
|
24032
|
-
console.log(
|
|
24033
|
-
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`));
|
|
24034
24658
|
} else {
|
|
24035
|
-
console.log(
|
|
24659
|
+
console.log(import_picocolors18.default.red("\u2717 Failed to start proxy server in background"));
|
|
24036
24660
|
process.exit(1);
|
|
24037
24661
|
}
|
|
24038
24662
|
}
|
|
@@ -24040,11 +24664,11 @@ async function cmdStop(args) {
|
|
|
24040
24664
|
const instanceId = args[0] || "default";
|
|
24041
24665
|
const status = getProxyStatus(instanceId);
|
|
24042
24666
|
if (!status.running) {
|
|
24043
|
-
console.log(
|
|
24667
|
+
console.log(import_picocolors18.default.yellow(`Proxy instance "${instanceId}" is not running`));
|
|
24044
24668
|
return;
|
|
24045
24669
|
}
|
|
24046
24670
|
await stopProxyServer(instanceId);
|
|
24047
|
-
console.log(
|
|
24671
|
+
console.log(import_picocolors18.default.green(`\u2713 Proxy instance "${instanceId}" stopped`));
|
|
24048
24672
|
}
|
|
24049
24673
|
async function cmdRun4(args) {
|
|
24050
24674
|
const doubleDash = args.indexOf("--");
|
|
@@ -24072,17 +24696,17 @@ async function cmdRun4(args) {
|
|
|
24072
24696
|
groupName = activeGroup?.name;
|
|
24073
24697
|
}
|
|
24074
24698
|
if (!groupName) {
|
|
24075
|
-
console.log(
|
|
24076
|
-
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"));
|
|
24077
24701
|
return;
|
|
24078
24702
|
}
|
|
24079
24703
|
const group = await getGroup(groupName);
|
|
24080
24704
|
if (!group) {
|
|
24081
|
-
console.log(
|
|
24705
|
+
console.log(import_picocolors18.default.red(`Group "${groupName}" not found`));
|
|
24082
24706
|
process.exit(EXIT_CODES.notFound);
|
|
24083
24707
|
return;
|
|
24084
24708
|
}
|
|
24085
|
-
console.log(
|
|
24709
|
+
console.log(import_picocolors18.default.cyan("Starting proxy server..."));
|
|
24086
24710
|
const allInstances = listProxyInstances();
|
|
24087
24711
|
const runtimeBinding = resolveProxyRuntimeBinding({
|
|
24088
24712
|
groupName,
|
|
@@ -24101,15 +24725,15 @@ async function cmdRun4(args) {
|
|
|
24101
24725
|
}
|
|
24102
24726
|
const coder = coderArgs[0];
|
|
24103
24727
|
if (!coder) {
|
|
24104
|
-
console.log(
|
|
24105
|
-
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"));
|
|
24106
24730
|
await stopProxyServer(instanceId);
|
|
24107
24731
|
return;
|
|
24108
24732
|
}
|
|
24109
24733
|
const env = buildCoderProxyEnv(coder, process.env, runtimeBinding.port);
|
|
24110
|
-
console.log(
|
|
24111
|
-
console.log(
|
|
24112
|
-
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}`));
|
|
24113
24737
|
if (coder === "claude") {
|
|
24114
24738
|
const firstProfile = group.profiles[0] ? await getProfile(group.profiles[0]) : null;
|
|
24115
24739
|
const proxyProfile = {
|
|
@@ -24144,21 +24768,21 @@ async function cmdRun4(args) {
|
|
|
24144
24768
|
process.exit(1);
|
|
24145
24769
|
});
|
|
24146
24770
|
}
|
|
24147
|
-
async function
|
|
24771
|
+
async function cmdStatus3() {
|
|
24148
24772
|
const instances = listProxyInstances();
|
|
24149
24773
|
console.log();
|
|
24150
|
-
console.log(
|
|
24774
|
+
console.log(import_picocolors18.default.bold("Proxy Status:"));
|
|
24151
24775
|
console.log();
|
|
24152
24776
|
const running = instances.filter((s) => s.running);
|
|
24153
24777
|
if (running.length === 0) {
|
|
24154
|
-
console.log(` ${
|
|
24778
|
+
console.log(` ${import_picocolors18.default.red("\u25CF")} No proxy instances running`);
|
|
24155
24779
|
console.log();
|
|
24156
|
-
console.log(
|
|
24780
|
+
console.log(import_picocolors18.default.dim(" Start with: swixter proxy start"));
|
|
24157
24781
|
return;
|
|
24158
24782
|
}
|
|
24159
24783
|
for (const status of running) {
|
|
24160
|
-
const typeLabel = status.type === "service" ?
|
|
24161
|
-
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})`);
|
|
24162
24786
|
console.log(` Address: ${status.host}:${status.port}`);
|
|
24163
24787
|
console.log(` Group: ${status.groupName || "none"}`);
|
|
24164
24788
|
console.log(` Requests: ${status.requestCount} | Errors: ${status.errorCount}`);
|
|
@@ -24170,35 +24794,35 @@ async function cmdStatus() {
|
|
|
24170
24794
|
}
|
|
24171
24795
|
function proxyHelp() {
|
|
24172
24796
|
return `
|
|
24173
|
-
${
|
|
24174
|
-
|
|
24175
|
-
${
|
|
24176
|
-
${
|
|
24177
|
-
|
|
24178
|
-
${
|
|
24179
|
-
${
|
|
24180
|
-
${
|
|
24181
|
-
${
|
|
24182
|
-
${
|
|
24183
|
-
|
|
24184
|
-
${
|
|
24185
|
-
${
|
|
24186
|
-
${
|
|
24187
|
-
${
|
|
24188
|
-
${
|
|
24189
|
-
${
|
|
24190
|
-
|
|
24191
|
-
${
|
|
24192
|
-
${
|
|
24193
|
-
${
|
|
24194
|
-
${
|
|
24195
|
-
${
|
|
24196
|
-
${
|
|
24197
|
-
${
|
|
24198
|
-
${
|
|
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")}
|
|
24199
24823
|
`;
|
|
24200
24824
|
}
|
|
24201
|
-
var
|
|
24825
|
+
var import_picocolors18;
|
|
24202
24826
|
var init_proxy = __esm(() => {
|
|
24203
24827
|
init_manager();
|
|
24204
24828
|
init_claude2();
|
|
@@ -24206,12 +24830,12 @@ var init_proxy = __esm(() => {
|
|
|
24206
24830
|
init_formatting();
|
|
24207
24831
|
init_server();
|
|
24208
24832
|
init_manager2();
|
|
24209
|
-
|
|
24833
|
+
import_picocolors18 = __toESM(require_picocolors(), 1);
|
|
24210
24834
|
});
|
|
24211
24835
|
|
|
24212
24836
|
// src/cli/index.ts
|
|
24213
24837
|
init_claude2();
|
|
24214
|
-
var
|
|
24838
|
+
var import_picocolors19 = __toESM(require_picocolors(), 1);
|
|
24215
24839
|
|
|
24216
24840
|
// src/cli/qwen.ts
|
|
24217
24841
|
init_dist2();
|
|
@@ -24455,7 +25079,7 @@ async function cmdCreateQuiet2(params) {
|
|
|
24455
25079
|
console.log(import_picocolors9.default.dim("Usage: swixter qwen create --quiet --name <name> --provider <id> --model <model> [--api-key <key>] [--base-url <url>]"));
|
|
24456
25080
|
process.exit(1);
|
|
24457
25081
|
}
|
|
24458
|
-
const preset =
|
|
25082
|
+
const preset = await getPresetByIdAsync(params.provider);
|
|
24459
25083
|
if (!preset) {
|
|
24460
25084
|
console.log(import_picocolors9.default.red(`Error: Unknown provider ID: ${params.provider}`));
|
|
24461
25085
|
console.log(import_picocolors9.default.dim("Run 'swixter providers' to see all supported providers"));
|
|
@@ -24517,7 +25141,7 @@ async function cmdList2() {
|
|
|
24517
25141
|
console.log(import_picocolors9.default.bold(LABELS.profileList));
|
|
24518
25142
|
console.log();
|
|
24519
25143
|
for (const profile of profiles) {
|
|
24520
|
-
const preset =
|
|
25144
|
+
const preset = await getPresetByIdAsync(profile.providerId);
|
|
24521
25145
|
const isCurrent = current?.name === profile.name;
|
|
24522
25146
|
const marker = isCurrent ? import_picocolors9.default.green(MARKERS.active) : import_picocolors9.default.dim(MARKERS.inactive);
|
|
24523
25147
|
const baseUrl = profile.baseURL || preset?.baseURLChat || preset?.baseURL || MISC_DEFAULTS.baseUrlFallback;
|
|
@@ -24539,7 +25163,11 @@ async function cmdSwitch2(profileName, args = []) {
|
|
|
24539
25163
|
try {
|
|
24540
25164
|
await setActiveProfileForCoder(CODER_NAME2, profileName);
|
|
24541
25165
|
const profile = await getActiveProfileForCoder(CODER_NAME2);
|
|
24542
|
-
|
|
25166
|
+
if (!profile) {
|
|
25167
|
+
console.log(import_picocolors9.default.red("Error: Profile not found after switch"));
|
|
25168
|
+
process.exit(1);
|
|
25169
|
+
}
|
|
25170
|
+
const preset = await getPresetByIdAsync(profile.providerId);
|
|
24543
25171
|
const baseUrl = profile.baseURL || preset?.baseURLChat || preset?.baseURL || "Default";
|
|
24544
25172
|
console.log();
|
|
24545
25173
|
console.log(import_picocolors9.default.green("\u2713") + " Switched successfully!");
|
|
@@ -24590,10 +25218,13 @@ async function cmdEdit2(profileName) {
|
|
|
24590
25218
|
}
|
|
24591
25219
|
const selected = await ve({
|
|
24592
25220
|
message: "Select profile to edit",
|
|
24593
|
-
options: profiles2.map((profile2) =>
|
|
24594
|
-
|
|
24595
|
-
|
|
24596
|
-
|
|
25221
|
+
options: await Promise.all(profiles2.map(async (profile2) => {
|
|
25222
|
+
const preset = await getPresetByIdAsync(profile2.providerId);
|
|
25223
|
+
return {
|
|
25224
|
+
value: profile2.name,
|
|
25225
|
+
label: profile2.name,
|
|
25226
|
+
hint: preset?.displayName || ""
|
|
25227
|
+
};
|
|
24597
25228
|
}))
|
|
24598
25229
|
});
|
|
24599
25230
|
if (pD(selected)) {
|
|
@@ -24614,7 +25245,7 @@ async function cmdEdit2(profileName) {
|
|
|
24614
25245
|
console.log();
|
|
24615
25246
|
const { getProvidersByWireApi: getProvidersByWireApi2 } = await Promise.resolve().then(() => (init_presets(), exports_presets));
|
|
24616
25247
|
const presets = await getProvidersByWireApi2("chat");
|
|
24617
|
-
const currentPreset =
|
|
25248
|
+
const currentPreset = await getPresetByIdAsync(profile.providerId);
|
|
24618
25249
|
const shouldChangeProvider = await ye({
|
|
24619
25250
|
message: `Change provider? Current: ${currentPreset?.displayName}`,
|
|
24620
25251
|
initialValue: false
|
|
@@ -24730,7 +25361,7 @@ async function cmdApply2() {
|
|
|
24730
25361
|
}
|
|
24731
25362
|
try {
|
|
24732
25363
|
const adapter = getAdapter(CODER_NAME2);
|
|
24733
|
-
const preset =
|
|
25364
|
+
const preset = await getPresetByIdAsync(profile.providerId);
|
|
24734
25365
|
console.log();
|
|
24735
25366
|
console.log(import_picocolors9.default.dim(`Applying profile to ${adapter.configPath}...`));
|
|
24736
25367
|
await adapter.apply(profile);
|
|
@@ -24760,7 +25391,7 @@ async function cmdCurrent2() {
|
|
|
24760
25391
|
console.log(import_picocolors9.default.yellow("No active profile"));
|
|
24761
25392
|
return;
|
|
24762
25393
|
}
|
|
24763
|
-
const preset =
|
|
25394
|
+
const preset = await getPresetByIdAsync(profile.providerId);
|
|
24764
25395
|
const baseUrl = profile.baseURL || preset?.baseURLChat || preset?.baseURL || "Default";
|
|
24765
25396
|
console.log();
|
|
24766
25397
|
console.log(import_picocolors9.default.bold("Current active profile:"));
|
|
@@ -24844,10 +25475,13 @@ async function cmdSwitchInteractive2() {
|
|
|
24844
25475
|
const current = await getActiveProfileForCoder(CODER_NAME2);
|
|
24845
25476
|
const profileName = await ve({
|
|
24846
25477
|
message: "Select profile to switch to",
|
|
24847
|
-
options: profiles.map((profile) =>
|
|
24848
|
-
|
|
24849
|
-
|
|
24850
|
-
|
|
25478
|
+
options: await Promise.all(profiles.map(async (profile) => {
|
|
25479
|
+
const preset = await getPresetByIdAsync(profile.providerId);
|
|
25480
|
+
return {
|
|
25481
|
+
value: profile.name,
|
|
25482
|
+
label: profile.name,
|
|
25483
|
+
hint: profile.name === current?.name ? "(current)" : preset?.displayName || ""
|
|
25484
|
+
};
|
|
24851
25485
|
}))
|
|
24852
25486
|
});
|
|
24853
25487
|
if (pD(profileName)) {
|
|
@@ -24864,10 +25498,13 @@ async function cmdDeleteInteractive2() {
|
|
|
24864
25498
|
}
|
|
24865
25499
|
const profileName = await ve({
|
|
24866
25500
|
message: "Select profile to delete",
|
|
24867
|
-
options: profiles.map((profile) =>
|
|
24868
|
-
|
|
24869
|
-
|
|
24870
|
-
|
|
25501
|
+
options: await Promise.all(profiles.map(async (profile) => {
|
|
25502
|
+
const preset = await getPresetByIdAsync(profile.providerId);
|
|
25503
|
+
return {
|
|
25504
|
+
value: profile.name,
|
|
25505
|
+
label: profile.name,
|
|
25506
|
+
hint: preset?.displayName || ""
|
|
25507
|
+
};
|
|
24871
25508
|
}))
|
|
24872
25509
|
});
|
|
24873
25510
|
if (pD(profileName)) {
|
|
@@ -24908,7 +25545,7 @@ async function cmdRun2(args) {
|
|
|
24908
25545
|
process.exit(1);
|
|
24909
25546
|
}
|
|
24910
25547
|
}
|
|
24911
|
-
const preset =
|
|
25548
|
+
const preset = await getPresetByIdAsync(profile.providerId);
|
|
24912
25549
|
const baseURL = profile.baseURL || preset?.baseURLChat || preset?.baseURL || "";
|
|
24913
25550
|
const env = {};
|
|
24914
25551
|
for (const [key, value] of Object.entries(process.env)) {
|
|
@@ -25264,7 +25901,7 @@ async function cmdCreateQuiet3(params) {
|
|
|
25264
25901
|
console.log(import_picocolors10.default.dim(`Usage: swixter ${CODER_NAME3} create --quiet --name <name> --provider <id> [--api-key <key>] [--base-url <url>] [--model <model>] [--env-key <var>] [--apply]`));
|
|
25265
25902
|
process.exit(1);
|
|
25266
25903
|
}
|
|
25267
|
-
const preset =
|
|
25904
|
+
const preset = await getPresetByIdAsync(params.provider);
|
|
25268
25905
|
if (!preset) {
|
|
25269
25906
|
console.log(import_picocolors10.default.red(`Error: Unknown provider ID: ${params.provider}`));
|
|
25270
25907
|
console.log(import_picocolors10.default.dim("Run 'swixter providers' to see all supported providers"));
|
|
@@ -25337,7 +25974,7 @@ async function cmdList3() {
|
|
|
25337
25974
|
console.log(import_picocolors10.default.bold(LABELS.profileList));
|
|
25338
25975
|
console.log();
|
|
25339
25976
|
for (const profile of profiles) {
|
|
25340
|
-
const preset =
|
|
25977
|
+
const preset = await getPresetByIdAsync(profile.providerId);
|
|
25341
25978
|
const isCurrent = current?.name === profile.name;
|
|
25342
25979
|
const marker = isCurrent ? import_picocolors10.default.green(MARKERS.active) : import_picocolors10.default.dim(MARKERS.inactive);
|
|
25343
25980
|
const baseUrl = profile.baseURL || preset?.baseURLChat || preset?.baseURL || MISC_DEFAULTS.baseUrlFallback;
|
|
@@ -25359,7 +25996,11 @@ async function cmdSwitch3(profileName, args = []) {
|
|
|
25359
25996
|
try {
|
|
25360
25997
|
await setActiveProfileForCoder(CODER_NAME3, profileName);
|
|
25361
25998
|
const profile = await getActiveProfileForCoder(CODER_NAME3);
|
|
25362
|
-
|
|
25999
|
+
if (!profile) {
|
|
26000
|
+
console.log(import_picocolors10.default.red("Error: Profile not found after switch"));
|
|
26001
|
+
process.exit(1);
|
|
26002
|
+
}
|
|
26003
|
+
const preset = await getPresetByIdAsync(profile.providerId);
|
|
25363
26004
|
const baseUrl = profile.baseURL || preset?.baseURLChat || preset?.baseURL || "Default";
|
|
25364
26005
|
console.log();
|
|
25365
26006
|
console.log(import_picocolors10.default.green("\u2713") + " Switched successfully!");
|
|
@@ -25410,10 +26051,13 @@ async function cmdEdit3(profileName) {
|
|
|
25410
26051
|
}
|
|
25411
26052
|
const selected = await ve({
|
|
25412
26053
|
message: "Select profile to edit",
|
|
25413
|
-
options: profiles2.map((profile2) =>
|
|
25414
|
-
|
|
25415
|
-
|
|
25416
|
-
|
|
26054
|
+
options: await Promise.all(profiles2.map(async (profile2) => {
|
|
26055
|
+
const preset = await getPresetByIdAsync(profile2.providerId);
|
|
26056
|
+
return {
|
|
26057
|
+
value: profile2.name,
|
|
26058
|
+
label: profile2.name,
|
|
26059
|
+
hint: preset?.displayName || ""
|
|
26060
|
+
};
|
|
25417
26061
|
}))
|
|
25418
26062
|
});
|
|
25419
26063
|
if (pD(selected)) {
|
|
@@ -25434,7 +26078,7 @@ async function cmdEdit3(profileName) {
|
|
|
25434
26078
|
console.log();
|
|
25435
26079
|
const { getProvidersByWireApi: getProvidersByWireApi2 } = await Promise.resolve().then(() => (init_presets(), exports_presets));
|
|
25436
26080
|
const presets = await getProvidersByWireApi2("chat");
|
|
25437
|
-
const currentPreset =
|
|
26081
|
+
const currentPreset = await getPresetByIdAsync(profile.providerId);
|
|
25438
26082
|
const shouldChangeProvider = await ye({
|
|
25439
26083
|
message: `Change provider? Current: ${currentPreset?.displayName}`,
|
|
25440
26084
|
initialValue: false
|
|
@@ -25611,7 +26255,7 @@ async function cmdApply3() {
|
|
|
25611
26255
|
}
|
|
25612
26256
|
try {
|
|
25613
26257
|
const adapter = getAdapter(CODER_NAME3);
|
|
25614
|
-
const preset =
|
|
26258
|
+
const preset = await getPresetByIdAsync(profile.providerId);
|
|
25615
26259
|
console.log();
|
|
25616
26260
|
console.log(import_picocolors10.default.dim(`Applying profile to ${adapter.configPath}...`));
|
|
25617
26261
|
await adapter.apply(profile);
|
|
@@ -25654,7 +26298,7 @@ async function cmdCurrent3() {
|
|
|
25654
26298
|
console.log(import_picocolors10.default.yellow("No active profile"));
|
|
25655
26299
|
return;
|
|
25656
26300
|
}
|
|
25657
|
-
const preset =
|
|
26301
|
+
const preset = await getPresetByIdAsync(profile.providerId);
|
|
25658
26302
|
const baseUrl = profile.baseURL || preset?.baseURLChat || preset?.baseURL || "Default";
|
|
25659
26303
|
console.log();
|
|
25660
26304
|
console.log(import_picocolors10.default.bold("Current active profile:"));
|
|
@@ -25738,10 +26382,13 @@ async function cmdSwitchInteractive3() {
|
|
|
25738
26382
|
const current = await getActiveProfileForCoder(CODER_NAME3);
|
|
25739
26383
|
const profileName = await ve({
|
|
25740
26384
|
message: "Select profile to switch to",
|
|
25741
|
-
options: profiles.map((profile) =>
|
|
25742
|
-
|
|
25743
|
-
|
|
25744
|
-
|
|
26385
|
+
options: await Promise.all(profiles.map(async (profile) => {
|
|
26386
|
+
const preset = await getPresetByIdAsync(profile.providerId);
|
|
26387
|
+
return {
|
|
26388
|
+
value: profile.name,
|
|
26389
|
+
label: profile.name,
|
|
26390
|
+
hint: profile.name === current?.name ? "(current)" : preset?.displayName || ""
|
|
26391
|
+
};
|
|
25745
26392
|
}))
|
|
25746
26393
|
});
|
|
25747
26394
|
if (pD(profileName)) {
|
|
@@ -25758,10 +26405,13 @@ async function cmdDeleteInteractive3() {
|
|
|
25758
26405
|
}
|
|
25759
26406
|
const profileName = await ve({
|
|
25760
26407
|
message: "Select profile to delete",
|
|
25761
|
-
options: profiles.map((profile) =>
|
|
25762
|
-
|
|
25763
|
-
|
|
25764
|
-
|
|
26408
|
+
options: await Promise.all(profiles.map(async (profile) => {
|
|
26409
|
+
const preset = await getPresetByIdAsync(profile.providerId);
|
|
26410
|
+
return {
|
|
26411
|
+
value: profile.name,
|
|
26412
|
+
label: profile.name,
|
|
26413
|
+
hint: preset?.displayName || ""
|
|
26414
|
+
};
|
|
25765
26415
|
}))
|
|
25766
26416
|
});
|
|
25767
26417
|
if (pD(profileName)) {
|
|
@@ -25805,7 +26455,7 @@ async function cmdRun3(args) {
|
|
|
25805
26455
|
try {
|
|
25806
26456
|
const adapter = getAdapter(CODER_NAME3);
|
|
25807
26457
|
await adapter.apply(profile);
|
|
25808
|
-
const preset =
|
|
26458
|
+
const preset = await getPresetByIdAsync(profile.providerId);
|
|
25809
26459
|
const envKey = profile.envKey || preset?.env_key || "OPENAI_API_KEY";
|
|
25810
26460
|
const env = {};
|
|
25811
26461
|
for (const [key, value] of Object.entries(process.env)) {
|
|
@@ -25863,9 +26513,8 @@ var import_picocolors12 = __toESM(require_picocolors(), 1);
|
|
|
25863
26513
|
|
|
25864
26514
|
// src/server/index.ts
|
|
25865
26515
|
var import_picocolors11 = __toESM(require_picocolors(), 1);
|
|
25866
|
-
import { dirname as dirname9, join as
|
|
26516
|
+
import { dirname as dirname9, join as join9 } from "path";
|
|
25867
26517
|
import { fileURLToPath } from "url";
|
|
25868
|
-
import { exec } from "child_process";
|
|
25869
26518
|
|
|
25870
26519
|
// src/server/middleware.ts
|
|
25871
26520
|
function corsMiddleware(req, res, next) {
|
|
@@ -26150,7 +26799,7 @@ class NodeResShim {
|
|
|
26150
26799
|
}
|
|
26151
26800
|
|
|
26152
26801
|
// src/server/bun-static.ts
|
|
26153
|
-
import { extname, join as
|
|
26802
|
+
import { extname, join as join5 } from "path";
|
|
26154
26803
|
import { stat } from "fs/promises";
|
|
26155
26804
|
var MIME_TYPES = {
|
|
26156
26805
|
".html": "text/html; charset=utf-8",
|
|
@@ -26173,11 +26822,11 @@ var MIME_TYPES = {
|
|
|
26173
26822
|
async function serveStaticRequest(request, options) {
|
|
26174
26823
|
const { root, index = "index.html", spa = true } = options;
|
|
26175
26824
|
const url2 = new URL(request.url);
|
|
26176
|
-
let filePath =
|
|
26825
|
+
let filePath = join5(root, url2.pathname);
|
|
26177
26826
|
try {
|
|
26178
26827
|
const stats = await stat(filePath);
|
|
26179
26828
|
if (stats.isDirectory()) {
|
|
26180
|
-
filePath =
|
|
26829
|
+
filePath = join5(filePath, index);
|
|
26181
26830
|
}
|
|
26182
26831
|
const file2 = Bun.file(filePath);
|
|
26183
26832
|
const exists = await file2.exists();
|
|
@@ -26190,7 +26839,7 @@ async function serveStaticRequest(request, options) {
|
|
|
26190
26839
|
});
|
|
26191
26840
|
} catch {
|
|
26192
26841
|
if (spa) {
|
|
26193
|
-
const indexPath =
|
|
26842
|
+
const indexPath = join5(root, index);
|
|
26194
26843
|
const file2 = Bun.file(indexPath);
|
|
26195
26844
|
const exists = await file2.exists();
|
|
26196
26845
|
if (exists) {
|
|
@@ -26640,7 +27289,7 @@ init_paths();
|
|
|
26640
27289
|
init_export();
|
|
26641
27290
|
import { existsSync as existsSync9, statSync as statSync2 } from "fs";
|
|
26642
27291
|
import { readFile as readFile7, writeFile as writeFile7, unlink } from "fs/promises";
|
|
26643
|
-
import { join as
|
|
27292
|
+
import { join as join8 } from "path";
|
|
26644
27293
|
async function getVersion(req, res) {
|
|
26645
27294
|
sendJson(res, {
|
|
26646
27295
|
appVersion: APP_VERSION,
|
|
@@ -26692,7 +27341,7 @@ async function exportConfigFile(req, res) {
|
|
|
26692
27341
|
const sanitize = url2.searchParams.get("sanitize") === "true";
|
|
26693
27342
|
const { exportConfig: exportConfig3 } = await Promise.resolve().then(() => (init_export(), exports_export));
|
|
26694
27343
|
const tempDir = getConfigDir("swixter");
|
|
26695
|
-
const tempPath =
|
|
27344
|
+
const tempPath = join8(tempDir, `.export-${Date.now()}.json`);
|
|
26696
27345
|
try {
|
|
26697
27346
|
await exportConfig3(tempPath, { sanitizeKeys: sanitize });
|
|
26698
27347
|
const content = await readFile7(tempPath, "utf-8");
|
|
@@ -26717,7 +27366,7 @@ async function importConfigFile(req, res) {
|
|
|
26717
27366
|
}
|
|
26718
27367
|
try {
|
|
26719
27368
|
const tempDir = getConfigDir("swixter");
|
|
26720
|
-
const tempPath =
|
|
27369
|
+
const tempPath = join8(tempDir, `.import-${Date.now()}.json`);
|
|
26721
27370
|
await writeFile7(tempPath, JSON.stringify(body.config), "utf-8");
|
|
26722
27371
|
try {
|
|
26723
27372
|
const result = await importConfig(tempPath, { overwrite: body.overwrite !== false });
|
|
@@ -26968,18 +27617,20 @@ async function findAvailablePort(startPort = 3141) {
|
|
|
26968
27617
|
}
|
|
26969
27618
|
function openBrowser(url2) {
|
|
26970
27619
|
const command = process.platform === "win32" ? "start" : process.platform === "darwin" ? "open" : "xdg-open";
|
|
26971
|
-
|
|
26972
|
-
|
|
26973
|
-
|
|
26974
|
-
|
|
27620
|
+
import("child_process").then(({ execFile }) => {
|
|
27621
|
+
execFile(command, [url2], (error46) => {
|
|
27622
|
+
if (error46) {
|
|
27623
|
+
console.warn(import_picocolors11.default.yellow(`Could not open browser automatically: ${error46.message}`));
|
|
27624
|
+
}
|
|
27625
|
+
});
|
|
26975
27626
|
});
|
|
26976
27627
|
}
|
|
26977
27628
|
function getUiDir() {
|
|
26978
27629
|
const isDev = true;
|
|
26979
27630
|
if (isDev) {
|
|
26980
|
-
return
|
|
27631
|
+
return join9(__dirname2, "..", "..", "ui", "dist");
|
|
26981
27632
|
}
|
|
26982
|
-
return
|
|
27633
|
+
return join9(__dirname2, "..", "..", "ui");
|
|
26983
27634
|
}
|
|
26984
27635
|
async function startServer(portArg) {
|
|
26985
27636
|
const port = portArg || await findAvailablePort(3141);
|
|
@@ -27739,7 +28390,489 @@ async function showProvider(providerId) {
|
|
|
27739
28390
|
console.log();
|
|
27740
28391
|
}
|
|
27741
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
|
+
|
|
27742
28874
|
// src/cli/index.ts
|
|
28875
|
+
init_sync();
|
|
27743
28876
|
init_meta();
|
|
27744
28877
|
init_versions2();
|
|
27745
28878
|
async function cmdProviders(subcommand, args) {
|
|
@@ -27786,104 +28919,104 @@ async function cmdProviders(subcommand, args) {
|
|
|
27786
28919
|
await showProvider(providerId);
|
|
27787
28920
|
return;
|
|
27788
28921
|
}
|
|
27789
|
-
console.log(
|
|
28922
|
+
console.log(import_picocolors19.default.red(`Unknown providers subcommand: ${subcommand}`));
|
|
27790
28923
|
console.log();
|
|
27791
|
-
console.log(
|
|
27792
|
-
console.log(` ${
|
|
27793
|
-
console.log(` ${
|
|
27794
|
-
console.log(` ${
|
|
27795
|
-
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`);
|
|
27796
28929
|
console.log();
|
|
27797
28930
|
process.exit(1);
|
|
27798
28931
|
}
|
|
27799
28932
|
async function cmdExport(filePath) {
|
|
27800
28933
|
if (!filePath) {
|
|
27801
|
-
console.log(
|
|
27802
|
-
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>"));
|
|
27803
28936
|
process.exit(1);
|
|
27804
28937
|
}
|
|
27805
28938
|
try {
|
|
27806
28939
|
await exportConfig(filePath, { sanitizeKeys: false });
|
|
27807
28940
|
console.log();
|
|
27808
|
-
console.log(
|
|
27809
|
-
console.log(` File: ${
|
|
28941
|
+
console.log(import_picocolors19.default.green("\u2713") + " Export successful!");
|
|
28942
|
+
console.log(` File: ${import_picocolors19.default.cyan(filePath)}`);
|
|
27810
28943
|
console.log();
|
|
27811
28944
|
} catch (error46) {
|
|
27812
28945
|
console.log();
|
|
27813
|
-
console.log(
|
|
28946
|
+
console.log(import_picocolors19.default.red(`\u2717 Export failed: ${error46}`));
|
|
27814
28947
|
console.log();
|
|
27815
28948
|
process.exit(1);
|
|
27816
28949
|
}
|
|
27817
28950
|
}
|
|
27818
28951
|
async function cmdCompletion(shell) {
|
|
27819
28952
|
if (!shell) {
|
|
27820
|
-
console.log(
|
|
28953
|
+
console.log(import_picocolors19.default.yellow("Please specify shell type"));
|
|
27821
28954
|
console.log();
|
|
27822
|
-
console.log(
|
|
27823
|
-
console.log(` ${
|
|
28955
|
+
console.log(import_picocolors19.default.bold("Usage:"));
|
|
28956
|
+
console.log(` ${import_picocolors19.default.green("swixter completion <shell>")}`);
|
|
27824
28957
|
console.log();
|
|
27825
|
-
console.log(
|
|
27826
|
-
console.log(` ${
|
|
27827
|
-
console.log(` ${
|
|
27828
|
-
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`);
|
|
27829
28962
|
console.log();
|
|
27830
|
-
console.log(
|
|
27831
|
-
console.log(` ${
|
|
27832
|
-
console.log(` ${
|
|
27833
|
-
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")}`);
|
|
27834
28967
|
process.exit(1);
|
|
27835
28968
|
}
|
|
27836
28969
|
const supportedShells = ["bash", "zsh", "fish"];
|
|
27837
28970
|
if (!supportedShells.includes(shell)) {
|
|
27838
|
-
console.log(
|
|
27839
|
-
console.log(
|
|
28971
|
+
console.log(import_picocolors19.default.red(`Unsupported shell: ${shell}`));
|
|
28972
|
+
console.log(import_picocolors19.default.dim(`Supported shells: ${supportedShells.join(", ")}`));
|
|
27840
28973
|
process.exit(1);
|
|
27841
28974
|
}
|
|
27842
28975
|
try {
|
|
27843
28976
|
const script = generateCompletion(shell);
|
|
27844
28977
|
console.log(script);
|
|
27845
28978
|
} catch (error46) {
|
|
27846
|
-
console.error(
|
|
28979
|
+
console.error(import_picocolors19.default.red("Failed to generate completion script:"), error46);
|
|
27847
28980
|
process.exit(1);
|
|
27848
28981
|
}
|
|
27849
28982
|
}
|
|
27850
28983
|
async function cmdImport(filePath) {
|
|
27851
28984
|
if (!filePath) {
|
|
27852
|
-
console.log(
|
|
27853
|
-
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>"));
|
|
27854
28987
|
process.exit(1);
|
|
27855
28988
|
}
|
|
27856
28989
|
try {
|
|
27857
28990
|
const result = await importConfig(filePath, { overwrite: false });
|
|
27858
28991
|
console.log();
|
|
27859
|
-
console.log(
|
|
28992
|
+
console.log(import_picocolors19.default.green("\u2713") + " Import completed!");
|
|
27860
28993
|
console.log();
|
|
27861
|
-
console.log(` Successfully imported: ${
|
|
27862
|
-
console.log(` Skipped: ${
|
|
27863
|
-
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`);
|
|
27864
28997
|
console.log();
|
|
27865
28998
|
if (result.errors.length > 0) {
|
|
27866
|
-
console.log(
|
|
27867
|
-
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}`)));
|
|
27868
29001
|
console.log();
|
|
27869
29002
|
}
|
|
27870
29003
|
} catch (error46) {
|
|
27871
29004
|
console.log();
|
|
27872
|
-
console.log(
|
|
29005
|
+
console.log(import_picocolors19.default.red(`\u2717 Import failed: ${error46}`));
|
|
27873
29006
|
console.log();
|
|
27874
29007
|
process.exit(1);
|
|
27875
29008
|
}
|
|
27876
29009
|
}
|
|
27877
29010
|
async function cmdVersion() {
|
|
27878
29011
|
console.log();
|
|
27879
|
-
console.log(
|
|
29012
|
+
console.log(import_picocolors19.default.bold(import_picocolors19.default.cyan("Swixter")) + import_picocolors19.default.dim(" - AI Coder Configuration Manager"));
|
|
27880
29013
|
console.log();
|
|
27881
|
-
console.log(` ${
|
|
27882
|
-
console.log(` ${
|
|
27883
|
-
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)}`);
|
|
27884
29017
|
console.log();
|
|
27885
|
-
console.log(
|
|
27886
|
-
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"));
|
|
27887
29020
|
console.log();
|
|
27888
29021
|
}
|
|
27889
29022
|
async function main() {
|
|
@@ -27920,6 +29053,14 @@ async function main() {
|
|
|
27920
29053
|
await handleCodexCommand(args.slice(1));
|
|
27921
29054
|
return;
|
|
27922
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
|
+
}
|
|
27923
29064
|
if (firstArg === "providers") {
|
|
27924
29065
|
await cmdProviders(args[1], args.slice(2));
|
|
27925
29066
|
return;
|
|
@@ -27940,11 +29081,11 @@ async function main() {
|
|
|
27940
29081
|
await cmdVersion();
|
|
27941
29082
|
return;
|
|
27942
29083
|
}
|
|
27943
|
-
console.log(
|
|
27944
|
-
console.log(
|
|
29084
|
+
console.log(import_picocolors19.default.red(`Unknown command: ${firstArg}`));
|
|
29085
|
+
console.log(import_picocolors19.default.dim("Run 'swixter --help' for help"));
|
|
27945
29086
|
process.exit(1);
|
|
27946
29087
|
} catch (error46) {
|
|
27947
|
-
console.error(
|
|
29088
|
+
console.error(import_picocolors19.default.red("An error occurred:"), error46);
|
|
27948
29089
|
process.exit(1);
|
|
27949
29090
|
}
|
|
27950
29091
|
}
|