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.
Files changed (3) hide show
  1. package/README.md +247 -351
  2. package/dist/cli/index.js +1389 -248
  3. 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, U, K2, b2 = (t) => {
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
- U = u("\u25B2", "!");
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.0";
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
- await writeFile5(configPath, content, "utf-8");
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
- const remainingProfiles = Object.keys(config2.profiles);
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: true
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 = getPresetById(params.provider);
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 = getPresetById(profile.providerId);
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
- const preset = getPresetById(profile.providerId);
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
- value: profile2.name,
22098
- label: profile2.name,
22099
- hint: getPresetById(profile2.providerId)?.displayName || ""
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 = getPresetById(profile.providerId);
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 = getPresetById(profile.providerId);
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 = getPresetById(profile.providerId);
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
- value: profile.name,
22407
- label: profile.name,
22408
- hint: profile.name === current?.name ? "(current)" : getPresetById(profile.providerId)?.displayName || ""
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
- value: profile.name,
22427
- label: profile.name,
22428
- hint: getPresetById(profile.providerId)?.displayName || ""
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 = getPresetById(profile.providerId);
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 join5 } from "path";
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 join5(dirname6(getConfigPath2()), `proxy-${instanceId}.log`);
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 join6 } from "path";
23231
+ import { dirname as dirname7, join as join7 } from "path";
23144
23232
  function getRegistryPath() {
23145
- return join6(dirname7(getConfigPath2()), "proxy-instances.json");
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 = join6(dirname7(getConfigPath2()), "proxy-runtime.json");
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(import_picocolors15.default.red(message));
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(import_picocolors15.default.red(`Unknown subcommand: ${subcommand}`));
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(import_picocolors15.default.yellow("No groups defined. Create one with: swixter group create"));
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(import_picocolors15.default.bold("Groups:"));
24157
+ console.log(import_picocolors17.default.bold("Groups:"));
23531
24158
  console.log();
23532
24159
  for (const group of groups) {
23533
- const marker = group.isDefault ? import_picocolors15.default.green("\u2713") : " ";
23534
- const name = group.isDefault ? import_picocolors15.default.green(group.name) : import_picocolors15.default.cyan(group.name);
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(import_picocolors15.default.green(`\u2713 Group "${group.name}" created`));
23576
- console.log(import_picocolors15.default.dim(` ID: ${group.id}`));
23577
- console.log(import_picocolors15.default.dim(` Profiles: ${group.profiles.join(", ")}`));
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(import_picocolors15.default.dim("Set failover priority. Priority 1 is tried first."));
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(import_picocolors15.default.green(`\u2713 Group "${updated.name}" updated`));
23720
- console.log(import_picocolors15.default.dim(` ID: ${updated.id}`));
23721
- console.log(import_picocolors15.default.dim(` Profiles: ${updated.profiles.join(", ")}`));
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(import_picocolors15.default.green(`\u2713 Group "${group.name}" deleted`));
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(import_picocolors15.default.green(`\u2713 "${group.name}" is now the default group`));
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(import_picocolors15.default.bold("Group: ") + import_picocolors15.default.cyan(group.name));
23773
- console.log(import_picocolors15.default.bold("ID: ") + group.id);
23774
- console.log(import_picocolors15.default.bold("Default: ") + (group.isDefault ? import_picocolors15.default.green("yes") : import_picocolors15.default.dim("no")));
23775
- console.log(import_picocolors15.default.bold("Profiles:"));
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(import_picocolors15.default.dim(` ${i2 + 1}. ${p2}`));
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
- ${import_picocolors15.default.bold("Swixter Group Commands")}
23784
-
23785
- ${import_picocolors15.default.bold("Usage:")}
23786
- ${import_picocolors15.default.green("swixter group <command> [options]")}
23787
-
23788
- ${import_picocolors15.default.bold("Commands:")}
23789
- ${import_picocolors15.default.cyan("list, ls")} List all groups
23790
- ${import_picocolors15.default.cyan("create, new")} Create a new group
23791
- ${import_picocolors15.default.cyan("edit")} Edit a group
23792
- ${import_picocolors15.default.cyan("delete, rm")} Delete a group
23793
- ${import_picocolors15.default.cyan("set-default")} Set default group
23794
- ${import_picocolors15.default.cyan("show, info")} Show group details
23795
-
23796
- ${import_picocolors15.default.bold("Examples:")}
23797
- ${import_picocolors15.default.green("swixter group list")}
23798
- ${import_picocolors15.default.green("swixter group create my-group --profiles profile-a,profile-b")}
23799
- ${import_picocolors15.default.green("swixter group set-default my-group")}
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 import_picocolors15;
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
- import_picocolors15 = __toESM(require_picocolors(), 1);
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 cmdStatus();
24538
+ await cmdStatus3();
23912
24539
  break;
23913
24540
  default:
23914
24541
  if (!subcommand || subcommand === "status") {
23915
- await cmdStatus();
24542
+ await cmdStatus3();
23916
24543
  } else {
23917
- console.log(import_picocolors16.default.red(`Unknown subcommand: ${subcommand}`));
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(import_picocolors16.default.red(`Group "${groupName}" not found`));
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(import_picocolors16.default.yellow(`Default proxy already running on ${defaultStatus.host}:${defaultStatus.port}`));
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(import_picocolors16.default.dim(`Using default group: ${groupName}`));
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(import_picocolors16.default.cyan("Starting proxy server..."));
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(import_picocolors16.default.green("\u2713 Proxy server started"));
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(import_picocolors16.default.dim(` Group: ${config2.groupName || "none"}`));
23989
- console.log(import_picocolors16.default.dim(` Endpoints:`));
23990
- console.log(import_picocolors16.default.dim(` - /v1/chat/completions (OpenAI)`));
23991
- console.log(import_picocolors16.default.dim(` - /v1/messages (Anthropic)`));
23992
- console.log(import_picocolors16.default.dim(` - /v1/responses (Anthropic)`));
23993
- console.log(import_picocolors16.default.dim(` - /anthropic/* (Anthropic)`));
23994
- console.log(import_picocolors16.default.dim(` - /health (Health check)`));
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(import_picocolors16.default.dim("Press Ctrl+C to stop"));
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(import_picocolors16.default.yellow(`Default proxy already running on ${defaultStatus.host}:${defaultStatus.port}`));
24628
+ console.log(import_picocolors18.default.yellow(`Default proxy already running on ${defaultStatus.host}:${defaultStatus.port}`));
24002
24629
  return;
24003
24630
  }
24004
- console.log(import_picocolors16.default.cyan("Starting proxy server in background..."));
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("bun", args, {
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(import_picocolors16.default.green("\u2713 Proxy server started in background"));
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(import_picocolors16.default.dim(` Use "swixter proxy status" to check status`));
24033
- console.log(import_picocolors16.default.dim(` Use "swixter proxy stop" to stop`));
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(import_picocolors16.default.red("\u2717 Failed to start proxy server in background"));
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(import_picocolors16.default.yellow(`Proxy instance "${instanceId}" is not running`));
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(import_picocolors16.default.green(`\u2713 Proxy instance "${instanceId}" stopped`));
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(import_picocolors16.default.red("No group specified and no default group set"));
24076
- console.log(import_picocolors16.default.dim("Use --group or create a default group first"));
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(import_picocolors16.default.red(`Group "${groupName}" not found`));
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(import_picocolors16.default.cyan("Starting proxy server..."));
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(import_picocolors16.default.red("Coder command required after --"));
24105
- console.log(import_picocolors16.default.dim("Example: swixter proxy run -- claude"));
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(import_picocolors16.default.green(`\u2713 Running: ${coder} ${coderArgs.slice(1).join(" ")}`));
24111
- console.log(import_picocolors16.default.dim(` Instance: ${instanceId} (run)`));
24112
- console.log(import_picocolors16.default.dim(` Proxy: ${runtimeBinding.host}:${runtimeBinding.port}`));
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 cmdStatus() {
24771
+ async function cmdStatus3() {
24148
24772
  const instances = listProxyInstances();
24149
24773
  console.log();
24150
- console.log(import_picocolors16.default.bold("Proxy Status:"));
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(` ${import_picocolors16.default.red("\u25CF")} No proxy instances running`);
24778
+ console.log(` ${import_picocolors18.default.red("\u25CF")} No proxy instances running`);
24155
24779
  console.log();
24156
- console.log(import_picocolors16.default.dim(" Start with: swixter proxy start"));
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" ? import_picocolors16.default.cyan("service") : import_picocolors16.default.yellow("run");
24161
- console.log(` ${import_picocolors16.default.green("\u25CF")} ${import_picocolors16.default.bold(status.instanceId)} (${typeLabel})`);
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
- ${import_picocolors16.default.bold("Swixter Proxy Commands")}
24174
-
24175
- ${import_picocolors16.default.bold("Usage:")}
24176
- ${import_picocolors16.default.green("swixter proxy <command> [options]")}
24177
-
24178
- ${import_picocolors16.default.bold("Commands:")}
24179
- ${import_picocolors16.default.cyan("start")} Start proxy server (default instance)
24180
- ${import_picocolors16.default.cyan("stop")} [instanceId] Stop proxy instance (default: "default")
24181
- ${import_picocolors16.default.cyan("run")} Start proxy and run coder with env vars
24182
- ${import_picocolors16.default.cyan("status")} Show all proxy instances
24183
-
24184
- ${import_picocolors16.default.bold("Options:")}
24185
- ${import_picocolors16.default.dim("--group <name>")} Use specified group
24186
- ${import_picocolors16.default.dim("--port <port>")} Proxy port (default: 15721)
24187
- ${import_picocolors16.default.dim("--host <host>")} Proxy host (default: 127.0.0.1)
24188
- ${import_picocolors16.default.dim("--timeout <ms>")} Request timeout in ms (default: 3000000)
24189
- ${import_picocolors16.default.dim("--daemon")} Run in background (detached)
24190
-
24191
- ${import_picocolors16.default.bold("Examples:")}
24192
- ${import_picocolors16.default.green("swixter proxy start")}
24193
- ${import_picocolors16.default.green("swixter proxy start --daemon")}
24194
- ${import_picocolors16.default.green("swixter proxy start --group my-group")}
24195
- ${import_picocolors16.default.green("swixter proxy run --group my-group -- claude")}
24196
- ${import_picocolors16.default.green("swixter proxy stop")}
24197
- ${import_picocolors16.default.green("swixter proxy stop run-15722")}
24198
- ${import_picocolors16.default.dim(" # Stop a specific run instance")}
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 import_picocolors16;
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
- import_picocolors16 = __toESM(require_picocolors(), 1);
24833
+ import_picocolors18 = __toESM(require_picocolors(), 1);
24210
24834
  });
24211
24835
 
24212
24836
  // src/cli/index.ts
24213
24837
  init_claude2();
24214
- var import_picocolors17 = __toESM(require_picocolors(), 1);
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 = getPresetById(params.provider);
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 = getPresetById(profile.providerId);
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
- const preset = getPresetById(profile.providerId);
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
- value: profile2.name,
24595
- label: profile2.name,
24596
- hint: getPresetById(profile2.providerId)?.displayName || ""
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 = getPresetById(profile.providerId);
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 = getPresetById(profile.providerId);
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 = getPresetById(profile.providerId);
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
- value: profile.name,
24849
- label: profile.name,
24850
- hint: profile.name === current?.name ? "(current)" : getPresetById(profile.providerId)?.displayName || ""
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
- value: profile.name,
24869
- label: profile.name,
24870
- hint: getPresetById(profile.providerId)?.displayName || ""
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 = getPresetById(profile.providerId);
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 = getPresetById(params.provider);
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 = getPresetById(profile.providerId);
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
- const preset = getPresetById(profile.providerId);
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
- value: profile2.name,
25415
- label: profile2.name,
25416
- hint: getPresetById(profile2.providerId)?.displayName || ""
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 = getPresetById(profile.providerId);
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 = getPresetById(profile.providerId);
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 = getPresetById(profile.providerId);
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
- value: profile.name,
25743
- label: profile.name,
25744
- hint: profile.name === current?.name ? "(current)" : getPresetById(profile.providerId)?.displayName || ""
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
- value: profile.name,
25763
- label: profile.name,
25764
- hint: getPresetById(profile.providerId)?.displayName || ""
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 = getPresetById(profile.providerId);
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 join8 } from "path";
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 join4 } from "path";
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 = join4(root, url2.pathname);
26825
+ let filePath = join5(root, url2.pathname);
26177
26826
  try {
26178
26827
  const stats = await stat(filePath);
26179
26828
  if (stats.isDirectory()) {
26180
- filePath = join4(filePath, index);
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 = join4(root, index);
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 join7 } from "path";
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 = join7(tempDir, `.export-${Date.now()}.json`);
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 = join7(tempDir, `.import-${Date.now()}.json`);
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
- exec(`${command} ${url2}`, (error46) => {
26972
- if (error46) {
26973
- console.warn(import_picocolors11.default.yellow(`Could not open browser automatically: ${error46.message}`));
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 join8(__dirname2, "..", "..", "ui", "dist");
27631
+ return join9(__dirname2, "..", "..", "ui", "dist");
26981
27632
  }
26982
- return join8(__dirname2, "..", "..", "ui");
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(import_picocolors17.default.red(`Unknown providers subcommand: ${subcommand}`));
28922
+ console.log(import_picocolors19.default.red(`Unknown providers subcommand: ${subcommand}`));
27790
28923
  console.log();
27791
- console.log(import_picocolors17.default.bold("Available subcommands:"));
27792
- console.log(` ${import_picocolors17.default.cyan("list, ls")} - List all providers`);
27793
- console.log(` ${import_picocolors17.default.cyan("add, new")} - Add a custom provider`);
27794
- console.log(` ${import_picocolors17.default.cyan("remove, rm, delete")} - Remove a custom provider`);
27795
- console.log(` ${import_picocolors17.default.cyan("show, info")} - Show provider details`);
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(import_picocolors17.default.red("Error: Please specify export file path"));
27802
- console.log(import_picocolors17.default.dim("Usage: swixter export <file>"));
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(import_picocolors17.default.green("\u2713") + " Export successful!");
27809
- console.log(` File: ${import_picocolors17.default.cyan(filePath)}`);
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(import_picocolors17.default.red(`\u2717 Export failed: ${error46}`));
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(import_picocolors17.default.yellow("Please specify shell type"));
28953
+ console.log(import_picocolors19.default.yellow("Please specify shell type"));
27821
28954
  console.log();
27822
- console.log(import_picocolors17.default.bold("Usage:"));
27823
- console.log(` ${import_picocolors17.default.green("swixter completion <shell>")}`);
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(import_picocolors17.default.bold("Supported shells:"));
27826
- console.log(` ${import_picocolors17.default.cyan("bash")} - Bash shell`);
27827
- console.log(` ${import_picocolors17.default.cyan("zsh")} - Z shell`);
27828
- console.log(` ${import_picocolors17.default.cyan("fish")} - Fish shell`);
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(import_picocolors17.default.bold("Examples:"));
27831
- console.log(` ${import_picocolors17.default.green("swixter completion bash > ~/.local/share/bash-completion/completions/swixter")}`);
27832
- console.log(` ${import_picocolors17.default.green("swixter completion zsh > ~/.zfunc/_swixter")}`);
27833
- console.log(` ${import_picocolors17.default.green("swixter completion fish > ~/.config/fish/completions/swixter.fish")}`);
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(import_picocolors17.default.red(`Unsupported shell: ${shell}`));
27839
- console.log(import_picocolors17.default.dim(`Supported shells: ${supportedShells.join(", ")}`));
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(import_picocolors17.default.red("Failed to generate completion script:"), error46);
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(import_picocolors17.default.red("Error: Please specify import file path"));
27853
- console.log(import_picocolors17.default.dim("Usage: swixter import <file>"));
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(import_picocolors17.default.green("\u2713") + " Import completed!");
28992
+ console.log(import_picocolors19.default.green("\u2713") + " Import completed!");
27860
28993
  console.log();
27861
- console.log(` Successfully imported: ${import_picocolors17.default.green(result.imported)} items`);
27862
- console.log(` Skipped: ${import_picocolors17.default.yellow(result.skipped)} items`);
27863
- console.log(` Errors: ${import_picocolors17.default.red(result.errors.length)} items`);
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(import_picocolors17.default.red("Error details:"));
27867
- result.errors.forEach((err) => console.log(import_picocolors17.default.red(` - ${err}`)));
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(import_picocolors17.default.red(`\u2717 Import failed: ${error46}`));
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(import_picocolors17.default.bold(import_picocolors17.default.cyan("Swixter")) + import_picocolors17.default.dim(" - AI Coder Configuration Manager"));
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(` ${import_picocolors17.default.bold("Version:")} ${import_picocolors17.default.green(APP_VERSION)}`);
27882
- console.log(` ${import_picocolors17.default.bold("Config Version:")} ${import_picocolors17.default.cyan(CONFIG_VERSION)}`);
27883
- console.log(` ${import_picocolors17.default.bold("Export Version:")} ${import_picocolors17.default.cyan(EXPORT_VERSION)}`);
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(import_picocolors17.default.dim(" GitHub: https://github.com/dawnswwwww/swixter"));
27886
- console.log(import_picocolors17.default.dim(" NPM: https://www.npmjs.com/package/swixter"));
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(import_picocolors17.default.red(`Unknown command: ${firstArg}`));
27944
- console.log(import_picocolors17.default.dim("Run 'swixter --help' for help"));
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(import_picocolors17.default.red("An error occurred:"), error46);
29088
+ console.error(import_picocolors19.default.red("An error occurred:"), error46);
27948
29089
  process.exit(1);
27949
29090
  }
27950
29091
  }