swixter 0.0.9 → 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.
- package/README.md +7 -2
- package/dist/cli/index.js +1028 -174
- 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: (
|
|
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: (
|
|
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) => {
|
|
@@ -13164,6 +13184,10 @@ function getConfigPath(type) {
|
|
|
13164
13184
|
const config2 = PATH_CONFIG[type];
|
|
13165
13185
|
return join(homedir(), config2.dir, config2.file);
|
|
13166
13186
|
}
|
|
13187
|
+
function getConfigDir(type) {
|
|
13188
|
+
const config2 = PATH_CONFIG[type];
|
|
13189
|
+
return join(homedir(), config2.dir);
|
|
13190
|
+
}
|
|
13167
13191
|
var PATH_CONFIG;
|
|
13168
13192
|
var init_paths = __esm(() => {
|
|
13169
13193
|
PATH_CONFIG = {
|
|
@@ -13237,7 +13261,7 @@ var CONFIG_VERSION = "2.0.0", EXPORT_VERSION = "1.0.0";
|
|
|
13237
13261
|
var init_versions2 = () => {};
|
|
13238
13262
|
|
|
13239
13263
|
// src/constants/meta.ts
|
|
13240
|
-
var APP_VERSION = "0.0.
|
|
13264
|
+
var APP_VERSION = "0.0.10";
|
|
13241
13265
|
var init_meta = () => {};
|
|
13242
13266
|
|
|
13243
13267
|
// src/constants/install.ts
|
|
@@ -13533,6 +13557,42 @@ var init_presets = __esm(() => {
|
|
|
13533
13557
|
allPresets = builtInPresets;
|
|
13534
13558
|
});
|
|
13535
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
|
+
|
|
13536
13596
|
// src/adapters/claude.ts
|
|
13537
13597
|
import { existsSync as existsSync2 } from "node:fs";
|
|
13538
13598
|
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "node:fs/promises";
|
|
@@ -13555,29 +13615,7 @@ class ClaudeCodeAdapter {
|
|
|
13555
13615
|
}
|
|
13556
13616
|
}
|
|
13557
13617
|
const envVars = this.coderConfig.envVarMapping;
|
|
13558
|
-
const newEnv =
|
|
13559
|
-
[envVars.baseURL]: baseURL
|
|
13560
|
-
};
|
|
13561
|
-
if (profile.apiKey) {
|
|
13562
|
-
newEnv[envVars.apiKey] = profile.apiKey;
|
|
13563
|
-
}
|
|
13564
|
-
if (profile.authToken && envVars.authToken) {
|
|
13565
|
-
newEnv[envVars.authToken] = profile.authToken;
|
|
13566
|
-
}
|
|
13567
|
-
if (profile.models) {
|
|
13568
|
-
if (profile.models.anthropicModel && envVars.anthropicModel) {
|
|
13569
|
-
newEnv[envVars.anthropicModel] = profile.models.anthropicModel;
|
|
13570
|
-
}
|
|
13571
|
-
if (profile.models.defaultHaikuModel && envVars.defaultHaikuModel) {
|
|
13572
|
-
newEnv[envVars.defaultHaikuModel] = profile.models.defaultHaikuModel;
|
|
13573
|
-
}
|
|
13574
|
-
if (profile.models.defaultOpusModel && envVars.defaultOpusModel) {
|
|
13575
|
-
newEnv[envVars.defaultOpusModel] = profile.models.defaultOpusModel;
|
|
13576
|
-
}
|
|
13577
|
-
if (profile.models.defaultSonnetModel && envVars.defaultSonnetModel) {
|
|
13578
|
-
newEnv[envVars.defaultSonnetModel] = profile.models.defaultSonnetModel;
|
|
13579
|
-
}
|
|
13580
|
-
}
|
|
13618
|
+
const newEnv = buildProfileEnv(profile, envVars, baseURL);
|
|
13581
13619
|
const managedKeys = Object.values(envVars).filter(Boolean);
|
|
13582
13620
|
const preservedEnv = {};
|
|
13583
13621
|
if (existingConfig.env) {
|
|
@@ -13605,25 +13643,13 @@ class ClaudeCodeAdapter {
|
|
|
13605
13643
|
const preset = await getPresetByIdAsync(profile.providerId);
|
|
13606
13644
|
const expectedBaseURL = profile.baseURL || preset?.baseURL || "";
|
|
13607
13645
|
const envVars = this.coderConfig.envVarMapping;
|
|
13608
|
-
const
|
|
13609
|
-
const
|
|
13610
|
-
|
|
13611
|
-
|
|
13612
|
-
if (profile.models.anthropicModel && envVars.anthropicModel) {
|
|
13613
|
-
hasMatchingModels = hasMatchingModels && config2.env?.[envVars.anthropicModel] === profile.models.anthropicModel;
|
|
13614
|
-
}
|
|
13615
|
-
if (profile.models.defaultHaikuModel && envVars.defaultHaikuModel) {
|
|
13616
|
-
hasMatchingModels = hasMatchingModels && config2.env?.[envVars.defaultHaikuModel] === profile.models.defaultHaikuModel;
|
|
13617
|
-
}
|
|
13618
|
-
if (profile.models.defaultOpusModel && envVars.defaultOpusModel) {
|
|
13619
|
-
hasMatchingModels = hasMatchingModels && config2.env?.[envVars.defaultOpusModel] === profile.models.defaultOpusModel;
|
|
13620
|
-
}
|
|
13621
|
-
if (profile.models.defaultSonnetModel && envVars.defaultSonnetModel) {
|
|
13622
|
-
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;
|
|
13623
13650
|
}
|
|
13624
13651
|
}
|
|
13625
|
-
|
|
13626
|
-
return (noCredentials || hasApiKey || hasAuthToken) && config2.env?.[envVars.baseURL] === expectedBaseURL && hasMatchingModels;
|
|
13652
|
+
return Object.keys(expectedEnv).length > 0;
|
|
13627
13653
|
} catch (error46) {
|
|
13628
13654
|
return false;
|
|
13629
13655
|
}
|
|
@@ -16247,14 +16273,6 @@ var init_js_yaml = __esm(() => {
|
|
|
16247
16273
|
safeDump = renamed("safeDump", "dump");
|
|
16248
16274
|
});
|
|
16249
16275
|
|
|
16250
|
-
// src/utils/model-helper.ts
|
|
16251
|
-
function getOpenAIModel(profile) {
|
|
16252
|
-
if (profile.models) {
|
|
16253
|
-
return;
|
|
16254
|
-
}
|
|
16255
|
-
return profile.model || profile.openaiModel;
|
|
16256
|
-
}
|
|
16257
|
-
|
|
16258
16276
|
// src/adapters/continue.ts
|
|
16259
16277
|
import { existsSync as existsSync3 } from "node:fs";
|
|
16260
16278
|
import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3 } from "node:fs/promises";
|
|
@@ -17701,6 +17719,21 @@ var init_adapters = __esm(() => {
|
|
|
17701
17719
|
});
|
|
17702
17720
|
|
|
17703
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
|
+
});
|
|
17704
17737
|
import { existsSync as existsSync5 } from "node:fs";
|
|
17705
17738
|
import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile5 } from "node:fs/promises";
|
|
17706
17739
|
import { dirname as dirname5 } from "node:path";
|
|
@@ -17758,6 +17791,9 @@ async function saveConfig(config2) {
|
|
|
17758
17791
|
throw new Error(`Failed to save configuration: ${error46}`);
|
|
17759
17792
|
}
|
|
17760
17793
|
}
|
|
17794
|
+
async function getActiveProfile() {
|
|
17795
|
+
return getActiveProfileForCoder("claude");
|
|
17796
|
+
}
|
|
17761
17797
|
async function getActiveProfileForCoder(coder) {
|
|
17762
17798
|
const config2 = await loadConfig();
|
|
17763
17799
|
const coderConfig = config2.coders[coder];
|
|
@@ -17766,6 +17802,9 @@ async function getActiveProfileForCoder(coder) {
|
|
|
17766
17802
|
}
|
|
17767
17803
|
return config2.profiles[coderConfig.activeProfile];
|
|
17768
17804
|
}
|
|
17805
|
+
async function setActiveProfile(profileName) {
|
|
17806
|
+
return setActiveProfileForCoder("claude", profileName);
|
|
17807
|
+
}
|
|
17769
17808
|
async function setActiveProfileForCoder(coder, profileName) {
|
|
17770
17809
|
const config2 = await loadConfig();
|
|
17771
17810
|
if (!config2.profiles[profileName]) {
|
|
@@ -17823,6 +17862,14 @@ async function listProfiles() {
|
|
|
17823
17862
|
const config2 = await loadConfig();
|
|
17824
17863
|
return Object.values(config2.profiles);
|
|
17825
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
|
+
}
|
|
17826
17873
|
var init_manager = __esm(() => {
|
|
17827
17874
|
init_types();
|
|
17828
17875
|
init_constants();
|
|
@@ -19614,7 +19661,7 @@ var require_semver2 = __commonJS((exports, module) => {
|
|
|
19614
19661
|
});
|
|
19615
19662
|
|
|
19616
19663
|
// src/cli/index.ts
|
|
19617
|
-
var
|
|
19664
|
+
var import_picocolors15 = __toESM(require_picocolors(), 1);
|
|
19618
19665
|
|
|
19619
19666
|
// node_modules/@clack/core/dist/index.mjs
|
|
19620
19667
|
var import_sisteransi = __toESM(require_src(), 1);
|
|
@@ -20336,7 +20383,8 @@ var FLAG_ALIASES = {
|
|
|
20336
20383
|
"-o": "--output",
|
|
20337
20384
|
"-i": "--input",
|
|
20338
20385
|
"-y": "--yes",
|
|
20339
|
-
"-v": "--verbose"
|
|
20386
|
+
"-v": "--verbose",
|
|
20387
|
+
"-P": "--port"
|
|
20340
20388
|
};
|
|
20341
20389
|
var VALID_COMMANDS = [
|
|
20342
20390
|
"create",
|
|
@@ -20357,7 +20405,8 @@ var GLOBAL_COMMANDS = [
|
|
|
20357
20405
|
"import",
|
|
20358
20406
|
"completion",
|
|
20359
20407
|
"help",
|
|
20360
|
-
"version"
|
|
20408
|
+
"version",
|
|
20409
|
+
"ui"
|
|
20361
20410
|
];
|
|
20362
20411
|
function resolveFlagAlias(flag) {
|
|
20363
20412
|
return FLAG_ALIASES[flag] || flag;
|
|
@@ -21682,15 +21731,7 @@ async function cmdRun(args) {
|
|
|
21682
21731
|
env[key] = value;
|
|
21683
21732
|
}
|
|
21684
21733
|
}
|
|
21685
|
-
|
|
21686
|
-
env.ANTHROPIC_API_KEY = profile.apiKey;
|
|
21687
|
-
}
|
|
21688
|
-
if (profile.authToken) {
|
|
21689
|
-
env.ANTHROPIC_AUTH_TOKEN = profile.authToken;
|
|
21690
|
-
}
|
|
21691
|
-
if (baseURL) {
|
|
21692
|
-
env.ANTHROPIC_BASE_URL = baseURL;
|
|
21693
|
-
}
|
|
21734
|
+
Object.assign(env, buildProfileEnv(profile, CODER_CONFIG.envVarMapping, baseURL));
|
|
21694
21735
|
const claudeArgs = args.filter((arg, idx) => {
|
|
21695
21736
|
if (arg === "--profile") {
|
|
21696
21737
|
return false;
|
|
@@ -22420,15 +22461,7 @@ async function cmdRun2(args) {
|
|
|
22420
22461
|
env[key] = value;
|
|
22421
22462
|
}
|
|
22422
22463
|
}
|
|
22423
|
-
|
|
22424
|
-
env.OPENAI_API_KEY = profile.apiKey;
|
|
22425
|
-
}
|
|
22426
|
-
if (baseURL) {
|
|
22427
|
-
env.OPENAI_BASE_URL = baseURL;
|
|
22428
|
-
}
|
|
22429
|
-
if (profile.model || profile.openaiModel) {
|
|
22430
|
-
env.OPENAI_MODEL = profile.model || profile.openaiModel;
|
|
22431
|
-
}
|
|
22464
|
+
Object.assign(env, buildProfileEnv(profile, CODER_CONFIG2.envVarMapping, baseURL));
|
|
22432
22465
|
const qwenArgs = [];
|
|
22433
22466
|
if (profile.apiKey) {
|
|
22434
22467
|
qwenArgs.push("--openai-api-key", profile.apiKey);
|
|
@@ -23316,12 +23349,9 @@ async function cmdRun3(args) {
|
|
|
23316
23349
|
env[key] = value;
|
|
23317
23350
|
}
|
|
23318
23351
|
}
|
|
23319
|
-
|
|
23320
|
-
|
|
23321
|
-
}
|
|
23322
|
-
if (profile.model || profile.openaiModel) {
|
|
23323
|
-
env["OPENAI_MODEL"] = profile.model || profile.openaiModel;
|
|
23324
|
-
}
|
|
23352
|
+
Object.assign(env, buildProfileEnv(profile, CODER_CONFIG3.envVarMapping, "", {
|
|
23353
|
+
apiKeyEnvName: envKey
|
|
23354
|
+
}));
|
|
23325
23355
|
const codexArgs = args.filter((arg, idx) => {
|
|
23326
23356
|
if (arg === "--profile") {
|
|
23327
23357
|
return false;
|
|
@@ -23364,6 +23394,611 @@ async function cmdUpdate3(args) {
|
|
|
23364
23394
|
await handleUpdateCommand(CODER_NAME3, CODER_CONFIG3, args);
|
|
23365
23395
|
}
|
|
23366
23396
|
|
|
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;
|
|
23420
|
+
}
|
|
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
|
+
|
|
23367
24002
|
// src/config/export.ts
|
|
23368
24003
|
init_types();
|
|
23369
24004
|
init_manager();
|
|
@@ -23453,47 +24088,262 @@ async function importConfig(filePath, options = {}) {
|
|
|
23453
24088
|
return { imported, skipped, errors: errors3 };
|
|
23454
24089
|
}
|
|
23455
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
|
+
|
|
23456
24305
|
// src/cli/help.ts
|
|
23457
|
-
var
|
|
24306
|
+
var import_picocolors13 = __toESM(require_picocolors(), 1);
|
|
23458
24307
|
function showGlobalHelp() {
|
|
23459
24308
|
console.log(`
|
|
23460
|
-
${
|
|
24309
|
+
${import_picocolors13.default.bold(import_picocolors13.default.cyan("Swixter - AI Coder Configuration Manager"))}
|
|
23461
24310
|
|
|
23462
|
-
${
|
|
23463
|
-
${
|
|
23464
|
-
${
|
|
24311
|
+
${import_picocolors13.default.bold("Usage:")}
|
|
24312
|
+
${import_picocolors13.default.green("swixter <coder> <command> [options]")}
|
|
24313
|
+
${import_picocolors13.default.green("swixter <global-command> [options]")}
|
|
23465
24314
|
|
|
23466
|
-
${
|
|
23467
|
-
${
|
|
23468
|
-
${
|
|
23469
|
-
${
|
|
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")}
|
|
23470
24319
|
|
|
23471
|
-
${
|
|
23472
|
-
${
|
|
23473
|
-
|
|
23474
|
-
|
|
23475
|
-
${import_picocolors11.default.cyan("completion <shell>")} ${import_picocolors11.default.dim("Generate shell auto-completion script")}
|
|
23476
|
-
${import_picocolors11.default.cyan("help")} ${import_picocolors11.default.dim("Show help information")}
|
|
23477
|
-
${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")}
|
|
23478
24324
|
|
|
23479
|
-
${
|
|
23480
|
-
${
|
|
23481
|
-
${
|
|
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")}
|
|
23482
24332
|
|
|
23483
|
-
|
|
23484
|
-
${
|
|
24333
|
+
${import_picocolors13.default.bold("Examples:")}
|
|
24334
|
+
${import_picocolors13.default.dim("# View Claude Code commands")}
|
|
24335
|
+
${import_picocolors13.default.green("swixter claude --help")}
|
|
23485
24336
|
|
|
23486
|
-
${
|
|
23487
|
-
${
|
|
24337
|
+
${import_picocolors13.default.dim("# Create Claude Code configuration")}
|
|
24338
|
+
${import_picocolors13.default.green("swixter claude create")}
|
|
23488
24339
|
|
|
23489
|
-
${
|
|
23490
|
-
${
|
|
24340
|
+
${import_picocolors13.default.dim("# Launch Web UI")}
|
|
24341
|
+
${import_picocolors13.default.green("swixter ui")}
|
|
23491
24342
|
|
|
23492
|
-
${
|
|
23493
|
-
${
|
|
24343
|
+
${import_picocolors13.default.dim("# View all providers")}
|
|
24344
|
+
${import_picocolors13.default.green("swixter providers")}
|
|
23494
24345
|
|
|
23495
|
-
${
|
|
23496
|
-
`);
|
|
24346
|
+
${import_picocolors13.default.dim("Documentation: https://github.com/dawnswwwww/swixter")}`);
|
|
23497
24347
|
}
|
|
23498
24348
|
|
|
23499
24349
|
// src/cli/completions.ts
|
|
@@ -23856,37 +24706,37 @@ function generateCompletion(shell) {
|
|
|
23856
24706
|
// src/cli/providers.ts
|
|
23857
24707
|
init_presets();
|
|
23858
24708
|
init_user_providers();
|
|
23859
|
-
var
|
|
24709
|
+
var import_picocolors14 = __toESM(require_picocolors(), 1);
|
|
23860
24710
|
init_formatting();
|
|
23861
|
-
async function
|
|
24711
|
+
async function listProviders2() {
|
|
23862
24712
|
console.log();
|
|
23863
|
-
Ie(
|
|
24713
|
+
Ie(import_picocolors14.default.cyan("Available Providers"));
|
|
23864
24714
|
const allPresets2 = await getAllPresets();
|
|
23865
24715
|
const userProviders = await loadUserProviders();
|
|
23866
24716
|
const userProviderIds = new Set(userProviders.map((p2) => p2.id));
|
|
23867
24717
|
const builtInProviderIds = new Set(getBuiltInPresets().map((p2) => p2.id));
|
|
23868
24718
|
if (allPresets2.length === 0) {
|
|
23869
|
-
console.log(
|
|
24719
|
+
console.log(import_picocolors14.default.yellow("No providers configured"));
|
|
23870
24720
|
console.log();
|
|
23871
24721
|
return;
|
|
23872
24722
|
}
|
|
23873
24723
|
console.log();
|
|
23874
|
-
console.log(
|
|
24724
|
+
console.log(import_picocolors14.default.bold("Built-in Providers:"));
|
|
23875
24725
|
allPresets2.filter((p2) => builtInProviderIds.has(p2.id) && !userProviderIds.has(p2.id)).forEach((preset) => {
|
|
23876
|
-
console.log(` ${
|
|
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")}`);
|
|
23877
24727
|
});
|
|
23878
24728
|
const userOnlyProviders = allPresets2.filter((p2) => userProviderIds.has(p2.id));
|
|
23879
24729
|
if (userOnlyProviders.length > 0) {
|
|
23880
24730
|
console.log();
|
|
23881
|
-
console.log(
|
|
24731
|
+
console.log(import_picocolors14.default.bold("User-defined Providers:"));
|
|
23882
24732
|
userOnlyProviders.forEach((preset) => {
|
|
23883
24733
|
const isOverride = builtInProviderIds.has(preset.id);
|
|
23884
|
-
const marker = isOverride ?
|
|
23885
|
-
console.log(` ${
|
|
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}`);
|
|
23886
24736
|
});
|
|
23887
24737
|
}
|
|
23888
24738
|
console.log();
|
|
23889
|
-
console.log(
|
|
24739
|
+
console.log(import_picocolors14.default.dim(`Total: ${allPresets2.length} providers`));
|
|
23890
24740
|
console.log();
|
|
23891
24741
|
}
|
|
23892
24742
|
async function addProvider(options) {
|
|
@@ -23898,7 +24748,7 @@ async function addProvider(options) {
|
|
|
23898
24748
|
let models = options.models;
|
|
23899
24749
|
if (!options.quiet) {
|
|
23900
24750
|
console.log();
|
|
23901
|
-
Ie(
|
|
24751
|
+
Ie(import_picocolors14.default.cyan("Add Custom Provider"));
|
|
23902
24752
|
const existing = providerId ? await getUserProvider(providerId) : undefined;
|
|
23903
24753
|
providerId = await he({
|
|
23904
24754
|
message: "Provider ID (unique identifier, e.g., 'openrouter', 'deepseek')",
|
|
@@ -23993,7 +24843,7 @@ async function addProvider(options) {
|
|
|
23993
24843
|
try {
|
|
23994
24844
|
await upsertUserProvider(provider);
|
|
23995
24845
|
if (!options.quiet) {
|
|
23996
|
-
Se(
|
|
24846
|
+
Se(import_picocolors14.default.green(`${MARKERS.success} Provider "${providerId}" added successfully!`));
|
|
23997
24847
|
} else {
|
|
23998
24848
|
showSuccess(`Provider "${providerId}" added successfully!`, {
|
|
23999
24849
|
ID: providerId,
|
|
@@ -24012,10 +24862,10 @@ async function removeProvider(providerId, options) {
|
|
|
24012
24862
|
showError("Error: Provider ID is required", "Usage: swixter providers remove <provider-id>");
|
|
24013
24863
|
}
|
|
24014
24864
|
console.log();
|
|
24015
|
-
Ie(
|
|
24865
|
+
Ie(import_picocolors14.default.cyan("Remove Custom Provider"));
|
|
24016
24866
|
const userProviders = await loadUserProviders();
|
|
24017
24867
|
if (userProviders.length === 0) {
|
|
24018
|
-
Se(
|
|
24868
|
+
Se(import_picocolors14.default.yellow("No user-defined providers to remove"));
|
|
24019
24869
|
return;
|
|
24020
24870
|
}
|
|
24021
24871
|
providerId = await ve({
|
|
@@ -24042,7 +24892,7 @@ async function removeProvider(providerId, options) {
|
|
|
24042
24892
|
showError(`Error: Provider "${providerId}" not found`, "Use 'swixter providers list' to see all providers");
|
|
24043
24893
|
}
|
|
24044
24894
|
if (!options?.quiet) {
|
|
24045
|
-
Se(
|
|
24895
|
+
Se(import_picocolors14.default.green(`${MARKERS.success} Provider "${providerId}" removed successfully!`));
|
|
24046
24896
|
} else {
|
|
24047
24897
|
showSuccess(`Provider "${providerId}" removed successfully!`);
|
|
24048
24898
|
}
|
|
@@ -24056,19 +24906,19 @@ async function showProvider(providerId) {
|
|
|
24056
24906
|
showError(`Error: Provider "${providerId}" not found`, "Use 'swixter providers list' to see all providers");
|
|
24057
24907
|
}
|
|
24058
24908
|
console.log();
|
|
24059
|
-
Ie(
|
|
24909
|
+
Ie(import_picocolors14.default.cyan(`Provider: ${provider.displayName}`));
|
|
24060
24910
|
console.log();
|
|
24061
|
-
console.log(` ID: ${
|
|
24062
|
-
console.log(` Name: ${
|
|
24063
|
-
console.log(` Display Name: ${
|
|
24064
|
-
console.log(` Base URL: ${
|
|
24065
|
-
console.log(` Auth Type: ${
|
|
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)}`);
|
|
24066
24916
|
if (provider.defaultModels && provider.defaultModels.length > 0) {
|
|
24067
24917
|
console.log(` Default Models:`);
|
|
24068
|
-
provider.defaultModels.forEach((model) => console.log(` - ${
|
|
24918
|
+
provider.defaultModels.forEach((model) => console.log(` - ${import_picocolors14.default.dim(model)}`));
|
|
24069
24919
|
}
|
|
24070
24920
|
if (provider.docs) {
|
|
24071
|
-
console.log(` Documentation: ${
|
|
24921
|
+
console.log(` Documentation: ${import_picocolors14.default.blue(provider.docs)}`);
|
|
24072
24922
|
}
|
|
24073
24923
|
console.log();
|
|
24074
24924
|
}
|
|
@@ -24078,7 +24928,7 @@ init_meta();
|
|
|
24078
24928
|
init_versions2();
|
|
24079
24929
|
async function cmdProviders(subcommand, args) {
|
|
24080
24930
|
if (!subcommand || subcommand === "list" || subcommand === "ls") {
|
|
24081
|
-
await
|
|
24931
|
+
await listProviders2();
|
|
24082
24932
|
return;
|
|
24083
24933
|
}
|
|
24084
24934
|
if (subcommand === "add" || subcommand === "new") {
|
|
@@ -24120,104 +24970,104 @@ async function cmdProviders(subcommand, args) {
|
|
|
24120
24970
|
await showProvider(providerId);
|
|
24121
24971
|
return;
|
|
24122
24972
|
}
|
|
24123
|
-
console.log(
|
|
24973
|
+
console.log(import_picocolors15.default.red(`Unknown providers subcommand: ${subcommand}`));
|
|
24124
24974
|
console.log();
|
|
24125
|
-
console.log(
|
|
24126
|
-
console.log(` ${
|
|
24127
|
-
console.log(` ${
|
|
24128
|
-
console.log(` ${
|
|
24129
|
-
console.log(` ${
|
|
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`);
|
|
24130
24980
|
console.log();
|
|
24131
24981
|
process.exit(1);
|
|
24132
24982
|
}
|
|
24133
24983
|
async function cmdExport(filePath) {
|
|
24134
24984
|
if (!filePath) {
|
|
24135
|
-
console.log(
|
|
24136
|
-
console.log(
|
|
24985
|
+
console.log(import_picocolors15.default.red("Error: Please specify export file path"));
|
|
24986
|
+
console.log(import_picocolors15.default.dim("Usage: swixter export <file>"));
|
|
24137
24987
|
process.exit(1);
|
|
24138
24988
|
}
|
|
24139
24989
|
try {
|
|
24140
24990
|
await exportConfig(filePath, { sanitizeKeys: false });
|
|
24141
24991
|
console.log();
|
|
24142
|
-
console.log(
|
|
24143
|
-
console.log(` File: ${
|
|
24992
|
+
console.log(import_picocolors15.default.green("✓") + " Export successful!");
|
|
24993
|
+
console.log(` File: ${import_picocolors15.default.cyan(filePath)}`);
|
|
24144
24994
|
console.log();
|
|
24145
24995
|
} catch (error46) {
|
|
24146
24996
|
console.log();
|
|
24147
|
-
console.log(
|
|
24997
|
+
console.log(import_picocolors15.default.red(`✗ Export failed: ${error46}`));
|
|
24148
24998
|
console.log();
|
|
24149
24999
|
process.exit(1);
|
|
24150
25000
|
}
|
|
24151
25001
|
}
|
|
24152
25002
|
async function cmdCompletion(shell) {
|
|
24153
25003
|
if (!shell) {
|
|
24154
|
-
console.log(
|
|
25004
|
+
console.log(import_picocolors15.default.yellow("Please specify shell type"));
|
|
24155
25005
|
console.log();
|
|
24156
|
-
console.log(
|
|
24157
|
-
console.log(` ${
|
|
25006
|
+
console.log(import_picocolors15.default.bold("Usage:"));
|
|
25007
|
+
console.log(` ${import_picocolors15.default.green("swixter completion <shell>")}`);
|
|
24158
25008
|
console.log();
|
|
24159
|
-
console.log(
|
|
24160
|
-
console.log(` ${
|
|
24161
|
-
console.log(` ${
|
|
24162
|
-
console.log(` ${
|
|
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`);
|
|
24163
25013
|
console.log();
|
|
24164
|
-
console.log(
|
|
24165
|
-
console.log(` ${
|
|
24166
|
-
console.log(` ${
|
|
24167
|
-
console.log(` ${
|
|
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")}`);
|
|
24168
25018
|
process.exit(1);
|
|
24169
25019
|
}
|
|
24170
25020
|
const supportedShells = ["bash", "zsh", "fish"];
|
|
24171
25021
|
if (!supportedShells.includes(shell)) {
|
|
24172
|
-
console.log(
|
|
24173
|
-
console.log(
|
|
25022
|
+
console.log(import_picocolors15.default.red(`Unsupported shell: ${shell}`));
|
|
25023
|
+
console.log(import_picocolors15.default.dim(`Supported shells: ${supportedShells.join(", ")}`));
|
|
24174
25024
|
process.exit(1);
|
|
24175
25025
|
}
|
|
24176
25026
|
try {
|
|
24177
25027
|
const script = generateCompletion(shell);
|
|
24178
25028
|
console.log(script);
|
|
24179
25029
|
} catch (error46) {
|
|
24180
|
-
console.error(
|
|
25030
|
+
console.error(import_picocolors15.default.red("Failed to generate completion script:"), error46);
|
|
24181
25031
|
process.exit(1);
|
|
24182
25032
|
}
|
|
24183
25033
|
}
|
|
24184
25034
|
async function cmdImport(filePath) {
|
|
24185
25035
|
if (!filePath) {
|
|
24186
|
-
console.log(
|
|
24187
|
-
console.log(
|
|
25036
|
+
console.log(import_picocolors15.default.red("Error: Please specify import file path"));
|
|
25037
|
+
console.log(import_picocolors15.default.dim("Usage: swixter import <file>"));
|
|
24188
25038
|
process.exit(1);
|
|
24189
25039
|
}
|
|
24190
25040
|
try {
|
|
24191
25041
|
const result = await importConfig(filePath, { overwrite: false });
|
|
24192
25042
|
console.log();
|
|
24193
|
-
console.log(
|
|
25043
|
+
console.log(import_picocolors15.default.green("✓") + " Import completed!");
|
|
24194
25044
|
console.log();
|
|
24195
|
-
console.log(` Successfully imported: ${
|
|
24196
|
-
console.log(` Skipped: ${
|
|
24197
|
-
console.log(` Errors: ${
|
|
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`);
|
|
24198
25048
|
console.log();
|
|
24199
25049
|
if (result.errors.length > 0) {
|
|
24200
|
-
console.log(
|
|
24201
|
-
result.errors.forEach((err) => console.log(
|
|
25050
|
+
console.log(import_picocolors15.default.red("Error details:"));
|
|
25051
|
+
result.errors.forEach((err) => console.log(import_picocolors15.default.red(` - ${err}`)));
|
|
24202
25052
|
console.log();
|
|
24203
25053
|
}
|
|
24204
25054
|
} catch (error46) {
|
|
24205
25055
|
console.log();
|
|
24206
|
-
console.log(
|
|
25056
|
+
console.log(import_picocolors15.default.red(`✗ Import failed: ${error46}`));
|
|
24207
25057
|
console.log();
|
|
24208
25058
|
process.exit(1);
|
|
24209
25059
|
}
|
|
24210
25060
|
}
|
|
24211
25061
|
async function cmdVersion() {
|
|
24212
25062
|
console.log();
|
|
24213
|
-
console.log(
|
|
25063
|
+
console.log(import_picocolors15.default.bold(import_picocolors15.default.cyan("Swixter")) + import_picocolors15.default.dim(" - AI Coder Configuration Manager"));
|
|
24214
25064
|
console.log();
|
|
24215
|
-
console.log(` ${
|
|
24216
|
-
console.log(` ${
|
|
24217
|
-
console.log(` ${
|
|
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)}`);
|
|
24218
25068
|
console.log();
|
|
24219
|
-
console.log(
|
|
24220
|
-
console.log(
|
|
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"));
|
|
24221
25071
|
console.log();
|
|
24222
25072
|
}
|
|
24223
25073
|
async function main() {
|
|
@@ -24228,6 +25078,10 @@ async function main() {
|
|
|
24228
25078
|
showGlobalHelp();
|
|
24229
25079
|
return;
|
|
24230
25080
|
}
|
|
25081
|
+
if (firstArg === "ui") {
|
|
25082
|
+
await handleUiCommand(args.slice(1));
|
|
25083
|
+
return;
|
|
25084
|
+
}
|
|
24231
25085
|
if (firstArg === "claude") {
|
|
24232
25086
|
await handleClaudeCommand(args.slice(1));
|
|
24233
25087
|
return;
|
|
@@ -24260,11 +25114,11 @@ async function main() {
|
|
|
24260
25114
|
await cmdVersion();
|
|
24261
25115
|
return;
|
|
24262
25116
|
}
|
|
24263
|
-
console.log(
|
|
24264
|
-
console.log(
|
|
25117
|
+
console.log(import_picocolors15.default.red(`Unknown command: ${firstArg}`));
|
|
25118
|
+
console.log(import_picocolors15.default.dim("Run 'swixter --help' for help"));
|
|
24265
25119
|
process.exit(1);
|
|
24266
25120
|
} catch (error46) {
|
|
24267
|
-
console.error(
|
|
25121
|
+
console.error(import_picocolors15.default.red("An error occurred:"), error46);
|
|
24268
25122
|
process.exit(1);
|
|
24269
25123
|
}
|
|
24270
25124
|
}
|