swixter 0.0.8 → 0.0.10

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 +29 -18
  2. package/dist/cli/index.js +1259 -413
  3. package/package.json +4 -1
package/dist/cli/index.js CHANGED
@@ -1,31 +1,51 @@
1
1
  #!/usr/bin/env node
2
+ import { createRequire } from "node:module";
2
3
  var __create = Object.create;
3
4
  var __getProtoOf = Object.getPrototypeOf;
4
5
  var __defProp = Object.defineProperty;
5
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ function __accessProp(key) {
9
+ return this[key];
10
+ }
11
+ var __toESMCache_node;
12
+ var __toESMCache_esm;
7
13
  var __toESM = (mod, isNodeMode, target) => {
14
+ var canCache = mod != null && typeof mod === "object";
15
+ if (canCache) {
16
+ var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
17
+ var cached = cache.get(mod);
18
+ if (cached)
19
+ return cached;
20
+ }
8
21
  target = mod != null ? __create(__getProtoOf(mod)) : {};
9
22
  const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
23
  for (let key of __getOwnPropNames(mod))
11
24
  if (!__hasOwnProp.call(to, key))
12
25
  __defProp(to, key, {
13
- get: () => mod[key],
26
+ get: __accessProp.bind(mod, key),
14
27
  enumerable: true
15
28
  });
29
+ if (canCache)
30
+ cache.set(mod, to);
16
31
  return to;
17
32
  };
18
33
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
34
+ var __returnValue = (v) => v;
35
+ function __exportSetter(name, newValue) {
36
+ this[name] = __returnValue.bind(null, newValue);
37
+ }
19
38
  var __export = (target, all) => {
20
39
  for (var name in all)
21
40
  __defProp(target, name, {
22
41
  get: all[name],
23
42
  enumerable: true,
24
43
  configurable: true,
25
- set: (newValue) => all[name] = () => newValue
44
+ set: __exportSetter.bind(all, name)
26
45
  });
27
46
  };
28
47
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
48
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
29
49
 
30
50
  // node_modules/picocolors/picocolors.js
31
51
  var require_picocolors = __commonJS((exports, module) => {
@@ -12951,7 +12971,9 @@ var init_types = __esm(() => {
12951
12971
  tokensPerMinute: exports_external.number().optional()
12952
12972
  }).optional(),
12953
12973
  docs: exports_external.string().url().optional(),
12954
- isChinese: exports_external.boolean().optional()
12974
+ isChinese: exports_external.boolean().optional(),
12975
+ wire_api: exports_external.enum(["chat", "responses"]).optional(),
12976
+ env_key: exports_external.string().optional()
12955
12977
  });
12956
12978
  ClaudeCodeProfileSchema = exports_external.object({
12957
12979
  name: exports_external.string().min(1),
@@ -13132,7 +13154,8 @@ var init_messages = __esm(() => {
13132
13154
  authToken: "Auth Token",
13133
13155
  configFile: "Config File",
13134
13156
  createdAt: "Created At",
13135
- updatedAt: "Updated At"
13157
+ updatedAt: "Updated At",
13158
+ profileList: "Profiles"
13136
13159
  };
13137
13160
  INSTALL = {
13138
13161
  cliNotInstalled: (name) => `${name} CLI is not installed`,
@@ -13161,6 +13184,10 @@ function getConfigPath(type) {
13161
13184
  const config2 = PATH_CONFIG[type];
13162
13185
  return join(homedir(), config2.dir, config2.file);
13163
13186
  }
13187
+ function getConfigDir(type) {
13188
+ const config2 = PATH_CONFIG[type];
13189
+ return join(homedir(), config2.dir);
13190
+ }
13164
13191
  var PATH_CONFIG;
13165
13192
  var init_paths = __esm(() => {
13166
13193
  PATH_CONFIG = {
@@ -13234,7 +13261,7 @@ var CONFIG_VERSION = "2.0.0", EXPORT_VERSION = "1.0.0";
13234
13261
  var init_versions2 = () => {};
13235
13262
 
13236
13263
  // src/constants/meta.ts
13237
- var APP_VERSION = "0.0.8";
13264
+ var APP_VERSION = "0.0.10";
13238
13265
  var init_meta = () => {};
13239
13266
 
13240
13267
  // src/constants/install.ts
@@ -13530,6 +13557,42 @@ var init_presets = __esm(() => {
13530
13557
  allPresets = builtInPresets;
13531
13558
  });
13532
13559
 
13560
+ // src/utils/model-helper.ts
13561
+ function getOpenAIModel(profile) {
13562
+ if (profile.models) {
13563
+ return;
13564
+ }
13565
+ return profile.model || profile.openaiModel;
13566
+ }
13567
+ function buildProfileEnv(profile, envVarMapping, baseURL, options) {
13568
+ const env = {};
13569
+ if (baseURL && envVarMapping.baseURL) {
13570
+ env[envVarMapping.baseURL] = baseURL;
13571
+ }
13572
+ if (profile.apiKey) {
13573
+ const apiKeyEnvName = options?.apiKeyEnvName || envVarMapping.apiKey;
13574
+ if (apiKeyEnvName) {
13575
+ env[apiKeyEnvName] = profile.apiKey;
13576
+ }
13577
+ }
13578
+ if (profile.authToken && envVarMapping.authToken) {
13579
+ env[envVarMapping.authToken] = profile.authToken;
13580
+ }
13581
+ if (profile.models) {
13582
+ for (const [key, value] of Object.entries(profile.models)) {
13583
+ const envName = envVarMapping[key];
13584
+ if (value && envName) {
13585
+ env[envName] = value;
13586
+ }
13587
+ }
13588
+ }
13589
+ const openaiModel = profile.model || profile.openaiModel;
13590
+ if (openaiModel && envVarMapping.openaiModel) {
13591
+ env[envVarMapping.openaiModel] = openaiModel;
13592
+ }
13593
+ return env;
13594
+ }
13595
+
13533
13596
  // src/adapters/claude.ts
13534
13597
  import { existsSync as existsSync2 } from "node:fs";
13535
13598
  import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "node:fs/promises";
@@ -13540,7 +13603,7 @@ class ClaudeCodeAdapter {
13540
13603
  configPath = getConfigPath("claude");
13541
13604
  coderConfig = CODER_REGISTRY.claude;
13542
13605
  async apply(profile) {
13543
- const preset = getPresetById(profile.providerId);
13606
+ const preset = await getPresetByIdAsync(profile.providerId);
13544
13607
  const baseURL = profile.baseURL || preset?.baseURL || "";
13545
13608
  let existingConfig = {};
13546
13609
  if (existsSync2(this.configPath)) {
@@ -13552,32 +13615,19 @@ class ClaudeCodeAdapter {
13552
13615
  }
13553
13616
  }
13554
13617
  const envVars = this.coderConfig.envVarMapping;
13555
- const newEnv = {
13556
- [envVars.baseURL]: baseURL
13557
- };
13558
- if (profile.apiKey) {
13559
- newEnv[envVars.apiKey] = profile.apiKey;
13560
- }
13561
- if (profile.authToken && envVars.authToken) {
13562
- newEnv[envVars.authToken] = profile.authToken;
13563
- }
13564
- if (profile.models) {
13565
- if (profile.models.anthropicModel && envVars.anthropicModel) {
13566
- newEnv[envVars.anthropicModel] = profile.models.anthropicModel;
13567
- }
13568
- if (profile.models.defaultHaikuModel && envVars.defaultHaikuModel) {
13569
- newEnv[envVars.defaultHaikuModel] = profile.models.defaultHaikuModel;
13570
- }
13571
- if (profile.models.defaultOpusModel && envVars.defaultOpusModel) {
13572
- newEnv[envVars.defaultOpusModel] = profile.models.defaultOpusModel;
13573
- }
13574
- if (profile.models.defaultSonnetModel && envVars.defaultSonnetModel) {
13575
- newEnv[envVars.defaultSonnetModel] = profile.models.defaultSonnetModel;
13618
+ const newEnv = buildProfileEnv(profile, envVars, baseURL);
13619
+ const managedKeys = Object.values(envVars).filter(Boolean);
13620
+ const preservedEnv = {};
13621
+ if (existingConfig.env) {
13622
+ for (const [key, value] of Object.entries(existingConfig.env)) {
13623
+ if (!managedKeys.includes(key)) {
13624
+ preservedEnv[key] = value;
13625
+ }
13576
13626
  }
13577
13627
  }
13578
13628
  const newConfig = {
13579
13629
  ...existingConfig,
13580
- env: newEnv
13630
+ env: { ...preservedEnv, ...newEnv }
13581
13631
  };
13582
13632
  await mkdir2(dirname2(this.configPath), { recursive: true });
13583
13633
  const content = JSON.stringify(newConfig, null, SERIALIZATION.jsonIndent);
@@ -13590,27 +13640,16 @@ class ClaudeCodeAdapter {
13590
13640
  try {
13591
13641
  const content = await readFile2(this.configPath, "utf-8");
13592
13642
  const config2 = JSON.parse(content);
13593
- const preset = getPresetById(profile.providerId);
13643
+ const preset = await getPresetByIdAsync(profile.providerId);
13594
13644
  const expectedBaseURL = profile.baseURL || preset?.baseURL || "";
13595
13645
  const envVars = this.coderConfig.envVarMapping;
13596
- const hasApiKey = profile.apiKey && config2.env?.[envVars.apiKey] === profile.apiKey;
13597
- const hasAuthToken = profile.authToken && envVars.authToken && config2.env?.[envVars.authToken] === profile.authToken;
13598
- let hasMatchingModels = true;
13599
- if (profile.models) {
13600
- if (profile.models.anthropicModel && envVars.anthropicModel) {
13601
- hasMatchingModels = hasMatchingModels && config2.env?.[envVars.anthropicModel] === profile.models.anthropicModel;
13602
- }
13603
- if (profile.models.defaultHaikuModel && envVars.defaultHaikuModel) {
13604
- hasMatchingModels = hasMatchingModels && config2.env?.[envVars.defaultHaikuModel] === profile.models.defaultHaikuModel;
13605
- }
13606
- if (profile.models.defaultOpusModel && envVars.defaultOpusModel) {
13607
- hasMatchingModels = hasMatchingModels && config2.env?.[envVars.defaultOpusModel] === profile.models.defaultOpusModel;
13608
- }
13609
- if (profile.models.defaultSonnetModel && envVars.defaultSonnetModel) {
13610
- hasMatchingModels = hasMatchingModels && config2.env?.[envVars.defaultSonnetModel] === profile.models.defaultSonnetModel;
13646
+ const expectedEnv = buildProfileEnv(profile, envVars, expectedBaseURL);
13647
+ for (const [key, value] of Object.entries(expectedEnv)) {
13648
+ if (config2.env?.[key] !== value) {
13649
+ return false;
13611
13650
  }
13612
13651
  }
13613
- return (hasApiKey || hasAuthToken) && config2.env?.[envVars.baseURL] === expectedBaseURL && hasMatchingModels;
13652
+ return Object.keys(expectedEnv).length > 0;
13614
13653
  } catch (error46) {
13615
13654
  return false;
13616
13655
  }
@@ -16234,14 +16273,6 @@ var init_js_yaml = __esm(() => {
16234
16273
  safeDump = renamed("safeDump", "dump");
16235
16274
  });
16236
16275
 
16237
- // src/utils/model-helper.ts
16238
- function getOpenAIModel(profile) {
16239
- if (profile.models) {
16240
- return;
16241
- }
16242
- return profile.model || profile.openaiModel;
16243
- }
16244
-
16245
16276
  // src/adapters/continue.ts
16246
16277
  import { existsSync as existsSync3 } from "node:fs";
16247
16278
  import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3 } from "node:fs/promises";
@@ -16251,7 +16282,7 @@ class ContinueAdapter {
16251
16282
  name = "continue";
16252
16283
  configPath = getConfigPath("continue");
16253
16284
  async apply(profile) {
16254
- const preset = getPresetById(profile.providerId);
16285
+ const preset = await getPresetByIdAsync(profile.providerId);
16255
16286
  const baseURL = profile.baseURL || preset?.baseURL || "";
16256
16287
  const continueProvider = PROVIDER_MAP[profile.providerId] || "openai";
16257
16288
  let existingConfig = {};
@@ -16305,7 +16336,7 @@ class ContinueAdapter {
16305
16336
  if (!model) {
16306
16337
  return false;
16307
16338
  }
16308
- const preset = getPresetById(profile.providerId);
16339
+ const preset = await getPresetByIdAsync(profile.providerId);
16309
16340
  const expectedBaseURL = profile.baseURL || preset?.baseURL || "";
16310
16341
  const expectedModel = getOpenAIModel(profile);
16311
16342
  if (model.apiBase !== expectedBaseURL) {
@@ -16332,7 +16363,11 @@ class ContinueAdapter {
16332
16363
  const initialLength = config2.models.length;
16333
16364
  config2.models = config2.models.filter((m2) => m2.title !== profileName);
16334
16365
  if (config2.models.length < initialLength) {
16335
- const yamlContent = dump(config2);
16366
+ const yamlContent = dump(config2, {
16367
+ indent: SERIALIZATION.yamlIndent,
16368
+ lineWidth: -1,
16369
+ noRefs: true
16370
+ });
16336
16371
  await writeFile3(this.configPath, yamlContent, "utf-8");
16337
16372
  }
16338
16373
  } catch (error46) {
@@ -17500,13 +17535,13 @@ var init_dist = __esm(() => {
17500
17535
  });
17501
17536
 
17502
17537
  // src/utils/env-key-helper.ts
17503
- function getEnvKey(profile) {
17504
- const preset = getPresetById(profile.providerId);
17538
+ async function getEnvKey(profile) {
17539
+ const preset = await getPresetByIdAsync(profile.providerId);
17505
17540
  return profile.envKey || preset?.env_key || "OPENAI_API_KEY";
17506
17541
  }
17507
- function getEnvExportCommands(profile) {
17542
+ async function getEnvExportCommands(profile) {
17508
17543
  const commands = [];
17509
- const envKey = getEnvKey(profile);
17544
+ const envKey = await getEnvKey(profile);
17510
17545
  if (profile.apiKey) {
17511
17546
  commands.push(`export ${envKey}="${profile.apiKey}"`);
17512
17547
  }
@@ -17546,7 +17581,7 @@ class CodexAdapter {
17546
17581
  config2 = {};
17547
17582
  }
17548
17583
  }
17549
- const preset = getPresetById(profile.providerId);
17584
+ const preset = await getPresetByIdAsync(profile.providerId);
17550
17585
  if (!preset) {
17551
17586
  throw new Error(`Unknown provider: ${profile.providerId}`);
17552
17587
  }
@@ -17555,11 +17590,11 @@ class CodexAdapter {
17555
17590
  if (!config2.model_providers) {
17556
17591
  config2.model_providers = {};
17557
17592
  }
17558
- config2.model_providers[providerName] = this.createProviderTable(profile, preset);
17593
+ config2.model_providers[providerName] = await this.createProviderTable(profile, preset);
17559
17594
  if (!config2.profiles) {
17560
17595
  config2.profiles = {};
17561
17596
  }
17562
- config2.profiles[profileName] = this.createProfileTable(profile, providerName);
17597
+ config2.profiles[profileName] = await this.createProfileTable(profile, providerName);
17563
17598
  config2.profile = profileName;
17564
17599
  config2.model_provider = providerName;
17565
17600
  const tomlContent = stringify(config2);
@@ -17591,19 +17626,19 @@ class CodexAdapter {
17591
17626
  return false;
17592
17627
  }
17593
17628
  }
17594
- createProviderTable(profile, preset) {
17629
+ async createProviderTable(profile, preset) {
17595
17630
  const providerTable = {
17596
17631
  name: preset.displayName,
17597
17632
  base_url: profile.baseURL || preset.baseURL,
17598
17633
  wire_api: preset.wire_api || "chat"
17599
17634
  };
17600
- providerTable.env_key = getEnvKey(profile);
17635
+ providerTable.env_key = await getEnvKey(profile);
17601
17636
  if (preset.headers) {
17602
17637
  providerTable.http_headers = preset.headers;
17603
17638
  }
17604
17639
  return providerTable;
17605
17640
  }
17606
- createProfileTable(profile, providerName) {
17641
+ async createProfileTable(profile, providerName) {
17607
17642
  const profileTable = {
17608
17643
  model_provider: providerName
17609
17644
  };
@@ -17611,15 +17646,15 @@ class CodexAdapter {
17611
17646
  if (modelValue) {
17612
17647
  profileTable.model = modelValue;
17613
17648
  } else {
17614
- const preset = getPresetById(profile.providerId);
17649
+ const preset = await getPresetByIdAsync(profile.providerId);
17615
17650
  if (preset && preset.defaultModels && preset.defaultModels.length > 0) {
17616
17651
  profileTable.model = preset.defaultModels[0];
17617
17652
  }
17618
17653
  }
17619
17654
  return profileTable;
17620
17655
  }
17621
- getEnvExportCommands(profile) {
17622
- const commands = getEnvExportCommands(profile);
17656
+ async getEnvExportCommands(profile) {
17657
+ const commands = await getEnvExportCommands(profile);
17623
17658
  const modelValue = getOpenAIModel(profile);
17624
17659
  if (modelValue) {
17625
17660
  commands.push(`export OPENAI_MODEL="${modelValue}"`);
@@ -17684,6 +17719,21 @@ var init_adapters = __esm(() => {
17684
17719
  });
17685
17720
 
17686
17721
  // src/config/manager.ts
17722
+ var exports_manager = {};
17723
+ __export(exports_manager, {
17724
+ upsertProfile: () => upsertProfile,
17725
+ setActiveProfileForCoder: () => setActiveProfileForCoder,
17726
+ setActiveProfile: () => setActiveProfile,
17727
+ saveConfig: () => saveConfig,
17728
+ profileExists: () => profileExists,
17729
+ loadConfig: () => loadConfig,
17730
+ listProfiles: () => listProfiles,
17731
+ getProfile: () => getProfile,
17732
+ getConfigPath: () => getConfigPath2,
17733
+ getActiveProfileForCoder: () => getActiveProfileForCoder,
17734
+ getActiveProfile: () => getActiveProfile,
17735
+ deleteProfile: () => deleteProfile
17736
+ });
17687
17737
  import { existsSync as existsSync5 } from "node:fs";
17688
17738
  import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile5 } from "node:fs/promises";
17689
17739
  import { dirname as dirname5 } from "node:path";
@@ -17741,6 +17791,9 @@ async function saveConfig(config2) {
17741
17791
  throw new Error(`Failed to save configuration: ${error46}`);
17742
17792
  }
17743
17793
  }
17794
+ async function getActiveProfile() {
17795
+ return getActiveProfileForCoder("claude");
17796
+ }
17744
17797
  async function getActiveProfileForCoder(coder) {
17745
17798
  const config2 = await loadConfig();
17746
17799
  const coderConfig = config2.coders[coder];
@@ -17749,6 +17802,9 @@ async function getActiveProfileForCoder(coder) {
17749
17802
  }
17750
17803
  return config2.profiles[coderConfig.activeProfile];
17751
17804
  }
17805
+ async function setActiveProfile(profileName) {
17806
+ return setActiveProfileForCoder("claude", profileName);
17807
+ }
17752
17808
  async function setActiveProfileForCoder(coder, profileName) {
17753
17809
  const config2 = await loadConfig();
17754
17810
  if (!config2.profiles[profileName]) {
@@ -17784,7 +17840,7 @@ async function deleteProfile(profileName) {
17784
17840
  if (!config2.profiles[profileName]) {
17785
17841
  throw new Error(`Profile "${profileName}" does not exist`);
17786
17842
  }
17787
- const allCoders = ["claude", "qwen", "codex"];
17843
+ const allCoders = Object.keys(CODER_REGISTRY);
17788
17844
  for (const coder of allCoders) {
17789
17845
  try {
17790
17846
  const adapter = getAdapter(coder);
@@ -17806,6 +17862,14 @@ async function listProfiles() {
17806
17862
  const config2 = await loadConfig();
17807
17863
  return Object.values(config2.profiles);
17808
17864
  }
17865
+ async function getProfile(profileName) {
17866
+ const config2 = await loadConfig();
17867
+ return config2.profiles[profileName] || null;
17868
+ }
17869
+ async function profileExists(profileName) {
17870
+ const config2 = await loadConfig();
17871
+ return profileName in config2.profiles;
17872
+ }
17809
17873
  var init_manager = __esm(() => {
17810
17874
  init_types();
17811
17875
  init_constants();
@@ -19597,7 +19661,7 @@ var require_semver2 = __commonJS((exports, module) => {
19597
19661
  });
19598
19662
 
19599
19663
  // src/cli/index.ts
19600
- var import_picocolors13 = __toESM(require_picocolors(), 1);
19664
+ var import_picocolors15 = __toESM(require_picocolors(), 1);
19601
19665
 
19602
19666
  // node_modules/@clack/core/dist/index.mjs
19603
19667
  var import_sisteransi = __toESM(require_src(), 1);
@@ -20292,25 +20356,106 @@ var ProfileValidators = {
20292
20356
 
20293
20357
  // src/utils/commands.ts
20294
20358
  var import_picocolors4 = __toESM(require_picocolors(), 1);
20295
- function parseArgs(args) {
20296
- const parsed = {};
20297
- for (let i2 = 0;i2 < args.length; i2++) {
20298
- if (args[i2].startsWith("--")) {
20299
- const key = args[i2].slice(2);
20300
- const value = args[i2 + 1];
20301
- if (!value || value.startsWith("--")) {
20302
- parsed[key] = true;
20303
- } else {
20304
- parsed[key] = value;
20305
- i2++;
20359
+
20360
+ // src/constants/commands.ts
20361
+ var COMMAND_ALIASES = {
20362
+ r: "run",
20363
+ ls: "list",
20364
+ sw: "switch",
20365
+ rm: "delete",
20366
+ new: "create",
20367
+ "create-profile": "create",
20368
+ "delete-profile": "delete",
20369
+ "list-profiles": "list",
20370
+ "switch-profile": "switch"
20371
+ };
20372
+ var FLAG_ALIASES = {
20373
+ "-n": "--name",
20374
+ "-p": "--provider",
20375
+ "-k": "--api-key",
20376
+ "-t": "--auth-token",
20377
+ "-u": "--base-url",
20378
+ "-m": "--model",
20379
+ "-a": "--apply",
20380
+ "-q": "--quiet",
20381
+ "-f": "--force",
20382
+ "-h": "--help",
20383
+ "-o": "--output",
20384
+ "-i": "--input",
20385
+ "-y": "--yes",
20386
+ "-v": "--verbose",
20387
+ "-P": "--port"
20388
+ };
20389
+ var VALID_COMMANDS = [
20390
+ "create",
20391
+ "list",
20392
+ "switch",
20393
+ "edit",
20394
+ "apply",
20395
+ "current",
20396
+ "delete",
20397
+ "run",
20398
+ "install",
20399
+ "update-cli",
20400
+ "upgrade"
20401
+ ];
20402
+ var GLOBAL_COMMANDS = [
20403
+ "providers",
20404
+ "export",
20405
+ "import",
20406
+ "completion",
20407
+ "help",
20408
+ "version",
20409
+ "ui"
20410
+ ];
20411
+ function resolveFlagAlias(flag) {
20412
+ return FLAG_ALIASES[flag] || flag;
20413
+ }
20414
+
20415
+ // src/cli/commands/parsers.ts
20416
+ function parseFlags(args) {
20417
+ const flags = {};
20418
+ let i2 = 0;
20419
+ while (i2 < args.length) {
20420
+ let arg = args[i2];
20421
+ if (!arg.startsWith("-")) {
20422
+ i2++;
20423
+ continue;
20424
+ }
20425
+ if (arg.includes("=")) {
20426
+ const [flag, value] = arg.split("=", 2);
20427
+ const resolvedFlag = resolveFlagAlias(flag).substring(2);
20428
+ flags[resolvedFlag] = value;
20429
+ i2++;
20430
+ continue;
20431
+ }
20432
+ if (arg.startsWith("-") && !arg.startsWith("--") && arg.length > 2) {
20433
+ const chars = arg.substring(1);
20434
+ for (const char of chars) {
20435
+ const resolved = resolveFlagAlias(`-${char}`).substring(2);
20436
+ flags[resolved] = true;
20306
20437
  }
20438
+ i2++;
20439
+ continue;
20440
+ }
20441
+ const resolvedArg = resolveFlagAlias(arg);
20442
+ const flagName = resolvedArg.substring(2);
20443
+ const nextArg = args[i2 + 1];
20444
+ if (nextArg && !nextArg.startsWith("-")) {
20445
+ flags[flagName] = nextArg;
20446
+ i2 += 2;
20447
+ } else {
20448
+ flags[flagName] = true;
20449
+ i2++;
20307
20450
  }
20308
20451
  }
20309
- return parsed;
20452
+ return flags;
20310
20453
  }
20454
+
20455
+ // src/utils/commands.ts
20311
20456
  async function handleApplyPrompt(options) {
20312
20457
  const { args, applyFn, coderDisplayName, coderName } = options;
20313
- const params = parseArgs(args);
20458
+ const params = parseFlags(args);
20314
20459
  const shouldApply = params.apply;
20315
20460
  const noApply = params["no-apply"];
20316
20461
  if (shouldApply) {
@@ -20651,7 +20796,7 @@ async function handleInstallCommand(coderId, coderConfig, args) {
20651
20796
  process.exit(EXIT_CODES.generalError);
20652
20797
  }
20653
20798
  let selectedMethod;
20654
- const params = parseArgs2(args);
20799
+ const params = parseFlags(args);
20655
20800
  if (params.method !== undefined) {
20656
20801
  const methodIndex = parseInt(params.method, 10) - 1;
20657
20802
  if (methodIndex < 0 || methodIndex >= methods.length) {
@@ -20791,22 +20936,6 @@ async function handleUpdateCommand(coderId, coderConfig, args) {
20791
20936
  }
20792
20937
  console.log();
20793
20938
  }
20794
- function parseArgs2(args) {
20795
- const parsed = {};
20796
- for (let i2 = 0;i2 < args.length; i2++) {
20797
- if (args[i2].startsWith("--")) {
20798
- const key = args[i2].slice(2);
20799
- const value = args[i2 + 1];
20800
- if (!value || value.startsWith("--")) {
20801
- parsed[key] = true;
20802
- } else {
20803
- parsed[key] = value;
20804
- i2++;
20805
- }
20806
- }
20807
- }
20808
- return parsed;
20809
- }
20810
20939
 
20811
20940
  // src/cli/claude.ts
20812
20941
  var CODER_NAME = "claude";
@@ -20863,6 +20992,7 @@ async function handleClaudeCommand(args) {
20863
20992
  break;
20864
20993
  default:
20865
20994
  showError(ERRORS.unknownCommand(command), USAGE.checkHelp(CODER_NAME));
20995
+ process.exit(EXIT_CODES.generalError);
20866
20996
  }
20867
20997
  }
20868
20998
  function showClaudeHelp() {
@@ -20915,24 +21045,8 @@ ${import_picocolors8.default.bold("Examples:")}
20915
21045
  ${import_picocolors8.default.green(`swixter ${CODER_NAME} r --print "What is 2+2?"`)}
20916
21046
  `);
20917
21047
  }
20918
- function parseArgs3(args) {
20919
- const parsed = {};
20920
- for (let i2 = 0;i2 < args.length; i2++) {
20921
- if (args[i2].startsWith("--")) {
20922
- const key = args[i2].slice(2);
20923
- const value = args[i2 + 1];
20924
- if (!value || value.startsWith("--")) {
20925
- parsed[key] = true;
20926
- } else {
20927
- parsed[key] = value;
20928
- i2++;
20929
- }
20930
- }
20931
- }
20932
- return parsed;
20933
- }
20934
21048
  async function cmdCreate(args) {
20935
- const params = parseArgs3(args);
21049
+ const params = parseFlags(args);
20936
21050
  if (params.quiet) {
20937
21051
  await cmdCreateQuiet(params);
20938
21052
  return;
@@ -20952,7 +21066,7 @@ async function cmdCreateInteractive() {
20952
21066
  });
20953
21067
  if (pD(name)) {
20954
21068
  xe(ERRORS.cancelled);
20955
- process.exit(EXIT_CODES.userCancelled);
21069
+ process.exit(EXIT_CODES.cancelled);
20956
21070
  }
20957
21071
  const providerId = await ve({
20958
21072
  message: PROMPTS.selectProvider,
@@ -20964,7 +21078,7 @@ async function cmdCreateInteractive() {
20964
21078
  });
20965
21079
  if (pD(providerId)) {
20966
21080
  xe(ERRORS.cancelled);
20967
- process.exit(EXIT_CODES.userCancelled);
21081
+ process.exit(EXIT_CODES.cancelled);
20968
21082
  }
20969
21083
  const preset = presets.find((p2) => p2.id === providerId);
20970
21084
  const apiKey = await he({
@@ -20973,7 +21087,7 @@ async function cmdCreateInteractive() {
20973
21087
  });
20974
21088
  if (pD(apiKey)) {
20975
21089
  xe(ERRORS.cancelled);
20976
- process.exit(EXIT_CODES.userCancelled);
21090
+ process.exit(EXIT_CODES.cancelled);
20977
21091
  }
20978
21092
  const authToken = await he({
20979
21093
  message: "Auth Token (corresponds to ANTHROPIC_AUTH_TOKEN, optional)",
@@ -20981,7 +21095,7 @@ async function cmdCreateInteractive() {
20981
21095
  });
20982
21096
  if (pD(authToken)) {
20983
21097
  xe(ERRORS.cancelled);
20984
- process.exit(EXIT_CODES.userCancelled);
21098
+ process.exit(EXIT_CODES.cancelled);
20985
21099
  }
20986
21100
  const customBaseURL = await he({
20987
21101
  message: "Base URL (optional, leave empty for default)",
@@ -20995,58 +21109,56 @@ async function cmdCreateInteractive() {
20995
21109
  });
20996
21110
  if (pD(customBaseURL)) {
20997
21111
  xe(ERRORS.cancelled);
20998
- process.exit(EXIT_CODES.userCancelled);
21112
+ process.exit(EXIT_CODES.cancelled);
20999
21113
  }
21000
21114
  let models = undefined;
21001
- if (true) {
21002
- const configureModels = await ye({
21003
- message: PROMPTS.configureModels,
21004
- initialValue: false
21115
+ const configureModels = await ye({
21116
+ message: PROMPTS.configureModels,
21117
+ initialValue: false
21118
+ });
21119
+ if (pD(configureModels)) {
21120
+ xe(ERRORS.cancelled);
21121
+ process.exit(EXIT_CODES.cancelled);
21122
+ }
21123
+ if (configureModels) {
21124
+ const anthropicModel = await he({
21125
+ message: PROMPTS.anthropicModel,
21126
+ placeholder: "claude-3-5-sonnet-20241022"
21005
21127
  });
21006
- if (pD(configureModels)) {
21128
+ if (pD(anthropicModel)) {
21007
21129
  xe(ERRORS.cancelled);
21008
- process.exit(EXIT_CODES.userCancelled);
21130
+ process.exit(EXIT_CODES.cancelled);
21009
21131
  }
21010
- if (configureModels) {
21011
- const anthropicModel = await he({
21012
- message: PROMPTS.anthropicModel,
21013
- placeholder: "claude-3-5-sonnet-20241022"
21014
- });
21015
- if (pD(anthropicModel)) {
21016
- xe(ERRORS.cancelled);
21017
- process.exit(EXIT_CODES.userCancelled);
21018
- }
21019
- const defaultHaikuModel = await he({
21020
- message: PROMPTS.defaultHaikuModel,
21021
- placeholder: "claude-3-5-haiku-20241022"
21022
- });
21023
- if (pD(defaultHaikuModel)) {
21024
- xe(ERRORS.cancelled);
21025
- process.exit(EXIT_CODES.userCancelled);
21026
- }
21027
- const defaultOpusModel = await he({
21028
- message: PROMPTS.defaultOpusModel,
21029
- placeholder: "claude-3-opus-20240229"
21030
- });
21031
- if (pD(defaultOpusModel)) {
21032
- xe(ERRORS.cancelled);
21033
- process.exit(EXIT_CODES.userCancelled);
21034
- }
21035
- const defaultSonnetModel = await he({
21036
- message: PROMPTS.defaultSonnetModel,
21037
- placeholder: "claude-3-5-sonnet-20241022"
21038
- });
21039
- if (pD(defaultSonnetModel)) {
21040
- xe(ERRORS.cancelled);
21041
- process.exit(EXIT_CODES.userCancelled);
21042
- }
21043
- models = {
21044
- ...anthropicModel && { anthropicModel },
21045
- ...defaultHaikuModel && { defaultHaikuModel },
21046
- ...defaultOpusModel && { defaultOpusModel },
21047
- ...defaultSonnetModel && { defaultSonnetModel }
21048
- };
21132
+ const defaultHaikuModel = await he({
21133
+ message: PROMPTS.defaultHaikuModel,
21134
+ placeholder: "claude-3-5-haiku-20241022"
21135
+ });
21136
+ if (pD(defaultHaikuModel)) {
21137
+ xe(ERRORS.cancelled);
21138
+ process.exit(EXIT_CODES.cancelled);
21139
+ }
21140
+ const defaultOpusModel = await he({
21141
+ message: PROMPTS.defaultOpusModel,
21142
+ placeholder: "claude-3-opus-20240229"
21143
+ });
21144
+ if (pD(defaultOpusModel)) {
21145
+ xe(ERRORS.cancelled);
21146
+ process.exit(EXIT_CODES.cancelled);
21147
+ }
21148
+ const defaultSonnetModel = await he({
21149
+ message: PROMPTS.defaultSonnetModel,
21150
+ placeholder: "claude-3-5-sonnet-20241022"
21151
+ });
21152
+ if (pD(defaultSonnetModel)) {
21153
+ xe(ERRORS.cancelled);
21154
+ process.exit(EXIT_CODES.cancelled);
21049
21155
  }
21156
+ models = {
21157
+ ...anthropicModel && { anthropicModel },
21158
+ ...defaultHaikuModel && { defaultHaikuModel },
21159
+ ...defaultOpusModel && { defaultOpusModel },
21160
+ ...defaultSonnetModel && { defaultSonnetModel }
21161
+ };
21050
21162
  }
21051
21163
  const shouldApply = await ye({
21052
21164
  message: "Apply this profile to Claude Code now?",
@@ -21054,7 +21166,7 @@ async function cmdCreateInteractive() {
21054
21166
  });
21055
21167
  if (pD(shouldApply)) {
21056
21168
  xe(ERRORS.cancelled);
21057
- process.exit(EXIT_CODES.userCancelled);
21169
+ process.exit(EXIT_CODES.cancelled);
21058
21170
  }
21059
21171
  const spinner = Y2();
21060
21172
  spinner.start("Creating profile...");
@@ -21172,7 +21284,7 @@ async function cmdList() {
21172
21284
  const preset = getPresetById(profile.providerId);
21173
21285
  const isCurrent = current?.name === profile.name;
21174
21286
  const marker = isCurrent ? import_picocolors8.default.green(MARKERS.active) : import_picocolors8.default.dim(MARKERS.inactive);
21175
- const baseUrl = profile.baseURL || preset?.baseURL || MISC_DEFAULTS.baseUrl;
21287
+ const baseUrl = profile.baseURL || preset?.baseURL || MISC_DEFAULTS.baseUrlFallback;
21176
21288
  console.log(`${marker} ${import_picocolors8.default.cyan(profile.name.padEnd(20))} ${import_picocolors8.default.dim("|")} ${preset?.displayName.padEnd(25)} ${import_picocolors8.default.dim("|")} ${import_picocolors8.default.yellow(baseUrl)}`);
21177
21289
  }
21178
21290
  console.log();
@@ -21471,7 +21583,9 @@ async function cmdCurrent() {
21471
21583
  console.log(` Name: ${import_picocolors8.default.cyan(profile.name)}`);
21472
21584
  console.log(` Provider: ${import_picocolors8.default.yellow(preset?.displayName)}`);
21473
21585
  console.log(` Base URL: ${import_picocolors8.default.yellow(baseUrl)}`);
21474
- console.log(` API Key: ${import_picocolors8.default.dim(profile.apiKey.slice(0, 10) + "...")}`);
21586
+ if (profile.apiKey) {
21587
+ console.log(` API Key: ${import_picocolors8.default.dim(profile.apiKey.slice(0, 10) + "...")}`);
21588
+ }
21475
21589
  console.log();
21476
21590
  }
21477
21591
  async function cmdMainMenu() {
@@ -21496,7 +21610,7 @@ async function cmdMainMenu() {
21496
21610
  });
21497
21611
  if (pD(action)) {
21498
21612
  xe(ERRORS.cancelled);
21499
- process.exit(EXIT_CODES.userCancelled);
21613
+ process.exit(EXIT_CODES.cancelled);
21500
21614
  }
21501
21615
  console.log();
21502
21616
  switch (action) {
@@ -21532,7 +21646,7 @@ async function cmdMainMenu() {
21532
21646
  break;
21533
21647
  case "exit":
21534
21648
  console.log(import_picocolors8.default.green("Goodbye!"));
21535
- process.exit(EXIT_CODES.userCancelled);
21649
+ process.exit(EXIT_CODES.cancelled);
21536
21650
  }
21537
21651
  }
21538
21652
  async function cmdSwitchInteractive() {
@@ -21591,7 +21705,7 @@ async function cmdRun(args) {
21591
21705
  process.exit(EXIT_CODES.generalError);
21592
21706
  }
21593
21707
  await ensureCliAvailable(CODER_NAME, CODER_CONFIG);
21594
- const params = parseArgs3(args);
21708
+ const params = parseFlags(args);
21595
21709
  let profile = null;
21596
21710
  if (params.profile) {
21597
21711
  const profiles = await listProfiles();
@@ -21617,15 +21731,7 @@ async function cmdRun(args) {
21617
21731
  env[key] = value;
21618
21732
  }
21619
21733
  }
21620
- if (profile.apiKey) {
21621
- env.ANTHROPIC_API_KEY = profile.apiKey;
21622
- }
21623
- if (profile.authToken) {
21624
- env.ANTHROPIC_AUTH_TOKEN = profile.authToken;
21625
- }
21626
- if (baseURL) {
21627
- env.ANTHROPIC_BASE_URL = baseURL;
21628
- }
21734
+ Object.assign(env, buildProfileEnv(profile, CODER_CONFIG.envVarMapping, baseURL));
21629
21735
  const claudeArgs = args.filter((arg, idx) => {
21630
21736
  if (arg === "--profile") {
21631
21737
  return false;
@@ -21721,6 +21827,7 @@ async function handleQwenCommand(args) {
21721
21827
  break;
21722
21828
  default:
21723
21829
  showError(ERRORS.unknownCommand(command), USAGE.checkHelp(CODER_NAME2));
21830
+ process.exit(EXIT_CODES.generalError);
21724
21831
  }
21725
21832
  }
21726
21833
  function showQwenHelp() {
@@ -21770,24 +21877,8 @@ ${import_picocolors9.default.bold("Examples:")}
21770
21877
  ${import_picocolors9.default.green('swixter qwen r --prompt "What is 2+2?"')}
21771
21878
  `);
21772
21879
  }
21773
- function parseArgs4(args) {
21774
- const parsed = {};
21775
- for (let i2 = 0;i2 < args.length; i2++) {
21776
- if (args[i2].startsWith("--")) {
21777
- const key = args[i2].slice(2);
21778
- const value = args[i2 + 1];
21779
- if (!value || value.startsWith("--")) {
21780
- parsed[key] = true;
21781
- } else {
21782
- parsed[key] = value;
21783
- i2++;
21784
- }
21785
- }
21786
- }
21787
- return parsed;
21788
- }
21789
21880
  async function cmdCreate2(args) {
21790
- const params = parseArgs4(args);
21881
+ const params = parseFlags(args);
21791
21882
  if (params.quiet) {
21792
21883
  await cmdCreateQuiet2(params);
21793
21884
  return;
@@ -21803,17 +21894,11 @@ async function cmdCreateInteractive2() {
21803
21894
  const name = await he({
21804
21895
  message: "Profile name",
21805
21896
  placeholder: "my-qwen-config",
21806
- validate: (value) => {
21807
- if (!value)
21808
- return "Profile name cannot be empty";
21809
- if (value.length < 2)
21810
- return "Profile name must be at least 2 characters";
21811
- return;
21812
- }
21897
+ validate: ProfileValidators.name
21813
21898
  });
21814
21899
  if (pD(name)) {
21815
21900
  xe(ERRORS.cancelled);
21816
- process.exit(EXIT_CODES.userCancelled);
21901
+ process.exit(EXIT_CODES.cancelled);
21817
21902
  }
21818
21903
  const providerId = await ve({
21819
21904
  message: "Select API provider",
@@ -21825,7 +21910,7 @@ async function cmdCreateInteractive2() {
21825
21910
  });
21826
21911
  if (pD(providerId)) {
21827
21912
  xe(ERRORS.cancelled);
21828
- process.exit(EXIT_CODES.userCancelled);
21913
+ process.exit(EXIT_CODES.cancelled);
21829
21914
  }
21830
21915
  const preset = presets.find((p2) => p2.id === providerId);
21831
21916
  const apiKey = await he({
@@ -21839,7 +21924,7 @@ async function cmdCreateInteractive2() {
21839
21924
  });
21840
21925
  if (pD(apiKey)) {
21841
21926
  xe(ERRORS.cancelled);
21842
- process.exit(EXIT_CODES.userCancelled);
21927
+ process.exit(EXIT_CODES.cancelled);
21843
21928
  }
21844
21929
  const customBaseURL = await he({
21845
21930
  message: "Base URL (optional, leave empty for default)",
@@ -21853,7 +21938,7 @@ async function cmdCreateInteractive2() {
21853
21938
  });
21854
21939
  if (pD(customBaseURL)) {
21855
21940
  xe(ERRORS.cancelled);
21856
- process.exit(EXIT_CODES.userCancelled);
21941
+ process.exit(EXIT_CODES.cancelled);
21857
21942
  }
21858
21943
  const modelName = await he({
21859
21944
  message: PROMPTS.enterQwenModel,
@@ -21866,7 +21951,7 @@ async function cmdCreateInteractive2() {
21866
21951
  });
21867
21952
  if (pD(modelName)) {
21868
21953
  xe(ERRORS.cancelled);
21869
- process.exit(EXIT_CODES.userCancelled);
21954
+ process.exit(EXIT_CODES.cancelled);
21870
21955
  }
21871
21956
  const shouldApply = await ye({
21872
21957
  message: "Apply this profile to Continue now?",
@@ -21874,7 +21959,7 @@ async function cmdCreateInteractive2() {
21874
21959
  });
21875
21960
  if (pD(shouldApply)) {
21876
21961
  xe(ERRORS.cancelled);
21877
- process.exit(EXIT_CODES.userCancelled);
21962
+ process.exit(EXIT_CODES.cancelled);
21878
21963
  }
21879
21964
  const spinner = Y2();
21880
21965
  spinner.start("Creating profile...");
@@ -21980,7 +22065,7 @@ async function cmdList2() {
21980
22065
  const preset = getPresetById(profile.providerId);
21981
22066
  const isCurrent = current?.name === profile.name;
21982
22067
  const marker = isCurrent ? import_picocolors9.default.green(MARKERS.active) : import_picocolors9.default.dim(MARKERS.inactive);
21983
- const baseUrl = profile.baseURL || preset?.baseURL || MISC_DEFAULTS.baseUrl;
22068
+ const baseUrl = profile.baseURL || preset?.baseURL || MISC_DEFAULTS.baseUrlFallback;
21984
22069
  console.log(`${marker} ${import_picocolors9.default.cyan(profile.name.padEnd(20))} ${import_picocolors9.default.dim("|")} ${preset?.displayName.padEnd(25)} ${import_picocolors9.default.dim("|")} ${import_picocolors9.default.yellow(baseUrl)}`);
21985
22070
  }
21986
22071
  console.log();
@@ -22255,7 +22340,7 @@ async function cmdMainMenu2() {
22255
22340
  });
22256
22341
  if (pD(action)) {
22257
22342
  xe(ERRORS.cancelled);
22258
- process.exit(EXIT_CODES.userCancelled);
22343
+ process.exit(EXIT_CODES.cancelled);
22259
22344
  }
22260
22345
  console.log();
22261
22346
  switch (action) {
@@ -22291,7 +22376,7 @@ async function cmdMainMenu2() {
22291
22376
  break;
22292
22377
  case "exit":
22293
22378
  console.log(import_picocolors9.default.green("Goodbye!"));
22294
- process.exit(EXIT_CODES.userCancelled);
22379
+ process.exit(EXIT_CODES.cancelled);
22295
22380
  }
22296
22381
  }
22297
22382
  async function cmdSwitchInteractive2() {
@@ -22350,7 +22435,7 @@ async function cmdRun2(args) {
22350
22435
  process.exit(EXIT_CODES.generalError);
22351
22436
  }
22352
22437
  await ensureCliAvailable(CODER_NAME2, CODER_CONFIG2);
22353
- const params = parseArgs4(args);
22438
+ const params = parseFlags(args);
22354
22439
  let profile = null;
22355
22440
  if (params.profile) {
22356
22441
  const profiles = await listProfiles();
@@ -22376,15 +22461,7 @@ async function cmdRun2(args) {
22376
22461
  env[key] = value;
22377
22462
  }
22378
22463
  }
22379
- if (profile.apiKey) {
22380
- env.OPENAI_API_KEY = profile.apiKey;
22381
- }
22382
- if (baseURL) {
22383
- env.OPENAI_BASE_URL = baseURL;
22384
- }
22385
- if (profile.model || profile.openaiModel) {
22386
- env.OPENAI_MODEL = profile.model || profile.openaiModel;
22387
- }
22464
+ Object.assign(env, buildProfileEnv(profile, CODER_CONFIG2.envVarMapping, baseURL));
22388
22465
  const qwenArgs = [];
22389
22466
  if (profile.apiKey) {
22390
22467
  qwenArgs.push("--openai-api-key", profile.apiKey);
@@ -22492,6 +22569,7 @@ async function handleCodexCommand(args) {
22492
22569
  break;
22493
22570
  default:
22494
22571
  showError(ERRORS.unknownCommand(command), USAGE.checkHelp(CODER_NAME3));
22572
+ process.exit(EXIT_CODES.generalError);
22495
22573
  }
22496
22574
  }
22497
22575
  function showCodexHelp() {
@@ -22547,24 +22625,8 @@ ${import_picocolors10.default.bold("Examples:")}
22547
22625
  ${import_picocolors10.default.green(`swixter ${CODER_NAME3} run --profile my-config`)}
22548
22626
  `);
22549
22627
  }
22550
- function parseArgs5(args) {
22551
- const parsed = {};
22552
- for (let i2 = 0;i2 < args.length; i2++) {
22553
- if (args[i2].startsWith("--")) {
22554
- const key = args[i2].slice(2);
22555
- const value = args[i2 + 1];
22556
- if (!value || value.startsWith("--")) {
22557
- parsed[key] = true;
22558
- } else {
22559
- parsed[key] = value;
22560
- i2++;
22561
- }
22562
- }
22563
- }
22564
- return parsed;
22565
- }
22566
22628
  async function cmdCreate3(args) {
22567
- const params = parseArgs5(args);
22629
+ const params = parseFlags(args);
22568
22630
  if (params.quiet) {
22569
22631
  await cmdCreateQuiet3(params);
22570
22632
  return;
@@ -22584,7 +22646,7 @@ async function cmdCreateInteractive3() {
22584
22646
  });
22585
22647
  if (pD(name)) {
22586
22648
  xe(ERRORS.cancelled);
22587
- process.exit(EXIT_CODES.userCancelled);
22649
+ process.exit(EXIT_CODES.cancelled);
22588
22650
  }
22589
22651
  const providerId = await ve({
22590
22652
  message: PROMPTS.selectProvider,
@@ -22596,7 +22658,7 @@ async function cmdCreateInteractive3() {
22596
22658
  });
22597
22659
  if (pD(providerId)) {
22598
22660
  xe(ERRORS.cancelled);
22599
- process.exit(EXIT_CODES.userCancelled);
22661
+ process.exit(EXIT_CODES.cancelled);
22600
22662
  }
22601
22663
  const preset = presets.find((p2) => p2.id === providerId);
22602
22664
  const apiKey = await he({
@@ -22610,7 +22672,7 @@ async function cmdCreateInteractive3() {
22610
22672
  });
22611
22673
  if (pD(apiKey)) {
22612
22674
  xe(ERRORS.cancelled);
22613
- process.exit(EXIT_CODES.userCancelled);
22675
+ process.exit(EXIT_CODES.cancelled);
22614
22676
  }
22615
22677
  const customBaseURL = await he({
22616
22678
  message: "Base URL (optional, leave empty for default)",
@@ -22624,7 +22686,7 @@ async function cmdCreateInteractive3() {
22624
22686
  });
22625
22687
  if (pD(customBaseURL)) {
22626
22688
  xe(ERRORS.cancelled);
22627
- process.exit(EXIT_CODES.userCancelled);
22689
+ process.exit(EXIT_CODES.cancelled);
22628
22690
  }
22629
22691
  let modelName = "";
22630
22692
  if (preset && preset.defaultModels && preset.defaultModels.length > 0) {
@@ -22643,7 +22705,7 @@ async function cmdCreateInteractive3() {
22643
22705
  });
22644
22706
  if (pD(modelName)) {
22645
22707
  xe(ERRORS.cancelled);
22646
- process.exit(EXIT_CODES.userCancelled);
22708
+ process.exit(EXIT_CODES.cancelled);
22647
22709
  }
22648
22710
  if (modelName === "__custom__") {
22649
22711
  modelName = await he({
@@ -22657,7 +22719,7 @@ async function cmdCreateInteractive3() {
22657
22719
  });
22658
22720
  if (pD(modelName)) {
22659
22721
  xe(ERRORS.cancelled);
22660
- process.exit(EXIT_CODES.userCancelled);
22722
+ process.exit(EXIT_CODES.cancelled);
22661
22723
  }
22662
22724
  }
22663
22725
  } else {
@@ -22670,7 +22732,7 @@ async function cmdCreateInteractive3() {
22670
22732
  });
22671
22733
  if (pD(modelName)) {
22672
22734
  xe(ERRORS.cancelled);
22673
- process.exit(EXIT_CODES.userCancelled);
22735
+ process.exit(EXIT_CODES.cancelled);
22674
22736
  }
22675
22737
  }
22676
22738
  const customEnvKey = await he({
@@ -22682,7 +22744,7 @@ async function cmdCreateInteractive3() {
22682
22744
  });
22683
22745
  if (pD(customEnvKey)) {
22684
22746
  xe(ERRORS.cancelled);
22685
- process.exit(EXIT_CODES.userCancelled);
22747
+ process.exit(EXIT_CODES.cancelled);
22686
22748
  }
22687
22749
  const shouldApply = await ye({
22688
22750
  message: `Apply this profile to ${CODER_CONFIG3.displayName} now?`,
@@ -22690,7 +22752,7 @@ async function cmdCreateInteractive3() {
22690
22752
  });
22691
22753
  if (pD(shouldApply)) {
22692
22754
  xe(ERRORS.cancelled);
22693
- process.exit(EXIT_CODES.userCancelled);
22755
+ process.exit(EXIT_CODES.cancelled);
22694
22756
  }
22695
22757
  const spinner = Y2();
22696
22758
  spinner.start("Creating profile...");
@@ -22814,7 +22876,7 @@ async function cmdList3() {
22814
22876
  const preset = getPresetById(profile.providerId);
22815
22877
  const isCurrent = current?.name === profile.name;
22816
22878
  const marker = isCurrent ? import_picocolors10.default.green(MARKERS.active) : import_picocolors10.default.dim(MARKERS.inactive);
22817
- const baseUrl = profile.baseURL || preset?.baseURL || MISC_DEFAULTS.baseUrl;
22879
+ const baseUrl = profile.baseURL || preset?.baseURL || MISC_DEFAULTS.baseUrlFallback;
22818
22880
  console.log(`${marker} ${import_picocolors10.default.cyan(profile.name.padEnd(20))} ${import_picocolors10.default.dim("|")} ${preset?.displayName.padEnd(25)} ${import_picocolors10.default.dim("|")} ${import_picocolors10.default.yellow(baseUrl)}`);
22819
22881
  }
22820
22882
  console.log();
@@ -23080,7 +23142,7 @@ async function cmdApply3() {
23080
23142
  const profile = await getActiveProfileForCoder(CODER_NAME3);
23081
23143
  if (!profile) {
23082
23144
  console.log(import_picocolors10.default.yellow("No active profile"));
23083
- console.log(import_picocolors10.default.dim("Run 'swixter claude create' to create a profile"));
23145
+ console.log(import_picocolors10.default.dim("Run 'swixter codex create' to create a profile"));
23084
23146
  return;
23085
23147
  }
23086
23148
  try {
@@ -23098,7 +23160,7 @@ async function cmdApply3() {
23098
23160
  console.log(` Config file: ${import_picocolors10.default.dim(adapter.configPath)}`);
23099
23161
  console.log();
23100
23162
  if (adapter.name === "codex" && "getEnvExportCommands" in adapter) {
23101
- const envCommands = adapter.getEnvExportCommands(profile);
23163
+ const envCommands = await adapter.getEnvExportCommands(profile);
23102
23164
  if (envCommands.length > 0) {
23103
23165
  console.log(import_picocolors10.default.bold("To use this profile, set environment variables:"));
23104
23166
  console.log();
@@ -23136,7 +23198,9 @@ async function cmdCurrent3() {
23136
23198
  console.log(` Name: ${import_picocolors10.default.cyan(profile.name)}`);
23137
23199
  console.log(` Provider: ${import_picocolors10.default.yellow(preset?.displayName)}`);
23138
23200
  console.log(` Base URL: ${import_picocolors10.default.yellow(baseUrl)}`);
23139
- console.log(` API Key: ${import_picocolors10.default.dim(profile.apiKey.slice(0, 10) + "...")}`);
23201
+ if (profile.apiKey) {
23202
+ console.log(` API Key: ${import_picocolors10.default.dim(profile.apiKey.slice(0, 10) + "...")}`);
23203
+ }
23140
23204
  console.log();
23141
23205
  }
23142
23206
  async function cmdMainMenu3() {
@@ -23161,7 +23225,7 @@ async function cmdMainMenu3() {
23161
23225
  });
23162
23226
  if (pD(action)) {
23163
23227
  xe(ERRORS.cancelled);
23164
- process.exit(EXIT_CODES.userCancelled);
23228
+ process.exit(EXIT_CODES.cancelled);
23165
23229
  }
23166
23230
  console.log();
23167
23231
  switch (action) {
@@ -23197,7 +23261,7 @@ async function cmdMainMenu3() {
23197
23261
  break;
23198
23262
  case "exit":
23199
23263
  console.log(import_picocolors10.default.green("Goodbye!"));
23200
- process.exit(EXIT_CODES.userCancelled);
23264
+ process.exit(EXIT_CODES.cancelled);
23201
23265
  }
23202
23266
  }
23203
23267
  async function cmdSwitchInteractive3() {
@@ -23256,7 +23320,7 @@ async function cmdRun3(args) {
23256
23320
  process.exit(EXIT_CODES.generalError);
23257
23321
  }
23258
23322
  await ensureCliAvailable(CODER_NAME3, CODER_CONFIG3);
23259
- const params = parseArgs5(args);
23323
+ const params = parseFlags(args);
23260
23324
  let profile = null;
23261
23325
  if (params.profile) {
23262
23326
  const profiles = await listProfiles();
@@ -23285,17 +23349,14 @@ async function cmdRun3(args) {
23285
23349
  env[key] = value;
23286
23350
  }
23287
23351
  }
23288
- if (profile.apiKey) {
23289
- env[envKey] = profile.apiKey;
23290
- }
23291
- if (profile.model || profile.openaiModel) {
23292
- env["OPENAI_MODEL"] = profile.model || profile.openaiModel;
23293
- }
23352
+ Object.assign(env, buildProfileEnv(profile, CODER_CONFIG3.envVarMapping, "", {
23353
+ apiKeyEnvName: envKey
23354
+ }));
23294
23355
  const codexArgs = args.filter((arg, idx) => {
23295
- if (arg === "--profile" || arg === "-p") {
23356
+ if (arg === "--profile") {
23296
23357
  return false;
23297
23358
  }
23298
- if (idx > 0 && (args[idx - 1] === "--profile" || args[idx - 1] === "-p")) {
23359
+ if (idx > 0 && args[idx - 1] === "--profile") {
23299
23360
  return false;
23300
23361
  }
23301
23362
  return true;
@@ -23333,18 +23394,623 @@ async function cmdUpdate3(args) {
23333
23394
  await handleUpdateCommand(CODER_NAME3, CODER_CONFIG3, args);
23334
23395
  }
23335
23396
 
23336
- // src/config/export.ts
23337
- init_types();
23338
- init_manager();
23339
- init_constants();
23340
- import { existsSync as existsSync6 } from "node:fs";
23341
- import { readFile as readFile6, writeFile as writeFile6 } from "node:fs/promises";
23342
- function sanitizeApiKey(apiKey) {
23343
- if (apiKey.length <= API_KEY_FORMAT.sanitizeLength) {
23344
- return "***";
23397
+ // src/cli/ui.ts
23398
+ var import_picocolors12 = __toESM(require_picocolors(), 1);
23399
+
23400
+ // src/server/index.ts
23401
+ var import_picocolors11 = __toESM(require_picocolors(), 1);
23402
+ import { createServer } from "node:http";
23403
+ import { dirname as dirname7, join as join6 } from "node:path";
23404
+ import { fileURLToPath } from "node:url";
23405
+ import { exec } from "node:child_process";
23406
+
23407
+ // src/server/middleware.ts
23408
+ function corsMiddleware(req, res, next) {
23409
+ const origin = req.headers.origin;
23410
+ if (origin && (origin.startsWith("http://127.0.0.1:") || origin.startsWith("http://localhost:"))) {
23411
+ res.setHeader("Access-Control-Allow-Origin", origin);
23412
+ }
23413
+ if (req.method === "OPTIONS") {
23414
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
23415
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
23416
+ res.setHeader("Access-Control-Max-Age", "86400");
23417
+ res.statusCode = 204;
23418
+ res.end();
23419
+ return;
23345
23420
  }
23346
- const start = apiKey.slice(0, API_KEY_FORMAT.prefixLength);
23347
- const end = apiKey.slice(-API_KEY_FORMAT.suffixLength);
23421
+ next();
23422
+ }
23423
+ function jsonBodyMiddleware(req, res, next) {
23424
+ if (!["POST", "PUT", "PATCH"].includes(req.method || "")) {
23425
+ next();
23426
+ return;
23427
+ }
23428
+ const contentType = req.headers["content-type"];
23429
+ if (!contentType?.includes("application/json")) {
23430
+ next();
23431
+ return;
23432
+ }
23433
+ const chunks = [];
23434
+ req.on("data", (chunk) => {
23435
+ chunks.push(chunk);
23436
+ });
23437
+ req.on("end", () => {
23438
+ try {
23439
+ if (chunks.length === 0) {
23440
+ next();
23441
+ return;
23442
+ }
23443
+ const body = Buffer.concat(chunks).toString("utf-8");
23444
+ req.body = JSON.parse(body);
23445
+ next();
23446
+ } catch (error46) {
23447
+ next(new Error("Invalid JSON body"));
23448
+ }
23449
+ });
23450
+ req.on("error", (error46) => {
23451
+ next(error46);
23452
+ });
23453
+ }
23454
+ function sendError(res, error46, statusCode = 400) {
23455
+ res.setHeader("Content-Type", "application/json");
23456
+ if (error46 instanceof Error) {
23457
+ res.statusCode = statusCode;
23458
+ res.end(JSON.stringify({
23459
+ error: {
23460
+ code: "UNKNOWN_ERROR",
23461
+ message: error46.message
23462
+ }
23463
+ }));
23464
+ return;
23465
+ }
23466
+ res.statusCode = statusCode;
23467
+ res.end(JSON.stringify({
23468
+ error: error46
23469
+ }));
23470
+ }
23471
+ function sendJson(res, data, statusCode = 200) {
23472
+ res.setHeader("Content-Type", "application/json");
23473
+ res.statusCode = statusCode;
23474
+ res.end(JSON.stringify(data));
23475
+ }
23476
+ function notFoundHandler(req, res) {
23477
+ res.setHeader("Content-Type", "application/json");
23478
+ res.statusCode = 404;
23479
+ res.end(JSON.stringify({
23480
+ error: {
23481
+ code: "NOT_FOUND",
23482
+ message: `Path ${req.url} not found`
23483
+ }
23484
+ }));
23485
+ }
23486
+
23487
+ // src/server/router.ts
23488
+ function extractParams(pattern, path) {
23489
+ const patternParts = pattern.replace(/\/$/, "").split("/").filter(Boolean);
23490
+ const pathParts = path.replace(/\/$/, "").split("/").filter(Boolean);
23491
+ if (patternParts.length !== pathParts.length) {
23492
+ return null;
23493
+ }
23494
+ const params = {};
23495
+ for (let i2 = 0;i2 < patternParts.length; i2++) {
23496
+ const patternPart = patternParts[i2];
23497
+ const pathPart = pathParts[i2];
23498
+ if (patternPart.startsWith(":")) {
23499
+ const paramName = patternPart.slice(1);
23500
+ params[paramName] = pathPart;
23501
+ } else if (patternPart !== pathPart) {
23502
+ return null;
23503
+ }
23504
+ }
23505
+ return params;
23506
+ }
23507
+
23508
+ class Router {
23509
+ routes = [];
23510
+ middleware = [];
23511
+ use(middleware) {
23512
+ this.middleware.push(middleware);
23513
+ }
23514
+ get(pattern, handler) {
23515
+ this.routes.push({ method: "GET", pattern, handler });
23516
+ }
23517
+ post(pattern, handler) {
23518
+ this.routes.push({ method: "POST", pattern, handler });
23519
+ }
23520
+ put(pattern, handler) {
23521
+ this.routes.push({ method: "PUT", pattern, handler });
23522
+ }
23523
+ delete(pattern, handler) {
23524
+ this.routes.push({ method: "DELETE", pattern, handler });
23525
+ }
23526
+ matchRoute(req) {
23527
+ const method = (req.method || "GET").toUpperCase();
23528
+ const url2 = new URL(req.url || "", `http://${req.headers.host || "localhost"}`);
23529
+ const path = url2.pathname;
23530
+ for (const route of this.routes) {
23531
+ if (route.method !== method) {
23532
+ continue;
23533
+ }
23534
+ const params = extractParams(route.pattern, path);
23535
+ if (params !== null) {
23536
+ return { route, params };
23537
+ }
23538
+ }
23539
+ return null;
23540
+ }
23541
+ async handle(req, res) {
23542
+ let middlewareIndex = 0;
23543
+ const runMiddleware = (error46) => {
23544
+ if (error46) {
23545
+ this.finalize(req, res, error46);
23546
+ return;
23547
+ }
23548
+ if (middlewareIndex < this.middleware.length) {
23549
+ const middleware = this.middleware[middlewareIndex++];
23550
+ Promise.resolve(middleware(req, res, runMiddleware)).catch(runMiddleware);
23551
+ return;
23552
+ }
23553
+ this.executeRoute(req, res).catch((error47) => {
23554
+ this.finalize(req, res, error47);
23555
+ });
23556
+ };
23557
+ runMiddleware();
23558
+ }
23559
+ async executeRoute(req, res) {
23560
+ const match = this.matchRoute(req);
23561
+ if (!match) {
23562
+ return;
23563
+ }
23564
+ const { route, params } = match;
23565
+ await route.handler(req, res, params);
23566
+ }
23567
+ finalize(req, res, error46) {
23568
+ if (error46) {
23569
+ sendError(res, error46, 500);
23570
+ return;
23571
+ }
23572
+ if (!res.writableEnded) {
23573
+ notFoundHandler(req, res);
23574
+ }
23575
+ }
23576
+ }
23577
+
23578
+ // src/server/static.ts
23579
+ import { createReadStream } from "node:fs";
23580
+ import { stat } from "node:fs/promises";
23581
+ import { extname, join as join4 } from "node:path";
23582
+ var MIME_TYPES = {
23583
+ ".html": "text/html; charset=utf-8",
23584
+ ".js": "application/javascript; charset=utf-8",
23585
+ ".mjs": "application/javascript; charset=utf-8",
23586
+ ".css": "text/css; charset=utf-8",
23587
+ ".json": "application/json; charset=utf-8",
23588
+ ".png": "image/png",
23589
+ ".jpg": "image/jpeg",
23590
+ ".jpeg": "image/jpeg",
23591
+ ".gif": "image/gif",
23592
+ ".svg": "image/svg+xml",
23593
+ ".ico": "image/x-icon",
23594
+ ".woff": "font/woff",
23595
+ ".woff2": "font/woff2",
23596
+ ".ttf": "font/ttf",
23597
+ ".eot": "application/vnd.ms-fontobject",
23598
+ ".mp4": "video/mp4",
23599
+ ".webm": "video/webm",
23600
+ ".ogg": "audio/ogg",
23601
+ ".mp3": "audio/mpeg",
23602
+ ".wav": "audio/wav",
23603
+ ".webp": "image/webp",
23604
+ ".avif": "image/avif"
23605
+ };
23606
+ function createStaticServe(options) {
23607
+ const { root, index = "index.html", spa = true } = options;
23608
+ return async (req, res) => {
23609
+ const url2 = new URL(req.url || "", `http://${req.headers.host || "localhost"}`);
23610
+ let filePath = join4(root, url2.pathname);
23611
+ try {
23612
+ const stats = await stat(filePath);
23613
+ if (stats.isDirectory()) {
23614
+ filePath = join4(filePath, index);
23615
+ await stat(filePath);
23616
+ }
23617
+ const ext = extname(filePath);
23618
+ const contentType = MIME_TYPES[ext] || "application/octet-stream";
23619
+ res.setHeader("Content-Type", contentType);
23620
+ const stream = createReadStream(filePath);
23621
+ stream.on("error", (error46) => {
23622
+ if (!res.writableEnded) {
23623
+ res.statusCode = 500;
23624
+ res.end("Internal Server Error");
23625
+ }
23626
+ });
23627
+ stream.pipe(res);
23628
+ } catch (error46) {
23629
+ if (spa) {
23630
+ try {
23631
+ const indexPath = join4(root, index);
23632
+ const stats = await stat(indexPath);
23633
+ if (stats.isFile()) {
23634
+ res.setHeader("Content-Type", "text/html; charset=utf-8");
23635
+ const stream = createReadStream(indexPath);
23636
+ stream.pipe(res);
23637
+ return;
23638
+ }
23639
+ } catch {}
23640
+ }
23641
+ if (!res.writableEnded) {
23642
+ res.statusCode = 404;
23643
+ res.setHeader("Content-Type", "text/plain; charset=utf-8");
23644
+ res.end("Not Found");
23645
+ }
23646
+ }
23647
+ };
23648
+ }
23649
+
23650
+ // src/server/api/profiles.ts
23651
+ init_manager();
23652
+
23653
+ // src/server/api/util.ts
23654
+ function maskApiKey(apiKey) {
23655
+ if (!apiKey || apiKey.length <= 8) {
23656
+ return "****";
23657
+ }
23658
+ const first = apiKey.slice(0, 4);
23659
+ const last = apiKey.slice(-4);
23660
+ return `${first}${"*".repeat(Math.min(apiKey.length - 8, 20))}${last}`;
23661
+ }
23662
+ function maskAuthToken(token) {
23663
+ if (!token || token.length <= 8) {
23664
+ return "****";
23665
+ }
23666
+ const first = token.slice(0, 4);
23667
+ const last = token.slice(-4);
23668
+ return `${first}${"*".repeat(Math.min(token.length - 8, 20))}${last}`;
23669
+ }
23670
+ function sanitizeProfile(profile) {
23671
+ return {
23672
+ ...profile,
23673
+ apiKey: maskApiKey(profile.apiKey),
23674
+ authToken: profile.authToken ? maskAuthToken(profile.authToken) : undefined
23675
+ };
23676
+ }
23677
+ function generateETag(mtime, size) {
23678
+ const mtimeMs = Math.floor(mtime.getTime() / 1000);
23679
+ return `"${mtimeMs}-${size}"`;
23680
+ }
23681
+ function parseIfNoneMatch(header) {
23682
+ if (!header) {
23683
+ return null;
23684
+ }
23685
+ return header.replace(/^"|"$/g, "");
23686
+ }
23687
+ function setETagHeaders(res, mtime, size) {
23688
+ const etag = generateETag(mtime, size);
23689
+ res.setHeader("ETag", etag);
23690
+ res.setHeader("Cache-Control", "no-cache");
23691
+ }
23692
+
23693
+ // src/server/api/profiles.ts
23694
+ init_presets();
23695
+ async function listProfiles2(req, res) {
23696
+ const profiles = await listProfiles();
23697
+ sendJson(res, profiles.map(sanitizeProfile));
23698
+ }
23699
+ async function getProfile2(req, res, params) {
23700
+ const { name } = params;
23701
+ if (!name) {
23702
+ sendError(res, { code: "INVALID_PARAMS", message: "Profile name is required" }, 400);
23703
+ return;
23704
+ }
23705
+ const profile = await getProfile(name);
23706
+ if (!profile) {
23707
+ sendError(res, { code: "PROFILE_NOT_FOUND", message: `Profile "${name}" does not exist` }, 404);
23708
+ return;
23709
+ }
23710
+ sendJson(res, sanitizeProfile(profile));
23711
+ }
23712
+ async function createProfile(req, res) {
23713
+ const body = req.body;
23714
+ if (!body || !body.name || !body.providerId) {
23715
+ sendError(res, { code: "INVALID_PARAMS", message: "name and providerId are required" }, 400);
23716
+ return;
23717
+ }
23718
+ const providers = await getAllPresets();
23719
+ const provider = providers.find((p2) => p2.id === body.providerId);
23720
+ if (!provider) {
23721
+ sendError(res, { code: "UNKNOWN_PROVIDER", message: `Provider "${body.providerId}" not found` }, 400);
23722
+ return;
23723
+ }
23724
+ const existing = await getProfile(body.name);
23725
+ if (existing) {
23726
+ sendError(res, { code: "PROFILE_EXISTS", message: `Profile "${body.name}" already exists` }, 409);
23727
+ return;
23728
+ }
23729
+ try {
23730
+ const now = new Date().toISOString();
23731
+ const profile = {
23732
+ name: body.name,
23733
+ providerId: body.providerId,
23734
+ apiKey: body.apiKey || "",
23735
+ authToken: body.authToken || "",
23736
+ baseURL: body.baseURL || provider.baseURL,
23737
+ model: body.model,
23738
+ openaiModel: body.openaiModel,
23739
+ models: body.models,
23740
+ envKey: body.envKey,
23741
+ headers: body.headers,
23742
+ createdAt: now,
23743
+ updatedAt: now
23744
+ };
23745
+ await upsertProfile(profile, body.coder);
23746
+ sendJson(res, sanitizeProfile(profile), 201);
23747
+ } catch (error46) {
23748
+ sendError(res, { code: "CREATE_FAILED", message: error46 instanceof Error ? error46.message : "Failed to create profile" }, 500);
23749
+ }
23750
+ }
23751
+ async function updateProfile(req, res, params) {
23752
+ const { name } = params;
23753
+ const body = req.body;
23754
+ if (!name) {
23755
+ sendError(res, { code: "INVALID_PARAMS", message: "Profile name is required" }, 400);
23756
+ return;
23757
+ }
23758
+ const existing = await getProfile(name);
23759
+ if (!existing) {
23760
+ sendError(res, { code: "PROFILE_NOT_FOUND", message: `Profile "${name}" does not exist` }, 404);
23761
+ return;
23762
+ }
23763
+ try {
23764
+ const now = new Date().toISOString();
23765
+ const profile = {
23766
+ ...existing,
23767
+ ...body,
23768
+ name,
23769
+ updatedAt: now
23770
+ };
23771
+ await upsertProfile(profile);
23772
+ sendJson(res, sanitizeProfile(profile));
23773
+ } catch (error46) {
23774
+ sendError(res, { code: "UPDATE_FAILED", message: error46 instanceof Error ? error46.message : "Failed to update profile" }, 500);
23775
+ }
23776
+ }
23777
+ async function deleteProfile2(req, res, params) {
23778
+ const { name } = params;
23779
+ if (!name) {
23780
+ sendError(res, { code: "INVALID_PARAMS", message: "Profile name is required" }, 400);
23781
+ return;
23782
+ }
23783
+ try {
23784
+ await deleteProfile(name);
23785
+ sendJson(res, { success: true, message: `Profile "${name}" deleted` });
23786
+ } catch (error46) {
23787
+ sendError(res, { code: "DELETE_FAILED", message: error46 instanceof Error ? error46.message : "Failed to delete profile" }, 500);
23788
+ }
23789
+ }
23790
+
23791
+ // src/server/api/providers.ts
23792
+ init_presets();
23793
+ init_user_providers();
23794
+ async function listProviders(req, res) {
23795
+ const providers = await getAllPresets();
23796
+ const userProviders = await loadUserProviders();
23797
+ const userIds = new Set(userProviders.map((p2) => p2.id));
23798
+ const result = providers.map((p2) => ({
23799
+ ...p2,
23800
+ isUser: userIds.has(p2.id)
23801
+ }));
23802
+ sendJson(res, result);
23803
+ }
23804
+ async function createProvider(req, res) {
23805
+ const body = req.body;
23806
+ if (!body || !body.id || !body.name || !body.displayName) {
23807
+ sendError(res, { code: "INVALID_PARAMS", message: "id, name, and displayName are required" }, 400);
23808
+ return;
23809
+ }
23810
+ const providers = await getAllPresets();
23811
+ const existing = providers.find((p2) => p2.id === body.id);
23812
+ if (existing) {
23813
+ sendError(res, { code: "PROVIDER_EXISTS", message: `Provider "${body.id}" already exists` }, 409);
23814
+ return;
23815
+ }
23816
+ try {
23817
+ const provider = {
23818
+ id: body.id,
23819
+ name: body.name,
23820
+ displayName: body.displayName,
23821
+ baseURL: body.baseURL || "",
23822
+ defaultModels: body.defaultModels || [],
23823
+ authType: body.authType || "api-key",
23824
+ headers: body.headers,
23825
+ rateLimit: body.rateLimit,
23826
+ docs: body.docs,
23827
+ isChinese: body.isChinese,
23828
+ wire_api: body.wire_api,
23829
+ env_key: body.env_key
23830
+ };
23831
+ await upsertUserProvider(provider);
23832
+ sendJson(res, { ...provider, isUser: true }, 201);
23833
+ } catch (error46) {
23834
+ sendError(res, { code: "CREATE_FAILED", message: error46 instanceof Error ? error46.message : "Failed to create provider" }, 500);
23835
+ }
23836
+ }
23837
+ async function updateProvider(req, res, params) {
23838
+ const { id } = params;
23839
+ const body = req.body;
23840
+ if (!id) {
23841
+ sendError(res, { code: "INVALID_PARAMS", message: "Provider ID is required" }, 400);
23842
+ return;
23843
+ }
23844
+ const userProviders = await loadUserProviders();
23845
+ const existing = userProviders.find((p2) => p2.id === id);
23846
+ if (!existing) {
23847
+ sendError(res, { code: "NOT_USER_PROVIDER", message: `Provider "${id}" is not a user-defined provider` }, 400);
23848
+ return;
23849
+ }
23850
+ try {
23851
+ const provider = {
23852
+ ...existing,
23853
+ ...body,
23854
+ id
23855
+ };
23856
+ await upsertUserProvider(provider);
23857
+ sendJson(res, { ...provider, isUser: true });
23858
+ } catch (error46) {
23859
+ sendError(res, { code: "UPDATE_FAILED", message: error46 instanceof Error ? error46.message : "Failed to update provider" }, 500);
23860
+ }
23861
+ }
23862
+ async function deleteProvider(req, res, params) {
23863
+ const { id } = params;
23864
+ if (!id) {
23865
+ sendError(res, { code: "INVALID_PARAMS", message: "Provider ID is required" }, 400);
23866
+ return;
23867
+ }
23868
+ const userProviders = await loadUserProviders();
23869
+ const existing = userProviders.find((p2) => p2.id === id);
23870
+ if (!existing) {
23871
+ sendError(res, { code: "NOT_USER_PROVIDER", message: `Provider "${id}" is not a user-defined provider` }, 400);
23872
+ return;
23873
+ }
23874
+ try {
23875
+ const deleted = await deleteUserProvider(id);
23876
+ if (!deleted) {
23877
+ sendError(res, { code: "DELETE_FAILED", message: `Failed to delete provider "${id}"` }, 500);
23878
+ return;
23879
+ }
23880
+ sendJson(res, { success: true, message: `Provider "${id}" deleted` });
23881
+ } catch (error46) {
23882
+ sendError(res, { code: "DELETE_FAILED", message: error46 instanceof Error ? error46.message : "Failed to delete provider" }, 500);
23883
+ }
23884
+ }
23885
+
23886
+ // src/server/api/coders.ts
23887
+ init_coders();
23888
+ init_manager();
23889
+ init_adapters();
23890
+ async function listCoders(req, res) {
23891
+ const result = [];
23892
+ for (const [coderId, coderConfig] of Object.entries(CODER_REGISTRY)) {
23893
+ const activeProfile = await getActiveProfileForCoder(coderId);
23894
+ result.push({
23895
+ id: coderId,
23896
+ displayName: coderConfig.displayName,
23897
+ executable: coderConfig.executable,
23898
+ activeProfile: activeProfile ? {
23899
+ name: activeProfile.name,
23900
+ providerId: activeProfile.providerId,
23901
+ baseURL: activeProfile.baseURL
23902
+ } : null
23903
+ });
23904
+ }
23905
+ sendJson(res, result);
23906
+ }
23907
+ async function getActiveProfile2(req, res, params) {
23908
+ const { coder } = params;
23909
+ if (!coder) {
23910
+ sendError(res, { code: "INVALID_PARAMS", message: "Coder ID is required" }, 400);
23911
+ return;
23912
+ }
23913
+ if (!CODER_REGISTRY[coder]) {
23914
+ sendError(res, { code: "UNKNOWN_CODER", message: `Coder "${coder}" not found` }, 404);
23915
+ return;
23916
+ }
23917
+ const profile = await getActiveProfileForCoder(coder);
23918
+ if (!profile) {
23919
+ sendJson(res, { activeProfile: null });
23920
+ return;
23921
+ }
23922
+ sendJson(res, { activeProfile: sanitizeProfile(profile) });
23923
+ }
23924
+ async function setActiveProfile2(req, res, params) {
23925
+ const { coder } = params;
23926
+ const body = req.body;
23927
+ if (!coder) {
23928
+ sendError(res, { code: "INVALID_PARAMS", message: "Coder ID is required" }, 400);
23929
+ return;
23930
+ }
23931
+ if (!CODER_REGISTRY[coder]) {
23932
+ sendError(res, { code: "UNKNOWN_CODER", message: `Coder "${coder}" not found` }, 404);
23933
+ return;
23934
+ }
23935
+ if (!body || !body.profileName) {
23936
+ sendError(res, { code: "INVALID_PARAMS", message: "profileName is required" }, 400);
23937
+ return;
23938
+ }
23939
+ try {
23940
+ await setActiveProfileForCoder(coder, body.profileName);
23941
+ const profile = await getActiveProfileForCoder(coder);
23942
+ sendJson(res, { activeProfile: profile ? sanitizeProfile(profile) : null });
23943
+ } catch (error46) {
23944
+ sendError(res, { code: "SWITCH_FAILED", message: error46 instanceof Error ? error46.message : "Failed to switch profile" }, 500);
23945
+ }
23946
+ }
23947
+ async function applyProfile(req, res, params) {
23948
+ const { coder } = params;
23949
+ if (!coder) {
23950
+ sendError(res, { code: "INVALID_PARAMS", message: "Coder ID is required" }, 400);
23951
+ return;
23952
+ }
23953
+ if (!CODER_REGISTRY[coder]) {
23954
+ sendError(res, { code: "UNKNOWN_CODER", message: `Coder "${coder}" not found` }, 404);
23955
+ return;
23956
+ }
23957
+ const profile = await getActiveProfileForCoder(coder);
23958
+ if (!profile) {
23959
+ sendError(res, { code: "NO_ACTIVE_PROFILE", message: `No active profile for coder "${coder}"` }, 400);
23960
+ return;
23961
+ }
23962
+ try {
23963
+ const adapter = getAdapter(coder);
23964
+ await adapter.apply(profile);
23965
+ sendJson(res, { success: true, message: `Profile applied to ${coder}` });
23966
+ } catch (error46) {
23967
+ sendError(res, { code: "APPLY_FAILED", message: error46 instanceof Error ? error46.message : "Failed to apply profile" }, 500);
23968
+ }
23969
+ }
23970
+ async function verifyConfig(req, res, params) {
23971
+ const { coder } = params;
23972
+ if (!coder) {
23973
+ sendError(res, { code: "INVALID_PARAMS", message: "Coder ID is required" }, 400);
23974
+ return;
23975
+ }
23976
+ if (!CODER_REGISTRY[coder]) {
23977
+ sendError(res, { code: "UNKNOWN_CODER", message: `Coder "${coder}" not found` }, 404);
23978
+ return;
23979
+ }
23980
+ const profile = await getActiveProfileForCoder(coder);
23981
+ if (!profile) {
23982
+ sendJson(res, { verified: false, message: "No active profile" });
23983
+ return;
23984
+ }
23985
+ try {
23986
+ const adapter = getAdapter(coder);
23987
+ const verified = await adapter.verify(profile);
23988
+ sendJson(res, { verified, message: verified ? "Configuration verified" : "Verification failed" });
23989
+ } catch (error46) {
23990
+ sendJson(res, { verified: false, message: error46 instanceof Error ? error46.message : "Verification failed" });
23991
+ }
23992
+ }
23993
+
23994
+ // src/server/api/config.ts
23995
+ init_meta();
23996
+ init_versions2();
23997
+ init_paths();
23998
+ import { existsSync as existsSync7, statSync } from "node:fs";
23999
+ import { readFile as readFile7, writeFile as writeFile7, unlink } from "node:fs/promises";
24000
+ import { join as join5 } from "node:path";
24001
+
24002
+ // src/config/export.ts
24003
+ init_types();
24004
+ init_manager();
24005
+ init_constants();
24006
+ import { existsSync as existsSync6 } from "node:fs";
24007
+ import { readFile as readFile6, writeFile as writeFile6 } from "node:fs/promises";
24008
+ function sanitizeApiKey(apiKey) {
24009
+ if (apiKey.length <= API_KEY_FORMAT.sanitizeLength) {
24010
+ return "***";
24011
+ }
24012
+ const start = apiKey.slice(0, API_KEY_FORMAT.prefixLength);
24013
+ const end = apiKey.slice(-API_KEY_FORMAT.suffixLength);
23348
24014
  return `${start}***${end}`;
23349
24015
  }
23350
24016
  async function exportConfig(filePath, options = {}) {
@@ -23422,90 +24088,266 @@ async function importConfig(filePath, options = {}) {
23422
24088
  return { imported, skipped, errors: errors3 };
23423
24089
  }
23424
24090
 
24091
+ // src/server/api/config.ts
24092
+ async function getVersion(req, res) {
24093
+ sendJson(res, {
24094
+ appVersion: APP_VERSION,
24095
+ configVersion: CONFIG_VERSION,
24096
+ exportVersion: EXPORT_VERSION
24097
+ });
24098
+ }
24099
+ async function getConfigMeta(req, res) {
24100
+ const configPath = getConfigPath("swixter");
24101
+ if (!existsSync7(configPath)) {
24102
+ sendJson(res, {
24103
+ exists: false,
24104
+ profiles: [],
24105
+ mtime: null,
24106
+ size: 0
24107
+ });
24108
+ return;
24109
+ }
24110
+ try {
24111
+ const stats = statSync(configPath);
24112
+ const etag = generateETag(stats.mtime, stats.size);
24113
+ const ifNoneMatch = parseIfNoneMatch(req.headers["if-none-match"]);
24114
+ if (ifNoneMatch === etag) {
24115
+ res.statusCode = 304;
24116
+ res.end();
24117
+ return;
24118
+ }
24119
+ setETagHeaders(res, stats.mtime, stats.size);
24120
+ const { listProfiles: listProfiles3 } = await Promise.resolve().then(() => (init_manager(), exports_manager));
24121
+ const profiles = await listProfiles3();
24122
+ sendJson(res, {
24123
+ exists: true,
24124
+ profiles: profiles.map((p2) => ({
24125
+ name: p2.name,
24126
+ providerId: p2.providerId,
24127
+ updatedAt: p2.updatedAt
24128
+ })),
24129
+ mtime: stats.mtime.toISOString(),
24130
+ size: stats.size,
24131
+ etag
24132
+ });
24133
+ } catch (error46) {
24134
+ sendError(res, { code: "STAT_FAILED", message: "Failed to read config metadata" }, 500);
24135
+ }
24136
+ }
24137
+ async function exportConfigFile(req, res) {
24138
+ try {
24139
+ const configPath = getConfigPath("swixter");
24140
+ const content = await readFile7(configPath, "utf-8");
24141
+ res.setHeader("Content-Type", "application/json");
24142
+ res.setHeader("Content-Disposition", 'attachment; filename="swixter-config.json"');
24143
+ res.statusCode = 200;
24144
+ res.end(content);
24145
+ } catch (error46) {
24146
+ sendError(res, { code: "EXPORT_FAILED", message: "Failed to export configuration" }, 500);
24147
+ }
24148
+ }
24149
+ async function importConfigFile(req, res) {
24150
+ const body = req.body;
24151
+ if (!body || !body.config) {
24152
+ sendError(res, { code: "INVALID_PARAMS", message: "config is required" }, 400);
24153
+ return;
24154
+ }
24155
+ try {
24156
+ const tempDir = getConfigDir("swixter");
24157
+ const tempPath = join5(tempDir, `.import-${Date.now()}.json`);
24158
+ await writeFile7(tempPath, JSON.stringify(body.config), "utf-8");
24159
+ try {
24160
+ const result = await importConfig(tempPath, { overwrite: body.overwrite !== false });
24161
+ sendJson(res, { success: true, ...result });
24162
+ } finally {
24163
+ try {
24164
+ await unlink(tempPath);
24165
+ } catch {}
24166
+ }
24167
+ } catch (error46) {
24168
+ sendError(res, { code: "IMPORT_FAILED", message: error46 instanceof Error ? error46.message : "Failed to import configuration" }, 500);
24169
+ }
24170
+ }
24171
+
24172
+ // src/server/index.ts
24173
+ var __dirname2 = dirname7(fileURLToPath(import.meta.url));
24174
+ async function findAvailablePort(startPort = 3141) {
24175
+ const net = await import("node:net");
24176
+ return new Promise((resolve) => {
24177
+ const server = net.createServer();
24178
+ server.listen(startPort, "127.0.0.1", () => {
24179
+ const port = server.address().port;
24180
+ server.close(() => resolve(port));
24181
+ });
24182
+ server.on("error", () => {
24183
+ server.close();
24184
+ resolve(findAvailablePort(startPort + 1));
24185
+ });
24186
+ });
24187
+ }
24188
+ function openBrowser(url2) {
24189
+ const command = process.platform === "win32" ? "start" : process.platform === "darwin" ? "open" : "xdg-open";
24190
+ exec(`${command} ${url2}`, (error46) => {
24191
+ if (error46) {
24192
+ console.warn(import_picocolors11.default.yellow(`Could not open browser automatically: ${error46.message}`));
24193
+ }
24194
+ });
24195
+ }
24196
+ function getUiDir() {
24197
+ const isDev = true;
24198
+ if (isDev) {
24199
+ return join6(__dirname2, "..", "..", "ui", "dist");
24200
+ }
24201
+ return join6(__dirname2, "..", "..", "ui");
24202
+ }
24203
+ async function startServer(portArg) {
24204
+ const port = portArg || await findAvailablePort(3141);
24205
+ const host = "127.0.0.1";
24206
+ const router = new Router;
24207
+ router.use(corsMiddleware);
24208
+ router.use(jsonBodyMiddleware);
24209
+ router.get("/api/profiles", listProfiles2);
24210
+ router.get("/api/profiles/:name", getProfile2);
24211
+ router.post("/api/profiles", createProfile);
24212
+ router.put("/api/profiles/:name", updateProfile);
24213
+ router.delete("/api/profiles/:name", deleteProfile2);
24214
+ router.get("/api/providers", listProviders);
24215
+ router.post("/api/providers", createProvider);
24216
+ router.put("/api/providers/:id", updateProvider);
24217
+ router.delete("/api/providers/:id", deleteProvider);
24218
+ router.get("/api/coders", listCoders);
24219
+ router.get("/api/coders/:coder/active", getActiveProfile2);
24220
+ router.put("/api/coders/:coder/active", setActiveProfile2);
24221
+ router.post("/api/coders/:coder/apply", applyProfile);
24222
+ router.get("/api/coders/:coder/verify", verifyConfig);
24223
+ router.get("/api/version", getVersion);
24224
+ router.get("/api/config", getConfigMeta);
24225
+ router.get("/api/config/export", exportConfigFile);
24226
+ router.post("/api/config/import", importConfigFile);
24227
+ const uiDir = getUiDir();
24228
+ const serveStatic = createStaticServe({ root: uiDir, index: "index.html", spa: true });
24229
+ const server = createServer(async (req, res) => {
24230
+ const url2 = req.url || "";
24231
+ if (url2.startsWith("/api/") || url2 === "/api") {
24232
+ await router.handle(req, res);
24233
+ } else {
24234
+ await serveStatic(req, res);
24235
+ }
24236
+ });
24237
+ server.listen(port, host, () => {
24238
+ const url2 = `http://${host}:${port}`;
24239
+ console.log();
24240
+ console.log(import_picocolors11.default.bold(import_picocolors11.default.cyan("Swixter Web UI")));
24241
+ console.log();
24242
+ console.log(` Server: ${import_picocolors11.default.cyan(url2)}`);
24243
+ console.log(` Press ${import_picocolors11.default.bold("Ctrl+C")} to stop`);
24244
+ console.log();
24245
+ openBrowser(url2);
24246
+ });
24247
+ server.on("error", (error46) => {
24248
+ if (error46.code === "EADDRINUSE") {
24249
+ console.error(import_picocolors11.default.red(`Error: Port ${port} is already in use`));
24250
+ console.log(import_picocolors11.default.dim("Try specifying a different port with --port"));
24251
+ process.exit(1);
24252
+ } else {
24253
+ console.error(import_picocolors11.default.red(`Server error: ${error46.message}`));
24254
+ process.exit(1);
24255
+ }
24256
+ });
24257
+ server.on("close", () => {
24258
+ console.log();
24259
+ console.log(import_picocolors11.default.dim("Server closed"));
24260
+ });
24261
+ return server;
24262
+ }
24263
+
24264
+ // src/cli/ui.ts
24265
+ async function handleUiCommand(args) {
24266
+ const port = getPortFromArgs(args);
24267
+ try {
24268
+ const server = await startServer(port);
24269
+ process.on("SIGINT", () => {
24270
+ console.log();
24271
+ console.log(import_picocolors12.default.dim("Shutting down..."));
24272
+ server.close(() => {
24273
+ process.exit(0);
24274
+ });
24275
+ });
24276
+ process.stdin.resume();
24277
+ } catch (error46) {
24278
+ console.error(import_picocolors12.default.red(`Failed to start server: ${error46}`));
24279
+ process.exit(1);
24280
+ }
24281
+ }
24282
+ function getPortFromArgs(args) {
24283
+ if (!args || args.length === 0) {
24284
+ return;
24285
+ }
24286
+ for (let i2 = 0;i2 < args.length; i2++) {
24287
+ const arg = args[i2];
24288
+ if (arg === "--port" || arg === "-p") {
24289
+ const portStr = args[i2 + 1];
24290
+ if (!portStr) {
24291
+ console.error(import_picocolors12.default.red("Error: --port requires a value"));
24292
+ process.exit(1);
24293
+ }
24294
+ const port = parseInt(portStr, 10);
24295
+ if (isNaN(port) || port < 1 || port > 65535) {
24296
+ console.error(import_picocolors12.default.red("Error: Invalid port number"));
24297
+ process.exit(1);
24298
+ }
24299
+ return port;
24300
+ }
24301
+ }
24302
+ return;
24303
+ }
24304
+
23425
24305
  // src/cli/help.ts
23426
- var import_picocolors11 = __toESM(require_picocolors(), 1);
24306
+ var import_picocolors13 = __toESM(require_picocolors(), 1);
23427
24307
  function showGlobalHelp() {
23428
24308
  console.log(`
23429
- ${import_picocolors11.default.bold(import_picocolors11.default.cyan("Swixter - AI Coder Configuration Manager"))}
24309
+ ${import_picocolors13.default.bold(import_picocolors13.default.cyan("Swixter - AI Coder Configuration Manager"))}
23430
24310
 
23431
- ${import_picocolors11.default.bold("Usage:")}
23432
- ${import_picocolors11.default.green("swixter <coder> <command> [options]")}
23433
- ${import_picocolors11.default.green("swixter <global-command> [options]")}
24311
+ ${import_picocolors13.default.bold("Usage:")}
24312
+ ${import_picocolors13.default.green("swixter <coder> <command> [options]")}
24313
+ ${import_picocolors13.default.green("swixter <global-command> [options]")}
23434
24314
 
23435
- ${import_picocolors11.default.bold("Supported Coders:")}
23436
- ${import_picocolors11.default.cyan("claude")} ${import_picocolors11.default.dim("Claude Code configuration management")}
23437
- ${import_picocolors11.default.cyan("codex")} ${import_picocolors11.default.dim("Codex configuration management")}
23438
- ${import_picocolors11.default.cyan("qwen")} ${import_picocolors11.default.dim("Continue/Qwen configuration management")}
24315
+ ${import_picocolors13.default.bold("Supported Coders:")}
24316
+ ${import_picocolors13.default.cyan("claude")} ${import_picocolors13.default.dim("Claude Code configuration management")}
24317
+ ${import_picocolors13.default.cyan("codex")} ${import_picocolors13.default.dim("Codex configuration management")}
24318
+ ${import_picocolors13.default.cyan("qwen")} ${import_picocolors13.default.dim("Continue/Qwen configuration management")}
23439
24319
 
23440
- ${import_picocolors11.default.bold("Global Commands:")}
23441
- ${import_picocolors11.default.cyan("providers")} ${import_picocolors11.default.dim("List all available API providers")}
23442
- ${import_picocolors11.default.cyan("export <file>")} ${import_picocolors11.default.dim("Export all configurations to file")}
23443
- ${import_picocolors11.default.cyan("import <file>")} ${import_picocolors11.default.dim("Import configurations from file")}
23444
- ${import_picocolors11.default.cyan("completion <shell>")} ${import_picocolors11.default.dim("Generate shell auto-completion script")}
23445
- ${import_picocolors11.default.cyan("doctor")} ${import_picocolors11.default.dim("Diagnose system configuration")}
23446
- ${import_picocolors11.default.cyan("help")} ${import_picocolors11.default.dim("Show help information")}
23447
- ${import_picocolors11.default.cyan("version")} ${import_picocolors11.default.dim("Show version information")}
24320
+ ${import_picocolors13.default.bold("Web UI:")}
24321
+ ${import_picocolors13.default.cyan("ui")} ${import_picocolors13.default.dim("Launch local Web UI")}
24322
+ ${import_picocolors13.default.dim("swixter ui [--port <port>]")}
24323
+ ${import_picocolors13.default.dim("Start local HTTP server and open browser")}
23448
24324
 
23449
- ${import_picocolors11.default.bold("Examples:")}
23450
- ${import_picocolors11.default.dim("# View Claude Code commands")}
23451
- ${import_picocolors11.default.green("swixter claude --help")}
24325
+ ${import_picocolors13.default.bold("Global Commands:")}
24326
+ ${import_picocolors13.default.cyan("providers")} ${import_picocolors13.default.dim("List all available API providers")}
24327
+ ${import_picocolors13.default.cyan("export <file>")} ${import_picocolors13.default.dim("Export all configurations to file")}
24328
+ ${import_picocolors13.default.cyan("import <file>")} ${import_picocolors13.default.dim("Import configurations from file")}
24329
+ ${import_picocolors13.default.cyan("completion <shell>")} ${import_picocolors13.default.dim("Generate shell auto-completion script")}
24330
+ ${import_picocolors13.default.cyan("help")} ${import_picocolors13.default.dim("Show help information")}
24331
+ ${import_picocolors13.default.cyan("version")} ${import_picocolors13.default.dim("Show version information")}
23452
24332
 
23453
- ${import_picocolors11.default.dim("# Create Claude Code configuration")}
23454
- ${import_picocolors11.default.green("swixter claude create")}
24333
+ ${import_picocolors13.default.bold("Examples:")}
24334
+ ${import_picocolors13.default.dim("# View Claude Code commands")}
24335
+ ${import_picocolors13.default.green("swixter claude --help")}
23455
24336
 
23456
- ${import_picocolors11.default.dim("# View all providers")}
23457
- ${import_picocolors11.default.green("swixter providers")}
24337
+ ${import_picocolors13.default.dim("# Create Claude Code configuration")}
24338
+ ${import_picocolors13.default.green("swixter claude create")}
23458
24339
 
23459
- ${import_picocolors11.default.dim("# Export configurations")}
23460
- ${import_picocolors11.default.green("swixter export my-config.json")}
24340
+ ${import_picocolors13.default.dim("# Launch Web UI")}
24341
+ ${import_picocolors13.default.green("swixter ui")}
23461
24342
 
23462
- ${import_picocolors11.default.dim("# Install bash auto-completion")}
23463
- ${import_picocolors11.default.green("swixter completion bash > ~/.local/share/bash-completion/completions/swixter")}
24343
+ ${import_picocolors13.default.dim("# View all providers")}
24344
+ ${import_picocolors13.default.green("swixter providers")}
23464
24345
 
23465
- ${import_picocolors11.default.dim("Documentation: https://github.com/loonghao/swixter")}
23466
- `);
24346
+ ${import_picocolors13.default.dim("Documentation: https://github.com/dawnswwwww/swixter")}`);
23467
24347
  }
23468
24348
 
23469
24349
  // src/cli/completions.ts
23470
24350
  init_presets();
23471
-
23472
- // src/constants/commands.ts
23473
- var COMMAND_ALIASES = {
23474
- r: "run",
23475
- ls: "list",
23476
- sw: "switch",
23477
- rm: "delete",
23478
- new: "create",
23479
- "create-profile": "create",
23480
- "delete-profile": "delete",
23481
- "list-profiles": "list",
23482
- "switch-profile": "switch"
23483
- };
23484
- var VALID_COMMANDS = [
23485
- "create",
23486
- "list",
23487
- "switch",
23488
- "edit",
23489
- "apply",
23490
- "current",
23491
- "delete",
23492
- "run",
23493
- "install",
23494
- "update-cli",
23495
- "upgrade",
23496
- "doctor"
23497
- ];
23498
- var GLOBAL_COMMANDS = [
23499
- "providers",
23500
- "export",
23501
- "import",
23502
- "completion",
23503
- "doctor",
23504
- "help",
23505
- "version"
23506
- ];
23507
-
23508
- // src/cli/completions.ts
23509
24351
  function generateBashCompletion() {
23510
24352
  const coders2 = ["claude", "qwen", "codex"];
23511
24353
  const commands = [...VALID_COMMANDS];
@@ -23864,37 +24706,37 @@ function generateCompletion(shell) {
23864
24706
  // src/cli/providers.ts
23865
24707
  init_presets();
23866
24708
  init_user_providers();
23867
- var import_picocolors12 = __toESM(require_picocolors(), 1);
24709
+ var import_picocolors14 = __toESM(require_picocolors(), 1);
23868
24710
  init_formatting();
23869
- async function listProviders() {
24711
+ async function listProviders2() {
23870
24712
  console.log();
23871
- Ie(import_picocolors12.default.cyan("Available Providers"));
24713
+ Ie(import_picocolors14.default.cyan("Available Providers"));
23872
24714
  const allPresets2 = await getAllPresets();
23873
24715
  const userProviders = await loadUserProviders();
23874
24716
  const userProviderIds = new Set(userProviders.map((p2) => p2.id));
23875
24717
  const builtInProviderIds = new Set(getBuiltInPresets().map((p2) => p2.id));
23876
24718
  if (allPresets2.length === 0) {
23877
- console.log(import_picocolors12.default.yellow("No providers configured"));
24719
+ console.log(import_picocolors14.default.yellow("No providers configured"));
23878
24720
  console.log();
23879
24721
  return;
23880
24722
  }
23881
24723
  console.log();
23882
- console.log(import_picocolors12.default.bold("Built-in Providers:"));
24724
+ console.log(import_picocolors14.default.bold("Built-in Providers:"));
23883
24725
  allPresets2.filter((p2) => builtInProviderIds.has(p2.id) && !userProviderIds.has(p2.id)).forEach((preset) => {
23884
- console.log(` ${import_picocolors12.default.cyan(preset.id.padEnd(15))} ${import_picocolors12.default.dim("|")} ${preset.displayName.padEnd(30)} ${import_picocolors12.default.dim("|")} ${import_picocolors12.default.yellow(preset.baseURL || "N/A")}`);
24726
+ console.log(` ${import_picocolors14.default.cyan(preset.id.padEnd(15))} ${import_picocolors14.default.dim("|")} ${preset.displayName.padEnd(30)} ${import_picocolors14.default.dim("|")} ${import_picocolors14.default.yellow(preset.baseURL || "N/A")}`);
23885
24727
  });
23886
24728
  const userOnlyProviders = allPresets2.filter((p2) => userProviderIds.has(p2.id));
23887
24729
  if (userOnlyProviders.length > 0) {
23888
24730
  console.log();
23889
- console.log(import_picocolors12.default.bold("User-defined Providers:"));
24731
+ console.log(import_picocolors14.default.bold("User-defined Providers:"));
23890
24732
  userOnlyProviders.forEach((preset) => {
23891
24733
  const isOverride = builtInProviderIds.has(preset.id);
23892
- const marker = isOverride ? import_picocolors12.default.yellow(" (override)") : "";
23893
- console.log(` ${import_picocolors12.default.green(preset.id.padEnd(15))} ${import_picocolors12.default.dim("|")} ${preset.displayName.padEnd(30)} ${import_picocolors12.default.dim("|")} ${import_picocolors12.default.yellow(preset.baseURL || "N/A")}${marker}`);
24734
+ const marker = isOverride ? import_picocolors14.default.yellow(" (override)") : "";
24735
+ console.log(` ${import_picocolors14.default.green(preset.id.padEnd(15))} ${import_picocolors14.default.dim("|")} ${preset.displayName.padEnd(30)} ${import_picocolors14.default.dim("|")} ${import_picocolors14.default.yellow(preset.baseURL || "N/A")}${marker}`);
23894
24736
  });
23895
24737
  }
23896
24738
  console.log();
23897
- console.log(import_picocolors12.default.dim(`Total: ${allPresets2.length} providers`));
24739
+ console.log(import_picocolors14.default.dim(`Total: ${allPresets2.length} providers`));
23898
24740
  console.log();
23899
24741
  }
23900
24742
  async function addProvider(options) {
@@ -23906,7 +24748,7 @@ async function addProvider(options) {
23906
24748
  let models = options.models;
23907
24749
  if (!options.quiet) {
23908
24750
  console.log();
23909
- Ie(import_picocolors12.default.cyan("Add Custom Provider"));
24751
+ Ie(import_picocolors14.default.cyan("Add Custom Provider"));
23910
24752
  const existing = providerId ? await getUserProvider(providerId) : undefined;
23911
24753
  providerId = await he({
23912
24754
  message: "Provider ID (unique identifier, e.g., 'openrouter', 'deepseek')",
@@ -24001,7 +24843,7 @@ async function addProvider(options) {
24001
24843
  try {
24002
24844
  await upsertUserProvider(provider);
24003
24845
  if (!options.quiet) {
24004
- Se(import_picocolors12.default.green(`${MARKERS.success} Provider "${providerId}" added successfully!`));
24846
+ Se(import_picocolors14.default.green(`${MARKERS.success} Provider "${providerId}" added successfully!`));
24005
24847
  } else {
24006
24848
  showSuccess(`Provider "${providerId}" added successfully!`, {
24007
24849
  ID: providerId,
@@ -24020,10 +24862,10 @@ async function removeProvider(providerId, options) {
24020
24862
  showError("Error: Provider ID is required", "Usage: swixter providers remove <provider-id>");
24021
24863
  }
24022
24864
  console.log();
24023
- Ie(import_picocolors12.default.cyan("Remove Custom Provider"));
24865
+ Ie(import_picocolors14.default.cyan("Remove Custom Provider"));
24024
24866
  const userProviders = await loadUserProviders();
24025
24867
  if (userProviders.length === 0) {
24026
- Se(import_picocolors12.default.yellow("No user-defined providers to remove"));
24868
+ Se(import_picocolors14.default.yellow("No user-defined providers to remove"));
24027
24869
  return;
24028
24870
  }
24029
24871
  providerId = await ve({
@@ -24050,7 +24892,7 @@ async function removeProvider(providerId, options) {
24050
24892
  showError(`Error: Provider "${providerId}" not found`, "Use 'swixter providers list' to see all providers");
24051
24893
  }
24052
24894
  if (!options?.quiet) {
24053
- Se(import_picocolors12.default.green(`${MARKERS.success} Provider "${providerId}" removed successfully!`));
24895
+ Se(import_picocolors14.default.green(`${MARKERS.success} Provider "${providerId}" removed successfully!`));
24054
24896
  } else {
24055
24897
  showSuccess(`Provider "${providerId}" removed successfully!`);
24056
24898
  }
@@ -24064,19 +24906,19 @@ async function showProvider(providerId) {
24064
24906
  showError(`Error: Provider "${providerId}" not found`, "Use 'swixter providers list' to see all providers");
24065
24907
  }
24066
24908
  console.log();
24067
- Ie(import_picocolors12.default.cyan(`Provider: ${provider.displayName}`));
24909
+ Ie(import_picocolors14.default.cyan(`Provider: ${provider.displayName}`));
24068
24910
  console.log();
24069
- console.log(` ID: ${import_picocolors12.default.cyan(provider.id)}`);
24070
- console.log(` Name: ${import_picocolors12.default.yellow(provider.name)}`);
24071
- console.log(` Display Name: ${import_picocolors12.default.yellow(provider.displayName)}`);
24072
- console.log(` Base URL: ${import_picocolors12.default.yellow(provider.baseURL)}`);
24073
- console.log(` Auth Type: ${import_picocolors12.default.yellow(provider.authType)}`);
24911
+ console.log(` ID: ${import_picocolors14.default.cyan(provider.id)}`);
24912
+ console.log(` Name: ${import_picocolors14.default.yellow(provider.name)}`);
24913
+ console.log(` Display Name: ${import_picocolors14.default.yellow(provider.displayName)}`);
24914
+ console.log(` Base URL: ${import_picocolors14.default.yellow(provider.baseURL)}`);
24915
+ console.log(` Auth Type: ${import_picocolors14.default.yellow(provider.authType)}`);
24074
24916
  if (provider.defaultModels && provider.defaultModels.length > 0) {
24075
24917
  console.log(` Default Models:`);
24076
- provider.defaultModels.forEach((model) => console.log(` - ${import_picocolors12.default.dim(model)}`));
24918
+ provider.defaultModels.forEach((model) => console.log(` - ${import_picocolors14.default.dim(model)}`));
24077
24919
  }
24078
24920
  if (provider.docs) {
24079
- console.log(` Documentation: ${import_picocolors12.default.blue(provider.docs)}`);
24921
+ console.log(` Documentation: ${import_picocolors14.default.blue(provider.docs)}`);
24080
24922
  }
24081
24923
  console.log();
24082
24924
  }
@@ -24086,7 +24928,7 @@ init_meta();
24086
24928
  init_versions2();
24087
24929
  async function cmdProviders(subcommand, args) {
24088
24930
  if (!subcommand || subcommand === "list" || subcommand === "ls") {
24089
- await listProviders();
24931
+ await listProviders2();
24090
24932
  return;
24091
24933
  }
24092
24934
  if (subcommand === "add" || subcommand === "new") {
@@ -24128,104 +24970,104 @@ async function cmdProviders(subcommand, args) {
24128
24970
  await showProvider(providerId);
24129
24971
  return;
24130
24972
  }
24131
- console.log(import_picocolors13.default.red(`Unknown providers subcommand: ${subcommand}`));
24973
+ console.log(import_picocolors15.default.red(`Unknown providers subcommand: ${subcommand}`));
24132
24974
  console.log();
24133
- console.log(import_picocolors13.default.bold("Available subcommands:"));
24134
- console.log(` ${import_picocolors13.default.cyan("list, ls")} - List all providers`);
24135
- console.log(` ${import_picocolors13.default.cyan("add, new")} - Add a custom provider`);
24136
- console.log(` ${import_picocolors13.default.cyan("remove, rm, delete")} - Remove a custom provider`);
24137
- console.log(` ${import_picocolors13.default.cyan("show, info")} - Show provider details`);
24975
+ console.log(import_picocolors15.default.bold("Available subcommands:"));
24976
+ console.log(` ${import_picocolors15.default.cyan("list, ls")} - List all providers`);
24977
+ console.log(` ${import_picocolors15.default.cyan("add, new")} - Add a custom provider`);
24978
+ console.log(` ${import_picocolors15.default.cyan("remove, rm, delete")} - Remove a custom provider`);
24979
+ console.log(` ${import_picocolors15.default.cyan("show, info")} - Show provider details`);
24138
24980
  console.log();
24139
24981
  process.exit(1);
24140
24982
  }
24141
24983
  async function cmdExport(filePath) {
24142
24984
  if (!filePath) {
24143
- console.log(import_picocolors13.default.red("Error: Please specify export file path"));
24144
- console.log(import_picocolors13.default.dim("Usage: swixter export <file>"));
24985
+ console.log(import_picocolors15.default.red("Error: Please specify export file path"));
24986
+ console.log(import_picocolors15.default.dim("Usage: swixter export <file>"));
24145
24987
  process.exit(1);
24146
24988
  }
24147
24989
  try {
24148
24990
  await exportConfig(filePath, { sanitizeKeys: false });
24149
24991
  console.log();
24150
- console.log(import_picocolors13.default.green("✓") + " Export successful!");
24151
- console.log(` File: ${import_picocolors13.default.cyan(filePath)}`);
24992
+ console.log(import_picocolors15.default.green("✓") + " Export successful!");
24993
+ console.log(` File: ${import_picocolors15.default.cyan(filePath)}`);
24152
24994
  console.log();
24153
24995
  } catch (error46) {
24154
24996
  console.log();
24155
- console.log(import_picocolors13.default.red(`✗ Export failed: ${error46}`));
24997
+ console.log(import_picocolors15.default.red(`✗ Export failed: ${error46}`));
24156
24998
  console.log();
24157
24999
  process.exit(1);
24158
25000
  }
24159
25001
  }
24160
25002
  async function cmdCompletion(shell) {
24161
25003
  if (!shell) {
24162
- console.log(import_picocolors13.default.yellow("Please specify shell type"));
25004
+ console.log(import_picocolors15.default.yellow("Please specify shell type"));
24163
25005
  console.log();
24164
- console.log(import_picocolors13.default.bold("Usage:"));
24165
- console.log(` ${import_picocolors13.default.green("swixter completion <shell>")}`);
25006
+ console.log(import_picocolors15.default.bold("Usage:"));
25007
+ console.log(` ${import_picocolors15.default.green("swixter completion <shell>")}`);
24166
25008
  console.log();
24167
- console.log(import_picocolors13.default.bold("Supported shells:"));
24168
- console.log(` ${import_picocolors13.default.cyan("bash")} - Bash shell`);
24169
- console.log(` ${import_picocolors13.default.cyan("zsh")} - Z shell`);
24170
- console.log(` ${import_picocolors13.default.cyan("fish")} - Fish shell`);
25009
+ console.log(import_picocolors15.default.bold("Supported shells:"));
25010
+ console.log(` ${import_picocolors15.default.cyan("bash")} - Bash shell`);
25011
+ console.log(` ${import_picocolors15.default.cyan("zsh")} - Z shell`);
25012
+ console.log(` ${import_picocolors15.default.cyan("fish")} - Fish shell`);
24171
25013
  console.log();
24172
- console.log(import_picocolors13.default.bold("Examples:"));
24173
- console.log(` ${import_picocolors13.default.green("swixter completion bash > ~/.local/share/bash-completion/completions/swixter")}`);
24174
- console.log(` ${import_picocolors13.default.green("swixter completion zsh > ~/.zfunc/_swixter")}`);
24175
- console.log(` ${import_picocolors13.default.green("swixter completion fish > ~/.config/fish/completions/swixter.fish")}`);
25014
+ console.log(import_picocolors15.default.bold("Examples:"));
25015
+ console.log(` ${import_picocolors15.default.green("swixter completion bash > ~/.local/share/bash-completion/completions/swixter")}`);
25016
+ console.log(` ${import_picocolors15.default.green("swixter completion zsh > ~/.zfunc/_swixter")}`);
25017
+ console.log(` ${import_picocolors15.default.green("swixter completion fish > ~/.config/fish/completions/swixter.fish")}`);
24176
25018
  process.exit(1);
24177
25019
  }
24178
25020
  const supportedShells = ["bash", "zsh", "fish"];
24179
25021
  if (!supportedShells.includes(shell)) {
24180
- console.log(import_picocolors13.default.red(`Unsupported shell: ${shell}`));
24181
- console.log(import_picocolors13.default.dim(`Supported shells: ${supportedShells.join(", ")}`));
25022
+ console.log(import_picocolors15.default.red(`Unsupported shell: ${shell}`));
25023
+ console.log(import_picocolors15.default.dim(`Supported shells: ${supportedShells.join(", ")}`));
24182
25024
  process.exit(1);
24183
25025
  }
24184
25026
  try {
24185
25027
  const script = generateCompletion(shell);
24186
25028
  console.log(script);
24187
25029
  } catch (error46) {
24188
- console.error(import_picocolors13.default.red("Failed to generate completion script:"), error46);
25030
+ console.error(import_picocolors15.default.red("Failed to generate completion script:"), error46);
24189
25031
  process.exit(1);
24190
25032
  }
24191
25033
  }
24192
25034
  async function cmdImport(filePath) {
24193
25035
  if (!filePath) {
24194
- console.log(import_picocolors13.default.red("Error: Please specify import file path"));
24195
- console.log(import_picocolors13.default.dim("Usage: swixter import <file>"));
25036
+ console.log(import_picocolors15.default.red("Error: Please specify import file path"));
25037
+ console.log(import_picocolors15.default.dim("Usage: swixter import <file>"));
24196
25038
  process.exit(1);
24197
25039
  }
24198
25040
  try {
24199
25041
  const result = await importConfig(filePath, { overwrite: false });
24200
25042
  console.log();
24201
- console.log(import_picocolors13.default.green("✓") + " Import completed!");
25043
+ console.log(import_picocolors15.default.green("✓") + " Import completed!");
24202
25044
  console.log();
24203
- console.log(` Successfully imported: ${import_picocolors13.default.green(result.imported)} items`);
24204
- console.log(` Skipped: ${import_picocolors13.default.yellow(result.skipped)} items`);
24205
- console.log(` Errors: ${import_picocolors13.default.red(result.errors.length)} items`);
25045
+ console.log(` Successfully imported: ${import_picocolors15.default.green(result.imported)} items`);
25046
+ console.log(` Skipped: ${import_picocolors15.default.yellow(result.skipped)} items`);
25047
+ console.log(` Errors: ${import_picocolors15.default.red(result.errors.length)} items`);
24206
25048
  console.log();
24207
25049
  if (result.errors.length > 0) {
24208
- console.log(import_picocolors13.default.red("Error details:"));
24209
- result.errors.forEach((err) => console.log(import_picocolors13.default.red(` - ${err}`)));
25050
+ console.log(import_picocolors15.default.red("Error details:"));
25051
+ result.errors.forEach((err) => console.log(import_picocolors15.default.red(` - ${err}`)));
24210
25052
  console.log();
24211
25053
  }
24212
25054
  } catch (error46) {
24213
25055
  console.log();
24214
- console.log(import_picocolors13.default.red(`✗ Import failed: ${error46}`));
25056
+ console.log(import_picocolors15.default.red(`✗ Import failed: ${error46}`));
24215
25057
  console.log();
24216
25058
  process.exit(1);
24217
25059
  }
24218
25060
  }
24219
25061
  async function cmdVersion() {
24220
25062
  console.log();
24221
- console.log(import_picocolors13.default.bold(import_picocolors13.default.cyan("Swixter")) + import_picocolors13.default.dim(" - AI Coder Configuration Manager"));
25063
+ console.log(import_picocolors15.default.bold(import_picocolors15.default.cyan("Swixter")) + import_picocolors15.default.dim(" - AI Coder Configuration Manager"));
24222
25064
  console.log();
24223
- console.log(` ${import_picocolors13.default.bold("Version:")} ${import_picocolors13.default.green(APP_VERSION)}`);
24224
- console.log(` ${import_picocolors13.default.bold("Config Version:")} ${import_picocolors13.default.cyan(CONFIG_VERSION)}`);
24225
- console.log(` ${import_picocolors13.default.bold("Export Version:")} ${import_picocolors13.default.cyan(EXPORT_VERSION)}`);
25065
+ console.log(` ${import_picocolors15.default.bold("Version:")} ${import_picocolors15.default.green(APP_VERSION)}`);
25066
+ console.log(` ${import_picocolors15.default.bold("Config Version:")} ${import_picocolors15.default.cyan(CONFIG_VERSION)}`);
25067
+ console.log(` ${import_picocolors15.default.bold("Export Version:")} ${import_picocolors15.default.cyan(EXPORT_VERSION)}`);
24226
25068
  console.log();
24227
- console.log(import_picocolors13.default.dim(" GitHub: https://github.com/dawnswwwww/swixter"));
24228
- console.log(import_picocolors13.default.dim(" NPM: https://www.npmjs.com/package/swixter"));
25069
+ console.log(import_picocolors15.default.dim(" GitHub: https://github.com/dawnswwwww/swixter"));
25070
+ console.log(import_picocolors15.default.dim(" NPM: https://www.npmjs.com/package/swixter"));
24229
25071
  console.log();
24230
25072
  }
24231
25073
  async function main() {
@@ -24236,6 +25078,10 @@ async function main() {
24236
25078
  showGlobalHelp();
24237
25079
  return;
24238
25080
  }
25081
+ if (firstArg === "ui") {
25082
+ await handleUiCommand(args.slice(1));
25083
+ return;
25084
+ }
24239
25085
  if (firstArg === "claude") {
24240
25086
  await handleClaudeCommand(args.slice(1));
24241
25087
  return;
@@ -24268,11 +25114,11 @@ async function main() {
24268
25114
  await cmdVersion();
24269
25115
  return;
24270
25116
  }
24271
- console.log(import_picocolors13.default.red(`Unknown command: ${firstArg}`));
24272
- console.log(import_picocolors13.default.dim("Run 'swixter --help' for help"));
25117
+ console.log(import_picocolors15.default.red(`Unknown command: ${firstArg}`));
25118
+ console.log(import_picocolors15.default.dim("Run 'swixter --help' for help"));
24273
25119
  process.exit(1);
24274
25120
  } catch (error46) {
24275
- console.error(import_picocolors13.default.red("An error occurred:"), error46);
25121
+ console.error(import_picocolors15.default.red("An error occurred:"), error46);
24276
25122
  process.exit(1);
24277
25123
  }
24278
25124
  }